{-# LANGUAGE TemplateHaskell #-} module MonadLab.Writer ( writerT ) where import Prelude hiding (Monad) import Data.Monoid import Language.Haskell.TH import MonadLab.CommonTypes writerT :: Layer -> MonadTransformer writerT l@(WriterT name w) = \m -> ( writerTransTypeCon w m , writerTransReturn m , writerTransBind m , writerTransLayerNPM l m : writerTransLiftLayerNPMs m , [| $(writerTransLift m) . $(getBaseLift m) |] ) -------------------------------- writerTransTypeCon :: TypeQ -> Monad -> MonadTypeCon writerTransTypeCon w m = let tc = getTypeCon m in \t -> tc (appT (appT (tupleT 2) t) w) writerTransReturn :: Monad -> ReturnExpQ writerTransReturn m = let return = getReturn m in [| \v -> $return (v, mempty) |] writerTransBind :: Monad -> BindExpQ writerTransBind m = let return = getReturn m bind = getBind m in [| \m -> \f -> $bind m (\ (a, w) -> $bind (f a) (\ (b, w') -> $return (b, w `mappend` w'))) |] writerTransTell :: Monad -> NonProperMorphismExpQ writerTransTell m = let return = getReturn m in [| \w -> $return ((), w) |] writerTransListen :: Monad -> NonProperMorphismExpQ writerTransListen m = let return = getReturn m bind = getBind m in [| \m -> $bind m (\(a, w) -> $return ((a, w), w)) |] writerTransPass :: Monad -> NonProperMorphismExpQ writerTransPass m = let return = getReturn m bind = getBind m in [| \m -> $bind m (\((a, f), w) -> $return (a, f w)) |] writerTransLift :: Monad -> LiftExpQ writerTransLift m = let return = getReturn m bind = getBind m in [| \m -> $bind m (\a -> $return (a, "")) |] -------------------------------- writerTransLayerNPM :: Layer -> Monad -> LayerNPM writerTransLayerNPM l m = (l, [writerTransTell m, writerTransListen m, writerTransPass m]) writerTransLiftLayerNPMs :: Monad -> [LayerNPM] writerTransLiftLayerNPMs m = map (writerTransLiftLayerNPM m) (getLayerNPMs m) where writerTransLiftLayerNPM :: Monad -> LayerNPM -> LayerNPM writerTransLiftLayerNPM m l = case l of (List, [merge, halt]) -> (List, [writerTransLiftMerge m, writerTransLiftHalt m]) (Io, [liftIO]) -> (Io, [writerTransLiftLiftIO m liftIO]) (StateT n t, [get,put]) -> (StateT n t, [writerTransLiftGet m get, writerTransLiftPut m put]) (EnvT n t, [rdEnv,inEnv]) -> (EnvT n t, [writerTransLiftRdEnv m rdEnv, writerTransLiftInEnv inEnv]) (ErrorT n t, [throw,catch]) -> (ErrorT n t, [writerTransLiftThrow m throw, writerTransLiftCatch catch]) (WriterT n t, [tell, listen, pass]) -> (WriterT n t, [writerTransLiftTell m tell, writerTransLiftListen m listen, writerTransLiftPass m pass]) (ContT t, [callcc]) -> (ContT t, [writerTransLiftCallCC m callcc]) writerTransLiftGet :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftGet m get = [| $(writerTransLift m) $get |] writerTransLiftPut :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftPut m put = [| $composition $(writerTransLift m) $put |] writerTransLiftRdEnv :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftRdEnv m rdEnv = [| $(writerTransLift m) $rdEnv |] writerTransLiftInEnv :: NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftInEnv inEnv = inEnv writerTransLiftThrow :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftThrow m throw = [| $composition $(writerTransLift m) $throw |] writerTransLiftCatch :: NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftCatch catch = catch writerTransLiftMerge :: Monad -> NonProperMorphismExpQ writerTransLiftMerge m = let newJoin = [| \x -> $(writerTransBind m) x (\a -> a) |] newBaseLift = [| $(writerTransLift m) . $(getBaseLift m) |] in [| $composition $newJoin $newBaseLift |] writerTransLiftHalt :: Monad -> NonProperMorphismExpQ writerTransLiftHalt m = let newBaseLift = [| $(writerTransLift m) . $(getBaseLift m) |] in [| $newBaseLift [] |] writerTransLiftLiftIO :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftLiftIO m liftIO = [| $(writerTransLift m) . $liftIO |] writerTransLiftTell :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftTell m tell = [| $composition $(writerTransLift m) $tell |] writerTransLiftListen :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftListen m listen = let return = getReturn m bind = getBind m in [| \m -> $bind ($listen m) (\((v, w'), w) -> $return ((v, w), w')) |] writerTransLiftPass :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftPass m pass = let return = getReturn m bind = getBind m in [| \m -> $pass $ $bind m (\((v, f), w') -> $return ((v, w'), f)) |] writerTransLiftCallCC :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ writerTransLiftCallCC m callcc = [| \f -> $callcc (\k -> f (\a -> k (a, ""))) |]