Browse Source

Fixed the docs

Marcos Dumay de Medeiros 8 years ago
parent
commit
397e778527

+ 3 - 3
interruptible.cabal

@@ -12,7 +12,7 @@ description:
     on @t@ and resuming it later.
     on @t@ and resuming it later.
     .
     .
     Interruptible monads implement the @runI@ function so that, given @f :: a -> t m b@ and
     Interruptible monads implement the @runI@ function so that, given @f :: a -> t m b@ and
-    @g :: b -> t m c@, @runI (f >>= g)@ is equivalent to @\x -> runI f x >>= runI g@.
+    @g :: b -> t m c@, @resume (f >>= g)@ is equivalent to @\x -> resume f x >>= resume g@.
     .
     .
     That makes it possible to intercalate the execution of different monads, and even to
     That makes it possible to intercalate the execution of different monads, and even to
     return a monadic context for another function to resume it.
     return a monadic context for another function to resume it.
@@ -28,8 +28,8 @@ build-type:          Simple
 cabal-version:       >=1.10
 cabal-version:       >=1.10
 
 
 library
 library
-  exposed-modules:     Control.Monad.Trans.Interruptible, Control.Monad.Trans.Interruptible.Class
-  -- other-modules:       
+  exposed-modules:     Control.Monad.Trans.Interruptible
+  other-modules:       Control.Monad.Trans.Interruptible.Class
   other-extensions:    TypeFamilies
   other-extensions:    TypeFamilies
   build-depends:
   build-depends:
       base >=4.7 && <4.9,
       base >=4.7 && <4.9,

+ 11 - 7
src/Control/Monad/Trans/Interruptible.hs

@@ -2,6 +2,7 @@
 
 
 module Control.Monad.Trans.Interruptible (
 module Control.Monad.Trans.Interruptible (
   module Control.Monad.Trans.Interruptible.Class,
   module Control.Monad.Trans.Interruptible.Class,
+  -- * Interruptible applications
   intercalateWith
   intercalateWith
   )where
   )where
 
 
@@ -12,17 +13,20 @@ Folds the second list with the function applied to the first,
 intercalating the evaluation. That is:
 intercalating the evaluation. That is:
 
 
 @
 @
-intercalateM f [a00, a10, a20] [b1, b2] = do
-  a01 <- f a00 b1
-  a11 <- f a10 b1
-  a21 <- f a20 b1
-  a02 <- f a11 b2
-  a12 <- f a21 b2
-  a22 <- f a31 b2
+intercalateWith resume f [a00, a10, a20] [b1, b2] = do
+  a01 <- resume (f b1) a00
+  a11 <- resume (f b1) a10
+  a21 <- resume (f b1) a20
+  a02 <- resume (f b2) a11
+  a12 <- resume (f b2) a21
+  a22 <- resume (f b2) a31
   return [a02, a12, a22]
   return [a02, a12, a22]
 @
 @
 
 
 Usefull for consuming lazy sequences.
 Usefull for consuming lazy sequences.
+
+The resume function is parametric for allowing resuming deeper Interruptible chains, with
+resume2, resume3, etc.
 -}
 -}
 intercalateWith :: Monad m => ((a -> t a) -> rsta -> m (rsta)) -> (b -> a -> t a) -> [b] -> [rsta] -> m [rsta]
 intercalateWith :: Monad m => ((a -> t a) -> rsta -> m (rsta)) -> (b -> a -> t a) -> [b] -> [rsta] -> m [rsta]
 intercalateWith _ _ [] aa = return aa
 intercalateWith _ _ [] aa = return aa

+ 49 - 3
src/Control/Monad/Trans/Interruptible/Class.hs

@@ -1,31 +1,77 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeFamilies #-}
 
 
-module Control.Monad.Trans.Interruptible.Class where
+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.Class
+import Control.Monad.Trans.State
 import Control.Monad.Trans.Either
 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
 class MonadTrans t => Interruptible t where
-  type RSt t :: * -> *
+  -- | 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)
   resume :: Monad m => (a -> t m b) -> RSt t a -> m (RSt t b)
 
 
 instance Interruptible (EitherT e) where
 instance Interruptible (EitherT e) where
-  type RSt (EitherT e) = Either e
+  -- | 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)
   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) =>
 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))
            (a -> u (t m) b) -> RSt t (RSt u a) -> m (RSt t (RSt u b))
 resume2 = resume.resume
 resume2 = resume.resume
+
 resume3 :: (Monad m, Interruptible t0, Monad (t0 m), Interruptible t1,
 resume3 :: (Monad m, Interruptible t0, Monad (t0 m), Interruptible t1,
             Monad (t1 (t0 m)), Interruptible t2) =>
             Monad (t1 (t0 m)), Interruptible t2) =>
            (a -> t2 (t1 (t0 m)) b) -> RSt t0 (RSt t1 (RSt t2 a)) ->
            (a -> t2 (t1 (t0 m)) b) -> RSt t0 (RSt t1 (RSt t2 a)) ->
            m (RSt t0 (RSt t1 (RSt t2 b)))
            m (RSt t0 (RSt t1 (RSt t2 b)))
 resume3 = resume2.resume
 resume3 = resume2.resume
+
 resume4 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
 resume4 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
             Interruptible t3, Monad (t0 m), Monad (t1 (t0 m)), Monad (t2 (t1 (t0 m)))) =>
             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))) ->
            (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))))
            m (RSt t0 (RSt t1 (RSt t2 (RSt t3 b))))
 resume4 = resume3.resume
 resume4 = resume3.resume
+
 resume5 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
 resume5 :: (Monad m, Interruptible t0, Interruptible t1, Interruptible t2,
             Interruptible t3, Interruptible t4, Monad (t0 m), Monad (t1 (t0 m)),
             Interruptible t3, Interruptible t4, Monad (t0 m), Monad (t1 (t0 m)),
             Monad (t2 (t1 (t0 m))), Monad (t3 (t2 (t1 (t0 m))))) =>
             Monad (t2 (t1 (t0 m))), Monad (t3 (t2 (t1 (t0 m))))) =>