--
-----------------------------------------------------------------------------
-module Data.Generics.Twins (
+module Data.Generics.Twins (
- -- * Generic folds and maps that also accumulate
- gfoldlAccum,
- gmapAccumT,
- gmapAccumM,
- gmapAccumQl,
- gmapAccumQr,
- gmapAccumQ,
+ -- * Generic folds and maps that also accumulate
+ gfoldlAccum,
+ gmapAccumT,
+ gmapAccumM,
+ gmapAccumQl,
+ gmapAccumQr,
+ gmapAccumQ,
- -- * Mapping combinators for twin traversal
- gzipWithT,
- gzipWithM,
- gzipWithQ,
+ -- * Mapping combinators for twin traversal
+ gzipWithT,
+ gzipWithM,
+ gzipWithQ,
- -- * Typical twin traversals
- geq,
- gzip
+ -- * Typical twin traversals
+ geq,
+ gzip
) where
------------------------------------------------------------------------------
--
--- Generic folds and maps that also accumulate
+-- Generic folds and maps that also accumulate
--
------------------------------------------------------------------------------
gmapAccumT f a d = let (a',d') = gfoldlAccum k z a d
in (a',unID d')
where
- k a (ID c) d = let (a',d') = f a d
+ k a (ID c) d = let (a',d') = f a d
in (a', ID (c d'))
z a x = (a, ID x)
-> a -> d -> (a, m d)
gmapAccumM f = gfoldlAccum k z
where
- k a c d = let (a',d') = f a d
+ k a c d = let (a',d') = f a d
in (a', d' >>= \d'' -> c >>= \c' -> return (c' d''))
z a x = (a, return x)
-- | gmapQl with accumulation
-gmapAccumQl :: Data d
- => (r -> r' -> r)
+gmapAccumQl :: Data d
+ => (r -> r' -> r)
-> r
-> (forall d. Data d => a -> d -> (a,r'))
-> a -> d -> (a, r)
gmapAccumQl o r f a d = let (a',r) = gfoldlAccum k z a d
in (a',unCONST r)
where
- k a (CONST c) d = let (a',r') = f a d
+ k a (CONST c) d = let (a',r') = f a d
in (a', CONST (c `o` r'))
z a _ = (a, CONST r)
-- | gmapQr with accumulation
-gmapAccumQr :: Data d
- => (r' -> r -> r)
+gmapAccumQr :: Data d
+ => (r' -> r -> r)
-> r
-> (forall d. Data d => a -> d -> (a,r'))
-> a -> d -> (a, r)
gmapAccumQr o r f a d = let (a',l) = gfoldlAccum k z a d
in (a',unQr l r)
where
- k a (Qr c) d = let (a',r') = f a d
+ k a (Qr c) d = let (a',r') = f a d
in (a', Qr (\r -> c (r' `o` r)))
z a _ = (a, Qr id)
------------------------------------------------------------------------------
--
--- Helper type constructors
+-- Helper type constructors
--
------------------------------------------------------------------------------
------------------------------------------------------------------------------
--
--- Mapping combinators for twin traversal
+-- Mapping combinators for twin traversal
--
------------------------------------------------------------------------------
gzipWithT :: GenericQ (GenericT) -> GenericQ (GenericT)
gzipWithT f x y = case gmapAccumT perkid funs y of
([], c) -> c
- _ -> error "gzipWithT"
+ _ -> error "gzipWithT"
where
perkid a d = (tail a, unGT (head a) d)
funs = gmapQ (\k -> GT (f k)) x
gzipWithM :: Monad m => GenericQ (GenericM m) -> GenericQ (GenericM m)
gzipWithM f x y = case gmapAccumM perkid funs y of
([], c) -> c
- _ -> error "gzipWithM"
+ _ -> error "gzipWithM"
where
perkid a d = (tail a, unGM (head a) d)
funs = gmapQ (\k -> GM (f k)) x
gzipWithQ :: GenericQ (GenericQ r) -> GenericQ (GenericQ [r])
gzipWithQ f x y = case gmapAccumQ perkid funs y of
([], r) -> r
- _ -> error "gzipWithQ"
+ _ -> error "gzipWithQ"
where
perkid a d = (tail a, unGQ (head a) d)
funs = gmapQ (\k -> GQ (f k)) x
------------------------------------------------------------------------------
--
--- Typical twin traversals
+-- Typical twin traversals
--
------------------------------------------------------------------------------
-- | Generic zip controlled by a function with type-specific branches
gzip :: GenericQ (GenericM Maybe) -> GenericQ (GenericM Maybe)
-- See testsuite/.../Generics/gzip.hs for an illustration
-gzip f x y =
+gzip f x y =
f x y
`orElse`
if toConstr x == toConstr y