Class.hs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. {-# LANGUAGE TypeFamilies #-}
  2. module Control.Monad.Trans.Interruptible.Class (
  3. Interruptible(..),
  4. -- * Resumers for stacks of interruptibles
  5. resume2,
  6. resume3,
  7. resume4,
  8. resume5
  9. )where
  10. import Control.Monad.Trans.Class
  11. import Control.Monad.Trans.State
  12. import Control.Monad.Trans.Either
  13. {- |
  14. Interruptible monad transformers.
  15. A monad transformer can be interrupted if it returns its
  16. final context from its type creator, and if it is possible
  17. to hoist this context again into the monad at the begining
  18. of its execution.
  19. For example, @StateT@ can be interrupted because
  20. @runStateT@ returns its final state, and because its state
  21. can be set at the type creation. Error can not be hoisted,
  22. thus is can not be interrupted.
  23. Interruptible transformers can be stacked so that their
  24. execution is resumed by composition of their @resume@
  25. functions, and their data by the composition of their data
  26. constructors at the inverse order. That is, in the stack:
  27. > (Monad m, Interruptible i, Interruptible j) => i j m
  28. Both i and j can be resumed by the function @resume . resume@,
  29. and given @initI :: a -> RSt i a@ and @initJ :: a -> RSt j a@,
  30. the total context is given by @initJ . initI@.
  31. The context data constructors vary with each Interruptible,
  32. as well as its signature.
  33. -}
  34. class MonadTrans t => Interruptible t where
  35. -- | Context data of the transformer
  36. type RSt t a :: *
  37. -- | Resumes the execution of an interruptible transformer
  38. resume :: Monad m => (a -> t m b) -> RSt t a -> m (RSt t b)
  39. instance Interruptible (EitherT e) where
  40. -- | The context of @EitherT e a@ is @Either e a@.
  41. type RSt (EitherT e) a = Either e a
  42. resume f st = runEitherT (hoistEither st >>= f)
  43. instance Interruptible (StateT st) where
  44. -- | The context of @StateT st a@ is @(a, st)@
  45. type RSt (StateT st) a = (a, st)
  46. resume f (a, st) = runStateT (f a) st
  47. resume2 :: (Monad m, Interruptible t, Monad (t m), Interruptible u) =>
  48. (a -> u (t m) b) -> RSt t (RSt u a) -> m (RSt t (RSt u b))
  49. resume2 = resume.resume
  50. resume3 :: (Monad m, Interruptible t0, Monad (t0 m), Interruptible t1,
  51. Monad (t1 (t0 m)), Interruptible t2) =>
  52. (a -> t2 (t1 (t0 m)) b) -> RSt t0 (RSt t1 (RSt t2 a)) ->
  53. m (RSt t0 (RSt t1 (RSt t2 b)))
  54. resume3 = resume2.resume
  55. resume4 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
  56. Interruptible t3, Monad (t0 m), Monad (t1 (t0 m)), Monad (t2 (t1 (t0 m)))) =>
  57. (a -> t3 (t2 (t1 (t0 m))) b) -> RSt t0 (RSt t1 (RSt t2 (RSt t3 a))) ->
  58. m (RSt t0 (RSt t1 (RSt t2 (RSt t3 b))))
  59. resume4 = resume3.resume
  60. resume5 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
  61. Interruptible t3, Interruptible t4, Monad (t0 m), Monad (t1 (t0 m)),
  62. Monad (t2 (t1 (t0 m))), Monad (t3 (t2 (t1 (t0 m))))) =>
  63. (a -> t4 (t3 (t2 (t1 (t0 m)))) b) -> RSt t0 (RSt t1 (RSt t2 (RSt t3 (RSt t4 a)))) ->
  64. m (RSt t0 (RSt t1 (RSt t2 (RSt t3 (RSt t4 b)))))
  65. resume5 = resume4.resume