Class.hs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. {-# LANGUAGE TypeFamilies #-}
  2. module Control.Monad.Trans.Interruptible.Class (
  3. Interruptible(..),
  4. -- * Instance accessors
  5. inEitherTCtx, peelEitherTCtx,
  6. inStateTCtx, peelStateTCtx,
  7. inWriterTCtx, peelWriterTCtx,
  8. inReaderTCtx, peelReaderTCtx,
  9. inRWSTCtx, peelRWSTCtx,
  10. -- * Resumers for stacks of interruptibles
  11. resume2,
  12. resume3,
  13. resume4,
  14. resume5
  15. )where
  16. import Control.Monad.Trans.Class
  17. import Control.Monad.Trans.State
  18. import Control.Monad.Trans.Either
  19. import Control.Monad.Trans.Reader
  20. import Control.Monad.Trans.Writer
  21. import Control.Monad.Trans.RWS
  22. {- |
  23. Interruptible monad transformers.
  24. A monad transformer can be made interruptible if it returns its
  25. final context from its type creator, and if it is possible
  26. to hoist this context again into the monad at the begining
  27. of its execution.
  28. For example, @StateT@ can be interrupted because
  29. @runStateT@ returns its final state, and because its state
  30. can be set again at creation simply by passing it as an
  31. parameter to @runStateT@. An Error context can not be hoisted
  32. back at the transformer, thus Error can not be interrupted.
  33. When instantiating, do not forget to create the corresponding
  34. inCtx and peelCtx functions, for documenting the RSt format
  35. and keeping the class consistent.
  36. -}
  37. class MonadTrans t => Interruptible t where
  38. -- | Context data of the transformer
  39. type RSt t a :: *
  40. -- | Resumes the execution of an interruptible transformer
  41. resume :: Monad m => (a -> t m b) -> RSt t a -> m (RSt t b)
  42. instance Interruptible (EitherT e) where
  43. -- | The context of @EitherT e a@ is @Either e a@.
  44. type RSt (EitherT e) a = Either e a
  45. resume f st = runEitherT (hoistEither st >>= f)
  46. -- | Cretes an interrupted EitherT context
  47. inEitherTCtx :: a -> RSt (EitherT e) a
  48. inEitherTCtx = Right
  49. -- | Unwraps an interrupted EitherT context
  50. peelEitherTCtx :: RSt (EitherT e) a -> Either e a
  51. peelEitherTCtx = id
  52. instance Interruptible (StateT st) where
  53. -- | The context of @StateT st a@ is @(a, st)@
  54. type RSt (StateT st) a = (a, st)
  55. resume f (a, st) = runStateT (f a) st
  56. -- | Creates an interrupted StateT context
  57. inStateTCtx :: st -> a -> RSt (StateT st) a
  58. inStateTCtx st a = (a, st)
  59. -- | Unwraps an interrupted StateT context
  60. peelStateTCtx :: RSt (StateT st) a -> (a, st)
  61. peelStateTCtx = id
  62. instance Monoid w => Interruptible (WriterT w) where
  63. type RSt (WriterT w) a = (a, w)
  64. resume f (a, w) = do
  65. (a', w') <- runWriterT (f a)
  66. return (a', mappend w w')
  67. -- | Creates an interrupted WriterT context
  68. inWriterTCtx :: Monoid w => a -> RSt (WriterT w) a
  69. inWriterTCtx a = (a, mempty)
  70. -- | Unwraps an interrupted WriterT context
  71. peelWriterTCtx :: RSt (WriterT w) a -> (a, w)
  72. peelWriterTCtx = id
  73. instance Interruptible (ReaderT r) where
  74. type RSt (ReaderT r) a = (a, r)
  75. resume f (a, r) = do
  76. a' <- runReaderT (f a) r
  77. return (a', r)
  78. -- | Creates an interrupted ReaderT context
  79. inReaderTCtx :: r -> a -> RSt (ReaderT r) a
  80. inReaderTCtx r a = (a, r)
  81. -- | Unwraps an interrupted WriterT context
  82. peelReaderTCtx :: RSt (ReaderT r) a -> a
  83. peelReaderTCtx (a, _) = a
  84. instance Monoid w => Interruptible (RWST r w s) where
  85. type RSt (RWST r w s) a = (a, r, w, s)
  86. resume f (a, r, w, s) = do
  87. (a', s', w') <- runRWST (f a) r s
  88. return (a', r, w', s')
  89. -- | Creates an interrupted RWST context
  90. inRWSTCtx :: Monoid w => r -> s -> a -> RSt (RWST r w s) a
  91. inRWSTCtx r s a = (a, r, mempty, s)
  92. -- | Unwraps an interrupted RWST context
  93. peelRWSTCtx :: RSt (RWST r w s) a -> (a, w, s)
  94. peelRWSTCtx (a, r, w, s) = (a, w, s)
  95. resume2 :: (Monad m, Interruptible t, Monad (t m), Interruptible u) =>
  96. (a -> u (t m) b) -> RSt t (RSt u a) -> m (RSt t (RSt u b))
  97. resume2 = resume.resume
  98. resume3 :: (Monad m, Interruptible t0, Monad (t0 m), Interruptible t1,
  99. Monad (t1 (t0 m)), Interruptible t2) =>
  100. (a -> t2 (t1 (t0 m)) b) -> RSt t0 (RSt t1 (RSt t2 a)) ->
  101. m (RSt t0 (RSt t1 (RSt t2 b)))
  102. resume3 = resume2.resume
  103. resume4 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
  104. Interruptible t3, Monad (t0 m), Monad (t1 (t0 m)), Monad (t2 (t1 (t0 m)))) =>
  105. (a -> t3 (t2 (t1 (t0 m))) b) -> RSt t0 (RSt t1 (RSt t2 (RSt t3 a))) ->
  106. m (RSt t0 (RSt t1 (RSt t2 (RSt t3 b))))
  107. resume4 = resume3.resume
  108. resume5 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
  109. Interruptible t3, Interruptible t4, Monad (t0 m), Monad (t1 (t0 m)),
  110. Monad (t2 (t1 (t0 m))), Monad (t3 (t2 (t1 (t0 m))))) =>
  111. (a -> t4 (t3 (t2 (t1 (t0 m)))) b) -> RSt t0 (RSt t1 (RSt t2 (RSt t3 (RSt t4 a)))) ->
  112. m (RSt t0 (RSt t1 (RSt t2 (RSt t3 (RSt t4 b)))))
  113. resume5 = resume4.resume