diff --git a/polyplate/Data/Generics/Polyplate.hs b/polyplate/Data/Generics/Polyplate.hs index c7ecea9..ac82d37 100644 --- a/polyplate/Data/Generics/Polyplate.hs +++ b/polyplate/Data/Generics/Polyplate.hs @@ -128,7 +128,8 @@ module Data.Generics.Polyplate (PolyplateMRoute(..), PolyplateM(..), Polyplate(. makeDescendM, DescendM, makeDescend, Descend, -- makeRecurseQ, RecurseQ, -- makeDescendQ, DescendQ, - BaseOp, baseOp, + BaseOp(..), BaseOpM(..), BaseOpMRoute(..), baseOp, baseOpM, baseOpM', baseOpMRoute, + (:-)(..), (:-*)(..), (:-@)(..), ExtOpM, extOpM, ExtOpMRoute, extOpMRoute, ExtOp, extOp, OneOpMRoute, OneOpM, OneOp, TwoOpM, TwoOp ) where @@ -178,7 +179,7 @@ import Data.Generics.Polyplate.Route -- Generally you will not use this function or type-class directly, but will instead -- use the helper functions lower down in this module. class Monad m => PolyplateMRoute t o o' m outer where - transformMRoute :: o -> o' -> (t, Route t outer) -> m t + transformMRoute :: o m outer -> o' m outer -> (t, Route t outer) -> m t -- | A derivative of PolyplateMRoute without all the route stuff. -- @@ -217,7 +218,7 @@ class Monad m => PolyplateMRoute t o o' m outer where -- Generally you will not use this function or type-class directly, but will instead -- use the helper functions lower down in this module. class (Monad m) => PolyplateM t o o' m where - transformM :: o -> o' -> t -> m t + transformM :: o m -> o' m -> t -> m t instance (Monad m @@ -242,25 +243,25 @@ instance (PolyplateM t mo mo' Identity, ConvertOpsToIdentity o mo, ConvertOpsToI -- | A type representing a monadic modifier function that applies the given ops -- (opT) in the given monad (m) directly to the given type (t). -type RecurseM m opT = forall t. PolyplateM t opT () m => t -> m t +type RecurseM m opT = forall t. PolyplateM t opT BaseOpM m => t -> m t -- | Given a set of operations (as described in the 'PolyplateM' type-class), -- makes a recursive modifier function. -makeRecurseM :: Monad m => opT -> RecurseM m opT -makeRecurseM ops = transformM ops () +makeRecurseM :: Monad m => opT m -> RecurseM m opT +makeRecurseM ops = transformM ops baseOpM -- | A type representing a monadic modifier function that applies the given ops -- (opT) in the given monad (m) to the children of the given type (t). -type DescendM m opT = forall t. PolyplateM t () opT m => t -> m t +type DescendM m opT = forall t. PolyplateM t BaseOpM opT m => t -> m t -- | Given a set of operations (as described in the 'PolyplateM' type-class), -- makes a descent modifier function that applies the operation to the type's children. -makeDescendM :: Monad m => opT -> DescendM m opT -makeDescendM ops = transformM () ops +makeDescendM :: Monad m => opT m -> DescendM m opT +makeDescendM ops = transformM baseOpM ops -- | A type representing a modifier function that applies the given ops -- (opT) directly to the given type (t). -type Recurse opT = forall t. Polyplate t opT () => t -> t +type Recurse opT = forall t. Polyplate t opT BaseOp => t -> t -- | Given a set of operations (as described in the 'Polyplate' type-class), -- makes a modifier function that applies the operations directly. @@ -296,48 +297,72 @@ type BaseOp = () baseOp :: BaseOp baseOp = () +baseOpM :: BaseOpM m +baseOpM = BaseOpM + +baseOpM' :: (a -> m a) -> BaseOpM m +baseOpM' = const BaseOpM + +baseOpMRoute :: BaseOpMRoute m outer +baseOpMRoute = BaseOpMRoute + -- | The type that extends an ops set (opT) in the given monad (m) to be applied to -- the given type (t). You cannot mix monadic and non-monadic operations in the -- same list. This is for use with the 'PolyplateM' class. -type ExtOpM m opT t = (t -> m t, opT) +--data ((t :: *) :-* (opT :: (* -> *) -> *)) m = (t -> m t) :-* (opT m) +data (t :-* opT) m = (t -> m t) :-* (opT m) +--data E t (opT :: (* -> *) -> *) m = (:-*) (t -> m t) (opT m) + +infixr 7 :-* + +type ExtOpM m opT t = (t :-* opT) m + +data BaseOpM m = BaseOpM + +data (t :-@ opT) m outer = ((t, Route t outer) -> m t) :-@ (opT m outer) + +data BaseOpMRoute m outer = BaseOpMRoute -- | The type that extends an ops set (opT) in the given monad (m) to be applied -- to the given type (t) with routes to the outer type (outer). This is for use -- with the 'PolyplateMRoute' class. -type ExtOpMRoute m opT t outer = ((t, Route t outer) -> m t, opT) +type ExtOpMRoute m opT t outer = (t :-@ opT) m outer +--((t, Route t outer) -> m t, opT) -- | The type that extends an ops set (opT) to be applied to the given type (t). -- You cannot mix monadic and non-monadic operations in the same list. This is -- for use with the 'Polyplate' class. -type ExtOp opT t = (t -> t, opT) +data t :- opT = (t -> t) :- opT + +type ExtOp opT t = t :- opT -- | The function that extends an ops set (opT) in the given monad (m) to be applied to -- the given type (t). You cannot mix monadic and non-monadic operations in the -- same list. This is for use with the 'PolyplateM' class. -extOpM :: opT -> (t -> m t) -> ExtOpM m opT t -extOpM ops f = (f, ops) +extOpM :: opT m -> (t -> m t) -> ExtOpM m opT t +extOpM ops f = f :-* ops -- | The function that extends an ops set (opT) in the given monad (m) to be applied -- to the given type (t) with routes to the outer type (outer). This is for use -- with the 'PolyplateMRoute' class. -extOpMRoute :: opT -> ((t, Route t outer) -> m t) -> ExtOpMRoute m opT t outer -extOpMRoute ops f = (f, ops) +extOpMRoute :: opT m outer -> ((t, Route t outer) -> m t) -> ExtOpMRoute m opT t outer +extOpMRoute ops f = f :-@ ops -- | The function that extends an ops set (opT) in the given monad (m) to be applied to -- the given type (t). You cannot mix monadic and non-monadic operations in the -- same list. This is for use with the 'Polyplate' class. extOp :: opT -> (t -> t) -> ExtOp opT t -extOp ops f = (f, ops) +extOp ops f = f :- ops -- | A handy synonym for a monadic ops set with only one item, to use with 'PolyplateMRoute'. -type OneOpMRoute m t outer = ExtOpMRoute m BaseOp t outer +type OneOpMRoute t = t :-@ BaseOpMRoute -- | A handy synonym for a monadic ops set with only one item, to use with 'PolyplateM'. -type OneOpM m t = ExtOpM m BaseOp t +type OneOpM t = t :-* BaseOpM -- | A handy synonym for an ops set with only one item, to use with 'Polyplate'. type OneOp t = ExtOp BaseOp t -- | A handy synonym for a monadic ops set with only two items, to use with 'PolyplateM'. -type TwoOpM m s t = ExtOpM m (ExtOpM m BaseOp s) t +type TwoOpM s t = (s :-* t :-* BaseOpM) --ExtOpM m (ExtOpM m BaseOpM s) t -- | A handy synonym for an ops set with only two items, to use with 'Polyplate'. type TwoOp s t = ExtOp (ExtOp BaseOp s) t @@ -347,13 +372,13 @@ type TwoOp s t = ExtOp (ExtOp BaseOp s) t -- | A helper class to convert non-monadic transformations into monadic ones in -- the Identity monad. class ConvertOpsToIdentity o o' | o -> o' where - convertOpsToIdentity :: o -> o' + convertOpsToIdentity :: o -> o' Identity -instance ConvertOpsToIdentity () () where - convertOpsToIdentity = id +instance ConvertOpsToIdentity BaseOp BaseOpM where + convertOpsToIdentity = const baseOpM -instance ConvertOpsToIdentity r r' => ConvertOpsToIdentity (a -> a, r) (a -> Identity a, r') where - convertOpsToIdentity (f, r) = (return . f, convertOpsToIdentity r) +instance ConvertOpsToIdentity r r' => ConvertOpsToIdentity (a :- r) (a :-* r') where + convertOpsToIdentity (f :- r) = (return . f) :-* (convertOpsToIdentity r) {- -- | A helper class to convert operation lists to have FullSpine at their base @@ -371,14 +396,18 @@ instance ConvertSpineOpsToFull b r r' => ConvertSpineOpsToFull b (a, r) (a, r') -- | A helper class to convert operations not expecting a route to those that ignore -- the route (which will have the unit type as its outer type). class ConvertOpsToIgnoreRoute o o' | o -> o' where - convertOpsToIgnoreRoute :: o -> o' + convertOpsToIgnoreRoute :: Monad m => o m -> o' m () -instance ConvertOpsToIgnoreRoute () () where - convertOpsToIgnoreRoute = id +instance ConvertOpsToIgnoreRoute BaseOpM BaseOpMRoute where + convertOpsToIgnoreRoute = const baseOpMRoute instance ConvertOpsToIgnoreRoute r r' => - ConvertOpsToIgnoreRoute (t -> m t, r) ((t, Route t ()) -> m t, r') where - convertOpsToIgnoreRoute (f, r) = (f . fst, convertOpsToIgnoreRoute r) - + ConvertOpsToIgnoreRoute (t :-* r) (t :-@ r') where + convertOpsToIgnoreRoute (f :-* r) = (f . fst) :-@ (convertOpsToIgnoreRoute r) +{- +instance ConvertOpsToIgnoreRoute (r m) (r' m ()) => + ConvertOpsToIgnoreRoute ((t :-* r) m) ((t :-@ r') m ()) where + convertOpsToIgnoreRoute (f :-* r) = (f . fst) :-@ (convertOpsToIgnoreRoute r) +-} -- }}} diff --git a/polyplate/Data/Generics/Polyplate/GenInstances.hs b/polyplate/Data/Generics/Polyplate/GenInstances.hs index 3b4cc44..fe62d03 100644 --- a/polyplate/Data/Generics/Polyplate/GenInstances.hs +++ b/polyplate/Data/Generics/Polyplate/GenInstances.hs @@ -129,13 +129,13 @@ genMapInstance k v modify (Map.insert tk (show $ typeOf m, Detailed (DataBox m) [DataBox (k, v), DataBox k, DataBox v] (\(funcSameType, funcNewType) -> - [funcSameType ++ " () ops (v, r) = let mns = zip (Map.toList v) (map ((r @->) . routeDataMap) [0..]) in" - ," do m <- mapM (" ++ funcNewType ++ " ops ()) mns" + [funcSameType ++ " _ ops (v, r) = let mns = zip (Map.toList v) (map ((r @->) . routeDataMap) [0..]) in" + ," do m <- mapM (" ++ funcNewType ++ " ops BaseOpMRoute) mns" ," return (Map.fromList m)" ]) (\(funcSameType, funcNewType) -> - [funcSameType ++ " () ops q v = Node q (map (" - ++ funcNewType ++ " ops () Nothing) (Map.toList v))" + [funcSameType ++ " _ ops q v = Node q (map (" + ++ funcNewType ++ " ops BaseOpMRoute Nothing) (Map.toList v))" ]) )) where @@ -153,13 +153,13 @@ genSetInstance x modify (Map.insert tk (show $ typeOf s, Detailed (DataBox s) [DataBox x] (\(funcSameType, funcNewType) -> - [funcSameType ++ " () ops (v, r) = let sns = zip (Set.toList v) (map ((r @->) . routeDataSet) [0..]) in" - ," do s <- mapM (" ++ funcNewType ++ " ops ()) sns" + [funcSameType ++ " _ ops (v, r) = let sns = zip (Set.toList v) (map ((r @->) . routeDataSet) [0..]) in" + ," do s <- mapM (" ++ funcNewType ++ " ops BaseOpMRoute) sns" ," return (Set.fromList s)" ]) (\(funcSameType, funcNewType) -> - [funcSameType ++ " () ops q v = Node q (map (" - ++ funcNewType ++ " ops () Nothing) (Set.toList v))" + [funcSameType ++ " _ ops q v = Node q (map (" + ++ funcNewType ++ " ops BaseOpMRoute Nothing) (Set.toList v))" ]) )) where @@ -347,23 +347,23 @@ instancesFrom genOverlapped genClass boxes w baseInst :: Maybe ([DataBox], (String, String) -> [String]) -> [String] baseInst mdoChildren = concat - [genInst context "()" "(f, ops)" $ + [genInst context "BaseOpMRoute" "(f :-@ ops)" $ maybe (if isAlgType wDType -- An algebraic type: apply to each child if we're following. then (concatMap constrCase wCtrs) -- A primitive (or non-represented) type: just return it. - else [funcSameType ++ " () _ (v,_) = return v"]) + else [funcSameType ++ " _ _ (v, _) = return v"]) (\(_,f) -> f (funcSameType, funcNewType)) mdoChildren - ,genInst [] "()" "()" [funcSameType ++ " () () (v,_) = return v"] + ,genInst [] "BaseOpMRoute" "BaseOpMRoute" [funcSameType ++ " _ _ (v, _) = return v"] ,if genOverlapped == GenWithoutOverlapped then [] else genInst [ contextSameType "r" "ops" ] - "((a, Route a outer) -> m a, r)" "ops" - [funcSameType ++ " (_, rest) ops vr = " ++ funcSameType ++ " rest ops vr"] + "(a :-@ r)" "ops" + [funcSameType ++ " (_ :-@ rest) ops vr = " ++ funcSameType ++ " rest ops vr"] ,if genClass == GenClassPerType then ["class Monad m => PolyplateMRoute" ++ wMunged ++ " o o' m outer where" - ," " ++ funcSameType ++ " :: o -> o' -> (" ++ wName + ," " ++ funcSameType ++ " :: o m outer -> o' m outer -> (" ++ wName ++ ", Route (" ++ wName ++ ") outer) -> m (" ++ wName ++ ")" ,"" ,"instance (Monad m, " ++ contextSameType "o0" "o1" ++ ") =>" @@ -378,7 +378,7 @@ instancesFrom genOverlapped genClass boxes w -- this type, so we can recurse into them. context :: [String] context - = [ contextNewType argType "(f,ops)" "()" + = [ contextNewType argType "(f :-@ ops)" "BaseOpMRoute" | argType <- nub $ sort $ concatMap ctrArgTypes $ maybe (map ctrArgs wCtrs) ((:[]) . fst) mdoChildren] @@ -387,11 +387,11 @@ instancesFrom genOverlapped genClass boxes w -- then stick it back together. constrCase :: Constr -> [String] constrCase ctr - = [ funcSameType ++ " () " ++ (if argNums == [] then "_" else "ops") ++ - " (" ++ ctrInput ++ ", " ++ (if argNums == [] then "_" else "rt") ++ ")" + = [ funcSameType ++ " _ " ++ (if argNums == [] then "_" else "ops") ++ + " (" ++ ctrInput ++ " , " ++ (if argNums == [] then "_" else "rt") ++ ")" , " = do" ] ++ - [ " r" ++ show i ++ " <- " ++ funcNewType ++ " ops () (a" ++ show i + [ " r" ++ show i ++ " <- " ++ funcNewType ++ " ops BaseOpMRoute (a" ++ show i ++ ", rt @-> makeRoute [" ++ show i ++ "] " ++ "(\\f (" ++ ctrMod ++ ") -> f b" ++ show i ++ " >>= (\\b" ++ show i ++ " -> return (" ++ ctrMod ++ "))))" @@ -414,7 +414,7 @@ instancesFrom genOverlapped genClass boxes w otherInst wKey containedKeys c cKey = if not shouldGen then [] else genInst context - ("((" ++ cName ++ ", Route (" ++ cName ++ ") outer) -> m (" ++ cName ++ "), r)") + ("((" ++ cName ++ ") :-@ r)") "ops" impl where @@ -424,19 +424,19 @@ instancesFrom genOverlapped genClass boxes w | wKey == cKey = (True ,[] - ,[funcSameType ++ " (f, _) _ vr = f vr"]) + ,[funcSameType ++ " (f :-@ _) _ vr = f vr"]) -- This type might contain the type that the transformation acts -- upon | cKey `Set.member` containedKeys = (True - ,[contextSameType "r" ("((" ++ cName ++ ", Route (" ++ cName ++ ") outer) -> m (" ++ cName ++ "), ops)")] - ,[funcSameType ++ " (f, rest) ops vr = " ++ funcSameType ++ " rest (f, ops) vr"]) + ,[contextSameType "r" ("((" ++ cName ++ ") :-@ ops)")] + ,[funcSameType ++ " (f :-@ rest) ops vr = " ++ funcSameType ++ " rest (f :-@ ops) vr"]) -- This type can't contain the transformed type; just move on to the -- next transformation. | genOverlapped == GenWithoutOverlapped = (True ,[contextSameType "r" "ops"] - ,[funcSameType ++ " (_, rest) ops vr = " ++ funcSameType ++ " rest ops vr"]) + ,[funcSameType ++ " (_ :-@ rest) ops vr = " ++ funcSameType ++ " rest ops vr"]) -- This is covered by one big overlapping instance: | otherwise = (False,[],[]) diff --git a/polyplate/Data/Generics/Polyplate/Schemes.hs b/polyplate/Data/Generics/Polyplate/Schemes.hs index e9581a5..58ac9ad 100644 --- a/polyplate/Data/Generics/Polyplate/Schemes.hs +++ b/polyplate/Data/Generics/Polyplate/Schemes.hs @@ -30,22 +30,25 @@ import Data.Generics.Polyplate.Route -- function to first descend into the value before then applying the modifier function. -- This can be used to perform a bottom-up depth-first traversal of a structure -- (see 'applyBottomUp'). -makeBottomUp :: Polyplate t () opT => opT -> (t -> t) -> t -> t +makeBottomUp :: Polyplate t BaseOp opT => opT -> (t -> t) -> t -> t makeBottomUp ops f v = f (makeDescend ops v) -- | Given a list of operations and a monadic modifier function, augments that modifier -- function to first descend into the value before then applying the modifier function. -- This can be used to perform a bottom-up depth-first traversal of a structure -- (see 'applyBottomUpM'). -makeBottomUpM :: PolyplateM t () opT m => opT -> (t -> m t) -> t -> m t +makeBottomUpM :: PolyplateM t BaseOpM opT m => opT m -> (t -> m t) -> t -> m t makeBottomUpM ops f v = makeDescendM ops v >>= f -- | As makeBottomUpM, but with routes as well. -makeBottomUpMRoute :: PolyplateMRoute t () opT m outer => - opT -> ((t, Route t outer) -> m t) -> (t, Route t outer) -> m t +makeBottomUpMRoute :: forall m opT t outer. PolyplateMRoute t BaseOpMRoute opT m outer => + opT m outer -> ((t, Route t outer) -> m t) -> (t, Route t outer) -> m t makeBottomUpMRoute ops f (v, r) - = do v' <- transformMRoute () ops (v, r) + = do v' <- transformMRoute base ops (v, r) f (v', r) + where + base :: BaseOpMRoute m outer + base = baseOpMRoute -- | Given a list of operations and a modifier function, augments that modifier -- function to first apply the modifier function before then descending into the value. @@ -58,15 +61,15 @@ makeTopDown ops f v = makeDescend ops (f v) -- function to first apply the modifier function before then descending into the value. -- This can be used to perform a top-down depth-first traversal of a structure -- (see 'applyTopDownM'). -makeTopDownM :: PolyplateM t () opT m => opT -> (t -> m t) -> t -> m t +makeTopDownM :: PolyplateM t BaseOpM opT m => opT m -> (t -> m t) -> t -> m t makeTopDownM ops f v = f v >>= makeDescendM ops -- | As makeTopDownM, but with routes as well. -makeTopDownMRoute :: PolyplateMRoute t () opT m outer => - opT -> ((t, Route t outer) -> m t) -> (t, Route t outer) -> m t +makeTopDownMRoute :: PolyplateMRoute t BaseOpMRoute opT m outer => + opT m outer -> ((t, Route t outer) -> m t) -> (t, Route t outer) -> m t makeTopDownMRoute ops f (v, r) = do v' <- f (v, r) - transformMRoute () ops (v', r) + transformMRoute baseOpMRoute ops (v', r) @@ -86,8 +89,8 @@ makeCheckM ops f v -- the item in the list, False to drop it), finds all items of type \"s\" in some -- larger item (of type \"t\") that satisfy this function, listed in depth-first -- order. -listifyDepth :: (PolyplateM t (OneOpM (State [s]) s) () (State [s]) - ,PolyplateM s () (OneOpM (State [s]) s) (State [s])) => (s -> Bool) -> t -> [s] +listifyDepth :: (PolyplateM t (OneOpM s) BaseOpM (State [s]) + ,PolyplateM s BaseOpM (OneOpM s) (State [s])) => (s -> Bool) -> t -> [s] -- We use applyBottomUp because we are prepending to the list. If we prepend from -- the bottom up, that's the same as appending from the top down, which is what -- this function is meant to be doing. @@ -96,8 +99,8 @@ listifyDepth qf = flip execState [] . applyBottomUpM qf' qf' x = if qf x then modify (x:) >> return x else return x -- | Like listifyDepth, but with routes -listifyDepthRoute :: (PolyplateMRoute t (OneOpMRoute (State [(s, Route s t)]) s t) () (State [(s, Route s t)]) t - ,PolyplateMRoute s () (OneOpMRoute (State [(s, Route s t)]) s t) (State [(s, Route s t)]) t) +listifyDepthRoute :: (PolyplateMRoute t (OneOpMRoute s) (BaseOpMRoute) (State [(s, Route s t)]) t + ,PolyplateMRoute s (BaseOpMRoute) (OneOpMRoute s) (State [(s, Route s t)]) t) => ((s, Route s t) -> Bool) -> t -> [(s, Route s t)] listifyDepthRoute qf = flip execState [] . applyBottomUpMRoute qf' where @@ -112,15 +115,15 @@ listifyDepthRoute qf = flip execState [] . applyBottomUpMRoute qf' -- -- This can be used, for example, to perform checks on items in an error monad, -- or to accumulate information in a state monad. -checkDepthM :: (Monad m, PolyplateM t (OneOpM m s) () m - , PolyplateM s () (OneOpM m s) m) => (s -> m ()) -> t -> m () +checkDepthM :: (Monad m, PolyplateM t (OneOpM s) BaseOpM m + , PolyplateM s BaseOpM (OneOpM s) m) => (s -> m ()) -> t -> m () checkDepthM f x = applyBottomUpM (\x -> f x >> return x) x >> return () -- | As 'checkDepthM', but takes two functions (one operating on type \"r\", the -- other on type \"s\"). -checkDepthM2 :: (Monad m, PolyplateM t (TwoOpM m r s) () m - , PolyplateM r () (TwoOpM m r s) m - , PolyplateM s () (TwoOpM m r s) m +checkDepthM2 :: (Monad m, PolyplateM t (TwoOpM r s) (BaseOpM) m + , PolyplateM r (BaseOpM) (TwoOpM r s) m + , PolyplateM s (BaseOpM) (TwoOpM r s) m ) => (r -> m ()) -> (s -> m ()) -> t -> m () checkDepthM2 f g x = applyBottomUpM2 (\x -> f x >> return x) @@ -134,31 +137,35 @@ checkDepthM2 f g x = applyBottomUpM2 (\x -> f x >> return x) -- traversal in order of a constructor's children (assuming you are using one of -- the generated instances, not your own), descending first and applying the function -- afterwards on the way back up. -applyBottomUpM :: (PolyplateM t (OneOpM m s) () m, - PolyplateM s () (OneOpM m s) m) => +applyBottomUpM :: (PolyplateM t (OneOpM s) BaseOpM m, + PolyplateM s BaseOpM (OneOpM s) m) => (s -> m s) -> t -> m t applyBottomUpM f = makeRecurseM ops where - ops = baseOp `extOpM` makeBottomUpM ops f + ops = baseOpM `extOpM` makeBottomUpM ops f -applyBottomUpMRoute :: (PolyplateMRoute t (OneOpMRoute m s t) () m t, - PolyplateMRoute s () (OneOpMRoute m s t) m t) => +applyBottomUpMRoute :: forall m s t. + (PolyplateMRoute t (OneOpMRoute s) (BaseOpMRoute) m t, + PolyplateMRoute s (BaseOpMRoute) (OneOpMRoute s) m t) => ((s, Route s t) -> m s) -> t -> m t -applyBottomUpMRoute f x = transformMRoute ops () (x, identityRoute) +applyBottomUpMRoute f x = transformMRoute ops base (x, identityRoute) where - ops = baseOp `extOpMRoute` makeBottomUpMRoute ops f + base :: BaseOpMRoute m t + base = baseOpMRoute + + ops = base `extOpMRoute` makeBottomUpMRoute ops f -- | As 'applyBottomUpM', but applies two functions. These should not be modifying -- the same type. -applyBottomUpM2 :: (PolyplateM t (TwoOpM m sA sB) () m, - PolyplateM sA () (TwoOpM m sA sB) m, - PolyplateM sB () (TwoOpM m sA sB) m +applyBottomUpM2 :: (PolyplateM t (TwoOpM sA sB) (BaseOpM) m, + PolyplateM sA (BaseOpM) (TwoOpM sA sB) m, + PolyplateM sB (BaseOpM) (TwoOpM sA sB) m ) => (sA -> m sA) -> (sB -> m sB) -> t -> m t applyBottomUpM2 fA fB = makeRecurseM ops where - ops = baseOp `extOpM` makeBottomUpM ops fA `extOpM` makeBottomUpM ops fB + ops = makeBottomUpM ops fA :-* makeBottomUpM ops fB :-* baseOpM -- | As 'applyBottomUpM', but non-monadic. applyBottomUp :: (Polyplate t (OneOp s) (), @@ -183,23 +190,23 @@ applyBottomUp2 fA fB = makeRecurse ops -- traversal in order of a constructor's children (assuming you are using one of -- the generated instances, not your own), applying the function first and then -- descending. -applyTopDownM :: (PolyplateM t (OneOpM m s) () m, - PolyplateM s () (OneOpM m s) m) => +applyTopDownM :: (PolyplateM t (s :-* BaseOpM) BaseOpM m, + PolyplateM s BaseOpM (s :-* BaseOpM) m) => (s -> m s) -> t -> m t applyTopDownM f = makeRecurseM ops where - ops = baseOp `extOpM` makeTopDownM ops f + ops = makeTopDownM ops f :-* baseOpM -- | As applyTopDownM, but applies two functions. These should not be modifying -- the same type. -applyTopDownM2 :: (PolyplateM t (TwoOpM m sA sB) () m, - PolyplateM sA () (TwoOpM m sA sB) m, - PolyplateM sB () (TwoOpM m sA sB) m +applyTopDownM2 :: (PolyplateM t (sA :-* sB :-* BaseOpM) BaseOpM m, + PolyplateM sA BaseOpM (sA :-* sB :-* BaseOpM) m, + PolyplateM sB BaseOpM (sA :-* sB :-* BaseOpM) m ) => (sA -> m sA) -> (sB -> m sB) -> t -> m t applyTopDownM2 fA fB = makeRecurseM ops where - ops = baseOp `extOpM` makeTopDownM ops fA `extOpM` makeTopDownM ops fB + ops = makeTopDownM ops fA :-* makeTopDownM ops fB :-* baseOpM {- TODO