Pārlūkot izejas kodu

Better documentation

Marcos Dumay de Medeiros 8 gadi atpakaļ
vecāks
revīzija
4794bdc5e5

+ 51 - 12
interruptible.cabal

@@ -2,20 +2,59 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                interruptible
-version:             0.1.1.0
+version:             0.1.1.1
 synopsis:            Monad transformers that can be run and resumed later, conserving their context.
 description:
-    Given an inner monad and a transformer:
-    > (Monad m, MonadTrans t)
-    If t is an interruptible transformer, it becomes possible to intercalate executions
-    on the t context with executions over the inner monad m by breaking the execution
-    on t and resuming it later.
+    Given an inner monad @M@ and a transformer @T@, if T is an interruptible transformer,
+    it becomes possible to intercalate functions over its context with functions over the
+    inner monad. That is, code like this:
     .
-    Interruptible monads implement the @runI@ function so that, given 'f :: a -> t m b' and
-    'g :: b -> t m c', 'resume (f >>= g)' is equivalent to '\x -> resume f x >>= resume g'.
+    @
+    runT (f 1 >>= g)
+    where
+        f :: Int -> T M a
+        g :: a -> T M b
+    @
     .
-    That makes it possible to intercalate the execution of different monads, and even to
-    return a monadic context for another function to resume it.
+    Can be broken up like this:
+    .
+    @
+    do
+    let c0 = inTCtx 1
+    c1 <- resume f ct1
+    _ <- resume g ct2
+    @
+    .
+    That makes it possible to intercalate the execution of different contexts, and
+    treat contexts like data, for iterating or returning them.
+    .
+    As shown on the example, interruptible transformers are resumed with the @resume@ function.
+    State may be managed by specialized functions usually named as @inTransfomerCtx@ and
+    @peelTransformerCtx@ that enclose a value in an initial context and retrieve the
+    value from a context.
+    .
+    Interruptible transformers can be stacked. On this case, they must be resumed with a
+    composition of @resume@ calls, and their contexts must be created and peeled on the inverse
+    order that they appear on the stack. Like:
+    .
+    @
+    do
+    let c0 = inT2Ctx . inT1Ctx $ 1
+    c1 <- (resume . resume) f ct1
+    _ <- (resume . resume) g ct2
+    where
+        f :: Monad m => Int -> T1 T2 M a
+        g :: Monad m => a -> T1 T2 M b
+    @
+    .
+    For convenience, the @Interruptible@ module exports the @resume2@ to @resume5@
+    functions as composotions of resume. They can be composed further as in
+    @resume7 = resume3 . resume4@ if necessary.
+    .
+    This package also contains the appliable instantiations of Interruptible for the mtl transformers,
+    the @intercalateWith@ function, that intercalates calls of a function through a list
+    of contexts and parameters, and the @SafeIO@ module that lifts IOException treatment from the
+    base monad into the current resumed context.
 homepage:            https://sealgram.com/git/haskell/interruptible/
 license:             BSD3
 license-file:        LICENSE
@@ -35,7 +74,7 @@ source-repository head
 source-repository this
   type:     git
   location: https://sealgram.com/git/haskell/interruptible/
-  tag:   0.1.1.0
+  tag:   0.1.1.1
 
 
 library
@@ -45,7 +84,7 @@ library
   other-modules:       Control.Monad.Trans.Interruptible.Class
   other-extensions:    TypeFamilies
   build-depends:
-      base >=4.7 && <4.9,
+      base >=4.7 && <5,
       transformers,
       monad-control,
       lifted-base,

+ 7 - 16
src/Control/Monad/Trans/Interruptible/Class.hs

@@ -25,29 +25,20 @@ import Control.Monad.Trans.RWS
 {- |
 Interruptible monad transformers.
 
-A monad transformer can be interrupted if it returns its
+A monad transformer can be made interruptible 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.
+can be set again at creation simply by passing it as an
+parameter to @runStateT@. An Error context can not be hoisted
+back at the transformer, thus Error 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.
+When instantiating, do not forget to create the corresponding
+inCtx and peelCtx functions, for documenting the RSt format
+and keeping the class consistent.
 -}
 class MonadTrans t => Interruptible t where
   -- | Context data of the transformer

+ 3 - 2
src/Control/Monad/Trans/SafeIO.hs

@@ -32,9 +32,10 @@ SafeIO was created to enforce this kind of behavior.
 
 ==How to use:
 
-1. Do not import Control.Monad.Trans, Control.Monad.IO or anything similar at your module.
+1. Idealy, do not import lift, liftIO, or anything similar at your module.
 2. Create an error type (let's call it @e@), and make it an instance of IOErrorDerivation.
-3. Wrap your computation inside an @EitherT e@ transformer.
+3. Wrap your computation inside an @EitherT e@ transformer (and keep the EitherT the top-level
+   transformer).
 4. Use the safe functions on this module instead of lift, liftIO, liftBase, etc.
 
 Remember that the context of interruptible transformers are in the inverse order that the