module MonadLab.Cont (
contT
) where
import Prelude hiding (Monad)
import Language.Haskell.TH
import MonadLab.CommonTypes
contT :: Layer -> MonadTransformer
contT l@(ContT t) = \m -> ( contTransTypeCon t m
, contTransReturn
, contTransBind
, contTransLayerNPM l : contTransLiftLayerNPMs m
, [| $(contTransLift m) . $(getBaseLift m) |]
)
contTransTypeCon :: TypeQ -> Monad -> MonadTypeCon
contTransTypeCon ans m = let tc = getTypeCon m
in \t -> arrow (arrow t (tc ans)) (tc ans)
contTransReturn :: ReturnExpQ
contTransReturn = [| \v -> \k -> k v |]
contTransBind :: BindExpQ
contTransBind = [| \x -> \f -> \k -> x (\a -> f a k) |]
contTransCallCC :: NonProperMorphismExpQ
contTransCallCC = [| \f -> \k -> f (\a -> \_ -> k a) k |]
contTransLift :: Monad -> LiftExpQ
contTransLift m = [| $(getBind m) |]
contTransLayerNPM :: Layer -> LayerNPM
contTransLayerNPM l = (l, [contTransCallCC])
contTransLiftLayerNPMs :: Monad -> [LayerNPM]
contTransLiftLayerNPMs m = map (contTransLiftLayerNPM m) (getLayerNPMs m)
where contTransLiftLayerNPM :: Monad -> LayerNPM -> LayerNPM
contTransLiftLayerNPM m l = case l of
(Io, [liftIO]) -> (Io, [contTransLiftLiftIO m liftIO])
(List, [merge, halt]) -> (List, [contTransLiftMerge m, contTransLiftHalt m])
(StateT n t, [get,put]) -> (StateT n t, [contTransLiftGet m get, contTransLiftPut m put])
(EnvT n t, [rdEnv,inEnv]) -> (EnvT n t, [contTransLiftRdEnv m rdEnv, contTransLiftInEnv m rdEnv inEnv])
(ErrorT n t, [throw,catch]) -> (ErrorT n t, [contTransLiftThrow m throw, contTransLiftCatch catch])
(WriterT n t, [tell, listen, pass]) -> (WriterT n t, [stateTransLiftTell m tell, stateTransLiftListen m listen, stateTransLiftPass m pass])
contTransLiftGet :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ
contTransLiftGet m get = [| $(contTransLift m) $get |]
contTransLiftPut :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ
contTransLiftPut m put = [| $composition $(contTransLift m) $put |]
contTransLiftRdEnv :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ
contTransLiftRdEnv m rdEnv = [| $(contTransLift m) $rdEnv |]
contTransLiftInEnv :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ -> NonProperMorphismExpQ
contTransLiftInEnv m rdEnv inEnv = [| \r -> \c -> \k -> $(getBind m) $rdEnv (\o -> $inEnv r (c ($composition ($inEnv o) k))) |]
contTransLiftThrow :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ
contTransLiftThrow m throw = [| $composition $(contTransLift m) $throw |]
contTransLiftCatch :: NonProperMorphismExpQ -> NonProperMorphismExpQ
contTransLiftCatch catch = error "contTransLiftCatch: Cannot lift 'catch' through cont transformer"
contTransLiftMerge :: Monad -> NonProperMorphismExpQ
contTransLiftMerge m = let newJoin = [| \x -> $contTransBind x (\a -> a) |]
newBaseLift = [| $(contTransLift m) . $(getBaseLift m) |]
in [| $composition $newJoin $newBaseLift |]
contTransLiftHalt :: Monad -> NonProperMorphismExpQ
contTransLiftHalt m = let newBaseLift = [| $(contTransLift m) . $(getBaseLift m) |]
in [| $newBaseLift [] |]
contTransLiftLiftIO :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ
contTransLiftLiftIO m liftIO = [| $(contTransLift m) . $liftIO |]
stateTransLiftTell :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ
stateTransLiftTell m tell = error "contTransLiftTell: Cannot lift 'tell' through cont transformer"
stateTransLiftListen :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ
stateTransLiftListen m listen = error "contTransLiftListen: Cannot lift 'listen' through cont transformer"
stateTransLiftPass :: Monad -> NonProperMorphismExpQ -> NonProperMorphismExpQ
stateTransLiftPass m pass = error "contTransLiftPass: Cannot lift 'pass' through cont transformer"