Object (empty) → 1.0
raw patch · 8 files changed
+599/−0 lines, 8 filesdep +basedep +containersdep +ghcsetup-changed
Dependencies added: base, containers, ghc, template-haskell
Files
- LICENSE +201/−0
- Object.cabal +22/−0
- Object.hs +13/−0
- Object/Example.lhs +127/−0
- Object/Letters.hs +68/−0
- Object/Templates.hs +111/−0
- Object/Types.hs +55/−0
- Setup.hs +2/−0
+ LICENSE view
@@ -0,0 +1,201 @@+Apache License+ Version 2.0, January 2004+ http://www.apache.org/licenses/++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION++ 1. Definitions.++ "License" shall mean the terms and conditions for use, reproduction,+ and distribution as defined by Sections 1 through 9 of this document.++ "Licensor" shall mean the copyright owner or entity authorized by+ the copyright owner that is granting the License.++ "Legal Entity" shall mean the union of the acting entity and all+ other entities that control, are controlled by, or are under common+ control with that entity. For the purposes of this definition,+ "control" means (i) the power, direct or indirect, to cause the+ direction or management of such entity, whether by contract or+ otherwise, or (ii) ownership of fifty percent (50%) or more of the+ outstanding shares, or (iii) beneficial ownership of such entity.++ "You" (or "Your") shall mean an individual or Legal Entity+ exercising permissions granted by this License.++ "Source" form shall mean the preferred form for making modifications,+ including but not limited to software source code, documentation+ source, and configuration files.++ "Object" form shall mean any form resulting from mechanical+ transformation or translation of a Source form, including but+ not limited to compiled object code, generated documentation,+ and conversions to other media types.++ "Work" shall mean the work of authorship, whether in Source or+ Object form, made available under the License, as indicated by a+ copyright notice that is included in or attached to the work+ (an example is provided in the Appendix below).++ "Derivative Works" shall mean any work, whether in Source or Object+ form, that is based on (or derived from) the Work and for which the+ editorial revisions, annotations, elaborations, or other modifications+ represent, as a whole, an original work of authorship. For the purposes+ of this License, Derivative Works shall not include works that remain+ separable from, or merely link (or bind by name) to the interfaces of,+ the Work and Derivative Works thereof.++ "Contribution" shall mean any work of authorship, including+ the original version of the Work and any modifications or additions+ to that Work or Derivative Works thereof, that is intentionally+ submitted to Licensor for inclusion in the Work by the copyright owner+ or by an individual or Legal Entity authorized to submit on behalf of+ the copyright owner. For the purposes of this definition, "submitted"+ means any form of electronic, verbal, or written communication sent+ to the Licensor or its representatives, including but not limited to+ communication on electronic mailing lists, source code control systems,+ and issue tracking systems that are managed by, or on behalf of, the+ Licensor for the purpose of discussing and improving the Work, but+ excluding communication that is conspicuously marked or otherwise+ designated in writing by the copyright owner as "Not a Contribution."++ "Contributor" shall mean Licensor and any individual or Legal Entity+ on behalf of whom a Contribution has been received by Licensor and+ subsequently incorporated within the Work.++ 2. Grant of Copyright License. Subject to the terms and conditions of+ this License, each Contributor hereby grants to You a perpetual,+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable+ copyright license to reproduce, prepare Derivative Works of,+ publicly display, publicly perform, sublicense, and distribute the+ Work and such Derivative Works in Source or Object form.++ 3. Grant of Patent License. Subject to the terms and conditions of+ this License, each Contributor hereby grants to You a perpetual,+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable+ (except as stated in this section) patent license to make, have made,+ use, offer to sell, sell, import, and otherwise transfer the Work,+ where such license applies only to those patent claims licensable+ by such Contributor that are necessarily infringed by their+ Contribution(s) alone or by combination of their Contribution(s)+ with the Work to which such Contribution(s) was submitted. If You+ institute patent litigation against any entity (including a+ cross-claim or counterclaim in a lawsuit) alleging that the Work+ or a Contribution incorporated within the Work constitutes direct+ or contributory patent infringement, then any patent licenses+ granted to You under this License for that Work shall terminate+ as of the date such litigation is filed.++ 4. Redistribution. You may reproduce and distribute copies of the+ Work or Derivative Works thereof in any medium, with or without+ modifications, and in Source or Object form, provided that You+ meet the following conditions:++ (a) You must give any other recipients of the Work or+ Derivative Works a copy of this License; and++ (b) You must cause any modified files to carry prominent notices+ stating that You changed the files; and++ (c) You must retain, in the Source form of any Derivative Works+ that You distribute, all copyright, patent, trademark, and+ attribution notices from the Source form of the Work,+ excluding those notices that do not pertain to any part of+ the Derivative Works; and++ (d) If the Work includes a "NOTICE" text file as part of its+ distribution, then any Derivative Works that You distribute must+ include a readable copy of the attribution notices contained+ within such NOTICE file, excluding those notices that do not+ pertain to any part of the Derivative Works, in at least one+ of the following places: within a NOTICE text file distributed+ as part of the Derivative Works; within the Source form or+ documentation, if provided along with the Derivative Works; or,+ within a display generated by the Derivative Works, if and+ wherever such third-party notices normally appear. The contents+ of the NOTICE file are for informational purposes only and+ do not modify the License. You may add Your own attribution+ notices within Derivative Works that You distribute, alongside+ or as an addendum to the NOTICE text from the Work, provided+ that such additional attribution notices cannot be construed+ as modifying the License.++ You may add Your own copyright statement to Your modifications and+ may provide additional or different license terms and conditions+ for use, reproduction, or distribution of Your modifications, or+ for any such Derivative Works as a whole, provided Your use,+ reproduction, and distribution of the Work otherwise complies with+ the conditions stated in this License.++ 5. Submission of Contributions. Unless You explicitly state otherwise,+ any Contribution intentionally submitted for inclusion in the Work+ by You to the Licensor shall be under the terms and conditions of+ this License, without any additional terms or conditions.+ Notwithstanding the above, nothing herein shall supersede or modify+ the terms of any separate license agreement you may have executed+ with Licensor regarding such Contributions.++ 6. Trademarks. This License does not grant permission to use the trade+ names, trademarks, service marks, or product names of the Licensor,+ except as required for reasonable and customary use in describing the+ origin of the Work and reproducing the content of the NOTICE file.++ 7. Disclaimer of Warranty. Unless required by applicable law or+ agreed to in writing, Licensor provides the Work (and each+ Contributor provides its Contributions) on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+ implied, including, without limitation, any warranties or conditions+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+ PARTICULAR PURPOSE. You are solely responsible for determining the+ appropriateness of using or redistributing the Work and assume any+ risks associated with Your exercise of permissions under this License.++ 8. Limitation of Liability. In no event and under no legal theory,+ whether in tort (including negligence), contract, or otherwise,+ unless required by applicable law (such as deliberate and grossly+ negligent acts) or agreed to in writing, shall any Contributor be+ liable to You for damages, including any direct, indirect, special,+ incidental, or consequential damages of any character arising as a+ result of this License or out of the use or inability to use the+ Work (including but not limited to damages for loss of goodwill,+ work stoppage, computer failure or malfunction, or any and all+ other commercial damages or losses), even if such Contributor+ has been advised of the possibility of such damages.++ 9. Accepting Warranty or Additional Liability. While redistributing+ the Work or Derivative Works thereof, You may choose to offer,+ and charge a fee for, acceptance of support, warranty, indemnity,+ or other liability obligations and/or rights consistent with this+ License. However, in accepting such obligations, You may act only+ on Your own behalf and on Your sole responsibility, not on behalf+ of any other Contributor, and only if You agree to indemnify,+ defend, and hold each Contributor harmless for any liability+ incurred by, or claims asserted against, such Contributor by reason+ of your accepting any such warranty or additional liability.++ END OF TERMS AND CONDITIONS++ APPENDIX: How to apply the Apache License to your work.++ To apply the Apache License to your work, attach the following+ boilerplate notice, with the fields enclosed by brackets "{}"+ replaced with your own identifying information. (Don't include+ the brackets!) The text should be enclosed in the appropriate+ comment syntax for the file format. We also recommend that a+ file or class name and description of purpose be included on the+ same "printed page" as the copyright notice for easier+ identification within third-party archives.++ Copyright {yyyy} {name of copyright owner}++ Licensed under the Apache License, Version 2.0 (the "License");+ you may not use this file except in compliance with the License.+ You may obtain a copy of the License at++ http://www.apache.org/licenses/LICENSE-2.0++ Unless required by applicable law or agreed to in writing, software+ distributed under the License is distributed on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ See the License for the specific language governing permissions and+ limitations under the License.
+ Object.cabal view
@@ -0,0 +1,22 @@+Name: Object+Version: 1.0+Cabal-Version: >= 1.4+License: Apache-2.0+License-File: LICENSE+Author: Silvio Frischknecht+Homepage: https://github.com/yokto/object+Category: Data, Control+Maintainer: yokto.reports@gmail.com+Synopsis: Object oriented programming for haskell using multiparameter typeclasses.+Description: Read the homepage or Object.Example for more information.+Build-Type: Simple++Library+ Build-Depends: base >= 3 && < 5, ghc >= 7.8, template-haskell, containers+ Exposed-modules:+ Object,+ Object.Types,+ Object.Templates,+ Object.Example,+ Object.Letters+ Extensions:
+ Object.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}+-- | This module Just reexports Object.Types and Object.Templates+module Object(+ module Object.Types,+ module Object.Templates+ ) where++import Object.Types+import Object.Templates++type instance Output (b -> c) (a -> b') = (a -> c)+instance (b ~ b') => Action (b -> c) (a -> b') where+ f . g = f Prelude.. g
+ Object/Example.lhs view
@@ -0,0 +1,127 @@+>{-# LANGUAGE TemplateHaskell, FlexibleInstances, TypeOperators, DataKinds, DeriveGeneric, MultiParamTypeClasses, FlexibleContexts, TypeFamilies, DataKinds, UndecidableInstances, OverlappingInstances #-}+>module Object.Example where++>import Object.Templates+>import Object.Types+>import Object.Letters++>import Prelude hiding ((.))+>import Data.Maybe+>import qualified Data.Map as Map+>import Data.Map (Map)++In this example file we will see how to make objects+out of two data type 'Simple' and 'Foo x'++>data Simple = Simple { _simple :: Int } deriving (Show)++>data Foo x = Foo {+> _bar ::Int,+> _baz :: Char,+> _blub :: x+> } deriving (Show)++To make 'Foo x' we use templateHaskell.++>makeObject ''Foo++Poof, and we're done.+For 'Simple' we will do everything manually so you can see what happenes behind 'makeObject'.+We will want to make instances of the following two things that are defined in Object.Types.++type family Output object action++class Action object action where+ (.) :: object -> action -> Output object action++Now 'makeObject' makes two types of 'Actions' actions called methods+(where action has type 'Method m' for some m) and actions called methodsets+(where action has type 'Method m := input).++Unless you want to use a closed type class later the following definition would not be neccessary.+So if you are new you can imagine 'Output' and 'MethodOutput' are the same thing. For the pros+the following two lines are not defined if you use 'makeObjectFlexible'.++>type instance Output Simple (Method m) = MethodOutput Simple (Method m)+>type instance Output Simple (Method m := input) = MethodOutput Simple (Method m := input)++First we need a method name for '_simple'++>type Simple_ = Method (T_s,T_i,T_m,T_p,T_l,T_e)+>simple = Method (T_s,T_i,T_m,T_p,T_l,T_e) :: Simple_++it is done this way so different modules can define the same name+you can use the macro makeName to produce the same thing.++So now we can implement a method we only need to make an instance of 'Action' and 'Output' or+since 'Output' was defered of 'MethodOutput'++the output will be an Int since _simple has type Int.++>type instance MethodOutput Simple Simple_ = Int++and the implementation will simply be a call to '_simple'++>instance Action Simple Simple_ where+> object . _ = _simple object++we can ignore the argument since we know it from the type++Now we can also make the methodset++>type instance MethodOutput Simple (Simple_ := anything) = Simple+>instance (anything ~ Int) => Action Simple (Simple_ := anything) where+> object . (_ := int) = object { _simple = int }++Notice how we match anything and only in the context make sure that it is in deed Int.+This is because other wise GHC would give some ambiguity error since someone else could+possibly add an instance++instance Action Simple (Simple_ := Float)++So let's see what we can do so far.++>fooAndSimple = do+> print$ Foo 1 'a' 1 . blub := 2 . blub -- 2+> print$ Simple 1 . simple -- 1++Pretty cool. Ok now something a bit more complicated for 'Data.Map'.++>type instance Output (Map k v) action = OutputMap (Map k v) action++>type family OutputMap map action where+> OutputMap (Map k v) (Method m) = MethodOutput (Map k v) (Method m)+> OutputMap (Map k v) [k' := v'] = (Map k v)+> OutputMap (Map k v) (k' := v') = (Map k v)+> OutputMap (Map k v) (Maybe k') = Maybe v+> OutputMap (Map k v) [k'] = [v]+> OutputMap (Map k v) k' = v++>makeName "size"+>type instance MethodOutput (Map k v) Size_ = Int+>instance Action (Map k v) Size_ where+> obj . _ = Map.size obj++>instance (k~k', v~v', OutputMap (Map k v) [k' := v'] ~ (Map k v), Ord k) => Action (Map k v) [k' := v'] where+> map . (k := v:rest) = Map.insert k v map . rest+> map . [] = map++>instance (k~k', v~v', OutputMap (Map k v) (k' := v') ~ (Map k v), Ord k) => Action (Map k v) (k' := v') where+> map . assign = map . [assign]++>instance (k~k', OutputMap (Map k v) (Maybe k') ~ (Maybe v), Ord k) => Action (Map k v) (Maybe k') where+> map . (Just key) = Map.lookup key map+> map . Nothing = Nothing++>instance (k~k', OutputMap (Map k v) [k'] ~ [v], Ord k) => Action (Map k v) [k'] where+> map . keys = catMaybes $ flip Map.lookup map <* keys++>instance (k~k', OutputMap (Map k v) k' ~ v, Ord k) => Action (Map k v) k' where+> map . key = fromMaybe (error "no element of this key in map") $ map . Just key++>mapExample = do+> let aMap = Map.empty . ['a' := "first_a", 'b' := "first_b"]+> print$ aMap . ('a' := "secont_a") . 'a' -- "second_a+> print$ aMap . ['a','b','c'] -- ["first_a","first_b"]+> print$ aMap . size -- 2+> print$ Map.empty . [(1::Int) := "hallo" ] . (1::Int) -- "hallo"
+ Object/Letters.hs view
@@ -0,0 +1,68 @@+module Object.Letters where++newtype Method a = Method a deriving (Show,Read,Eq)++data T_a = T_a deriving (Show, Read, Eq)+data T_b = T_b deriving (Show, Read, Eq)+data T_c = T_c deriving (Show, Read, Eq)+data T_d = T_d deriving (Show, Read, Eq)+data T_e = T_e deriving (Show, Read, Eq)+data T_f = T_f deriving (Show, Read, Eq)+data T_g = T_g deriving (Show, Read, Eq)+data T_h = T_h deriving (Show, Read, Eq)+data T_i = T_i deriving (Show, Read, Eq)+data T_j = T_j deriving (Show, Read, Eq)+data T_k = T_k deriving (Show, Read, Eq)+data T_l = T_l deriving (Show, Read, Eq)+data T_m = T_m deriving (Show, Read, Eq)+data T_n = T_n deriving (Show, Read, Eq)+data T_o = T_o deriving (Show, Read, Eq)+data T_p = T_p deriving (Show, Read, Eq)+data T_q = T_q deriving (Show, Read, Eq)+data T_r = T_r deriving (Show, Read, Eq)+data T_s = T_s deriving (Show, Read, Eq)+data T_t = T_t deriving (Show, Read, Eq)+data T_u = T_u deriving (Show, Read, Eq)+data T_v = T_v deriving (Show, Read, Eq)+data T_w = T_w deriving (Show, Read, Eq)+data T_x = T_x deriving (Show, Read, Eq)+data T_y = T_y deriving (Show, Read, Eq)+data T_z = T_z deriving (Show, Read, Eq)+data T_A = T_A deriving (Show, Read, Eq)+data T_B = T_B deriving (Show, Read, Eq)+data T_C = T_C deriving (Show, Read, Eq)+data T_D = T_D deriving (Show, Read, Eq)+data T_E = T_E deriving (Show, Read, Eq)+data T_F = T_F deriving (Show, Read, Eq)+data T_G = T_G deriving (Show, Read, Eq)+data T_H = T_H deriving (Show, Read, Eq)+data T_I = T_I deriving (Show, Read, Eq)+data T_J = T_J deriving (Show, Read, Eq)+data T_K = T_K deriving (Show, Read, Eq)+data T_L = T_L deriving (Show, Read, Eq)+data T_M = T_M deriving (Show, Read, Eq)+data T_N = T_N deriving (Show, Read, Eq)+data T_O = T_O deriving (Show, Read, Eq)+data T_P = T_P deriving (Show, Read, Eq)+data T_Q = T_Q deriving (Show, Read, Eq)+data T_R = T_R deriving (Show, Read, Eq)+data T_S = T_S deriving (Show, Read, Eq)+data T_T = T_T deriving (Show, Read, Eq)+data T_U = T_U deriving (Show, Read, Eq)+data T_V = T_V deriving (Show, Read, Eq)+data T_W = T_W deriving (Show, Read, Eq)+data T_X = T_X deriving (Show, Read, Eq)+data T_Y = T_Y deriving (Show, Read, Eq)+data T_Z = T_Z deriving (Show, Read, Eq)+data T_0 = T_0 deriving (Show, Read, Eq)+data T_1 = T_1 deriving (Show, Read, Eq)+data T_2 = T_2 deriving (Show, Read, Eq)+data T_3 = T_3 deriving (Show, Read, Eq)+data T_4 = T_4 deriving (Show, Read, Eq)+data T_5 = T_5 deriving (Show, Read, Eq)+data T_6 = T_6 deriving (Show, Read, Eq)+data T_7 = T_7 deriving (Show, Read, Eq)+data T_8 = T_8 deriving (Show, Read, Eq)+data T_9 = T_9 deriving (Show, Read, Eq)+data T__ = T__ deriving (Show, Read, Eq)+data T_' = T_' deriving (Show, Read, Eq)
+ Object/Templates.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE TemplateHaskell, MultiParamTypeClasses, TypeFamilies, FlexibleInstances, OverlappingInstances, TypeOperators, PatternGuards #-}+module Object.Templates(+ makeName,+ makeObject,+ makeObjectFlexible+ ) where++import Object.Letters+import Object.Types++import Prelude hiding ((.))+import Language.Haskell.TH+import Language.Haskell.TH.Syntax+import Data.Char+import Data.Maybe++-- |+-- takes lower case 'foo' and makes+-- 'type Foo = Method (T_f,T_o,T_o)'+-- 'foo = Method (T_f,T_o,T_o) :: Foo'+makeName :: String -> Q [Dec]+makeName name = makeName' name *> fst++makeName' :: String -> Q ([Dec],(Name,Name))+makeName' name = go where+ go+ | [] <- name = fail "can't make empty variable"+ | not $ isLower $ head name = fail $ name ++ ": does not start with a lower letter"+ | (first:rest) <- name = do+ typeTuple <- mapM typeCon name+ dataTuple <- mapM dataCon name+ typeName <- newName $ [toUpper first] ++ rest ++ ['_']+ dataName <- newName $ [first] ++ rest+ typ <- [t| Method $(return $ foldl AppT (TupleT (length typeTuple)) typeTuple) |]+ dat <- [| Method $(return $ (TupE dataTuple)) :: $(return $ ConT typeName) |]+ let typeDecl = TySynD typeName [] typ+ let dataDecl = ValD (VarP dataName) (NormalB dat) []+ return ([typeDecl,dataDecl],(typeName,dataName))+ typeCon c = do+ Just res <- lookupTypeName $ "T_" ++ [c] + return $ ConT res+ dataCon c = do+ Just res <- lookupValueName $ "T_" ++ [c] + return $ ConE res++-- |+-- returns (typeName, variableNames, and fields)+getInfo :: Info -> Q (Name, [Name], [VarStrictType])+getInfo (TyConI (DataD context typeName vars [RecC constrName fields] _)) = go where+ go = return (typeName, map getVar vars, fields)+ getVar (PlainTV n) = n+ getVar (KindedTV n _) = n+getInfo _ = fail $ "type needs to have a single constructor record type"++getFieldName (fieldName,strictness,type')+ | nameBase fieldName !! 0 /= '_' || not (isLower $ nameBase fieldName !! 1)+ = fail $ show fieldName +++ ": all fieldNames must commence with a '_' \+ \and continue with a lower case letter"+ | otherwise = nameBase fieldName++-- |+-- takes a Type with one record constructor+-- 'setGetFunctional \'\'Foo'+-- and produces+-- set and get instances for all fields+makeObject :: Name -> Q [Dec]+makeObject = makeObject' False++makeObjectFlexible = makeObject' True++-- |+-- implements 'makeObject' or 'makeObjectFlexible' depending on the first argument+makeObject' :: Bool -> Name -> Q [Dec]+makeObject' flexible name = go name where+ go :: Name -> Q [Dec]+ go obj = do+ (name, vars, fields) <- reify name >>= getInfo+ let objType = foldl AppT (ConT name) (VarT<*vars)+ outputDecls <- if flexible+ then return []+ else [d|+ type instance Output $(return objType) (Method m) =+ MethodOutput $(return objType) (Method m)+ type instance Output $(return objType) (Method m := input) =+ MethodOutput $(return objType) (Method m := input)+ |]+ fieldDecls <- (sequence $ makeField name vars <* fields) *> concat+ return $ outputDecls ++ fieldDecls+-- "(Object.Example.Foo,[x_1627454179],[(Object.Example._bar,NotStrict,ConT GHC.Types.Int),(Object.Example._baz,NotStrict,ConT GHC.Types.Char),(Object.Example._blub,NotStrict,VarT x_1627454179)])"+ makeField :: Name -> [Name] -> VarStrictType -> Q [Dec]+ makeField _ _ (name,_,_) | '_' /= head (nameBase name) = fail $ show name ++ " did not start with underscore"+ makeField name vars (fName, _, fType) = do+ (decs1,(typeName,dataName)) <- makeName' (tail $ nameBase fName)+ methodOutput <- lookupTypeName "Object.Types.MethodOutput" *> fromMaybe (error "no MethodOutput in scope")+ let objType = foldl AppT (ConT name) (VarT<*vars)++ let methodOutInst = TySynInstD methodOutput $ TySynEqn [objType, ConT typeName] fType+ actionInst <- [d|+ instance Action $(return objType) $(return $ ConT typeName) where+ object . _ = $(return $ VarE fName) object+ |]++ matchType <- [t| $(return $ ConT typeName) := $(return $ VarT $ mkName "value") |]+ let methodSetOutInst = TySynInstD methodOutput $ TySynEqn [objType, matchType] objType+ actionSetInst <- [d|+ instance (value ~ $(return fType)) => Action $(return objType) $(return matchType) where+ object . ( _ := v) = $(recUpdE [e|object|] [return (fName, VarE $ mkName "v")])+ |]++ return $ [methodOutInst,methodSetOutInst] ++ actionInst ++ actionSetInst ++ decs1
+ Object/Types.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, TypeOperators #-}+module Object.Types where++import Prelude hiding ((.))+import Control.Applicative+import Control.Monad++type family Output object action++class Action object action where+ (.) :: object -> action -> Output object action++data a := b = a := b deriving (Show,Read,Eq)++type family MethodOutput object method++(%) = flip ($)+a ... b = \x -> a (b x)++-- |+-- Explanation of all these operators.+-- They are basically an assortment of 'Functor' and+-- 'Applicative' functions. I.e.,+-- '[1,2,3] *> (+1)' === map (+1) [1,2,3]'+-- The asterisk '*' indicates where the 'Functor', 'Applicative' is.+-- And the greather than (smaller than) indicates in which direction+-- the argument is going. So you could also have+-- '[(+1),(+2),(+3)] *< 1 === map ($ 1) [(+1),(+2),(+3)]'.+-- If there are asterisks on both sides the 'Functor' has to be 'Applicative'+a *> b = fmap (%b) a+a *< b = fmap ($ b) a -- space is in case of TH+a *. b = fmap (.b) a+a >* b = fmap (a%) b+a <* b = fmap (a$) b+a .* b = fmap (a.) b+a *>* b = (%) <$> (a) <*> b+a *<* b = ($) <$> a <*> b+a *.* b = (.) <$> a <*> b+++infixl 8 .+infixl 9 :=+infixl 0 %++infixl 4 *.+infixl 4 .*+infixl 4 *.*++infixl 4 *>+infixl 4 >*+infixl 4 *>*++infixr 4 *<+infixr 4 <*+infixr 4 *<*
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain