module Test.Sloth.Generics
(
Compose(..), inCompose,
fromConstrWithChildren,
gunfoldM, gunfoldWithIndex
) where
import Control.Monad.State ( evalState, get, put )
import Data.Data ( Data, Constr, gunfold, fromConstrM )
newtype Compose f g a = Compose { compose :: f (g a) }
inCompose :: (f (g a) -> f (g b)) -> Compose f g a -> Compose f g b
inCompose f (Compose x) = Compose (f x)
gunfoldM :: (Data a,Monad m)
=> (forall b r. Data b => m (c (b -> r)) -> m (c r))
-> (forall r. r -> m (c r)) -> Constr -> m (c a)
gunfoldM k z c = compose (gunfold (inCompose k) (Compose . z) c)
gunfoldWithIndex :: Data a => (forall b r. Data b => Int -> c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c a
gunfoldWithIndex k z c =
evalState (gunfoldM applyWithIndex (return . z) c) 0
where
applyWithIndex cf = do
f <- cf
n <- get
put (n+1)
return (k n f)
fromConstrWithChildren :: Data a => (forall b. Data b => c -> b) -> [c]
-> Constr -> a
fromConstrWithChildren toData children c =
evalState (fromConstrM (fmap toData nextChild) c) children
where
nextChild = do
xxs <- get
case xxs of
[] -> error "fromConstRec: Constr expects arguments but none \
\are provided"
x:xs -> put xs >> return x