1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- {-# LANGUAGE TypeFamilies #-}
- module Control.Monad.Trans.Interruptible.Class (
- Interruptible(..),
- -- * Resumers for stacks of interruptibles
- resume2,
- resume3,
- resume4,
- resume5
- )where
- import Control.Monad.Trans.Class
- import Control.Monad.Trans.State
- import Control.Monad.Trans.Either
- {- |
- Interruptible monad transformers.
- A monad transformer can be interrupted if it returns its
- final context from its type creator, and if it is possible
- to hoist this context again into the monad at the begining
- of its execution.
- For example, @StateT@ can be interrupted because
- @runStateT@ returns its final state, and because its state
- can be set at the type creation. Error can not be hoisted,
- thus is can not be interrupted.
- Interruptible transformers can be stacked so that their
- execution is resumed by composition of their @resume@
- functions, and their data by the composition of their data
- constructors at the inverse order. That is, in the stack:
- > (Monad m, Interruptible i, Interruptible j) => i j m
- Both i and j can be resumed by the function @resume . resume@,
- and given @initI :: a -> RSt i a@ and @initJ :: a -> RSt j a@,
- the total context is given by @initJ . initI@.
- The context data constructors vary with each Interruptible,
- as well as its signature.
- -}
- class MonadTrans t => Interruptible t where
- -- | Context data of the transformer
- type RSt t a :: *
- -- | Resumes the execution of an interruptible transformer
- resume :: Monad m => (a -> t m b) -> RSt t a -> m (RSt t b)
- instance Interruptible (EitherT e) where
- -- | The context of @EitherT e a@ is @Either e a@.
- type RSt (EitherT e) a = Either e a
- resume f st = runEitherT (hoistEither st >>= f)
- instance Interruptible (StateT st) where
- -- | The context of @StateT st a@ is @(a, st)@
- type RSt (StateT st) a = (a, st)
- resume f (a, st) = runStateT (f a) st
- resume2 :: (Monad m, Interruptible t, Monad (t m), Interruptible u) =>
- (a -> u (t m) b) -> RSt t (RSt u a) -> m (RSt t (RSt u b))
- resume2 = resume.resume
- resume3 :: (Monad m, Interruptible t0, Monad (t0 m), Interruptible t1,
- Monad (t1 (t0 m)), Interruptible t2) =>
- (a -> t2 (t1 (t0 m)) b) -> RSt t0 (RSt t1 (RSt t2 a)) ->
- m (RSt t0 (RSt t1 (RSt t2 b)))
- resume3 = resume2.resume
- resume4 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
- Interruptible t3, Monad (t0 m), Monad (t1 (t0 m)), Monad (t2 (t1 (t0 m)))) =>
- (a -> t3 (t2 (t1 (t0 m))) b) -> RSt t0 (RSt t1 (RSt t2 (RSt t3 a))) ->
- m (RSt t0 (RSt t1 (RSt t2 (RSt t3 b))))
- resume4 = resume3.resume
- resume5 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
- Interruptible t3, Interruptible t4, Monad (t0 m), Monad (t1 (t0 m)),
- Monad (t2 (t1 (t0 m))), Monad (t3 (t2 (t1 (t0 m))))) =>
- (a -> t4 (t3 (t2 (t1 (t0 m)))) b) -> RSt t0 (RSt t1 (RSt t2 (RSt t3 (RSt t4 a)))) ->
- m (RSt t0 (RSt t1 (RSt t2 (RSt t3 (RSt t4 b)))))
- resume5 = resume4.resume
|