packages feed

continue 0.1.1 → 0.2.0

raw patch · 7 files changed

+447/−334 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Continue: (<!>) :: Alt f => f a -> f a -> f a
- Control.Continue: class Functor f => Alt (f :: * -> *)
- Control.Continue: class Alt f => Plus (f :: * -> *)
- Control.Continue: many :: (Alt f, Applicative f) => f a -> f [a]
- Control.Continue: some :: (Alt f, Applicative f) => f a -> f [a]
- Control.Continue: zero :: Plus f => f a
- Control.Continue.Class: addCont :: MonadContinue e f m => Either e a -> f (m a) -> m a
- Control.Continue.Class: class (Plus f, Monad m, Monoid e) => MonadContinue e f m | m -> e, m -> f
- Control.Continue.Class: instance (MonadContinue e f m, Monoid l) => MonadContinue e f (WriterT l m)
- Control.Continue.Class: instance MonadContinue e f m => MonadContinue e f (IdentityT m)
- Control.Continue.Class: instance MonadContinue e f m => MonadContinue e f (MaybeT m)
- Control.Continue.Class: instance MonadContinue e f m => MonadContinue e f (ReaderT r m)
- Control.Continue.Class: instance MonadContinue e f m => MonadContinue e f (StateT s m)
- Control.Continue.Types: ContinueT :: m (Either e a, f (ContinueT e f m a)) -> ContinueT e f m a
- Control.Continue.Types: instance (Functor f, Monad m) => Functor (ContinueT e f m)
- Control.Continue.Types: instance (Monad m, Monoid e, Plus f) => Alternative (ContinueT e f m)
- Control.Continue.Types: instance (Monad m, Monoid e, Plus f) => Monad (ContinueT e f m)
- Control.Continue.Types: instance (Monad m, Monoid e, Plus f) => MonadContinue e f (ContinueT e f m)
- Control.Continue.Types: instance (Monad m, Monoid e, Plus f) => MonadError e (ContinueT e f m)
- Control.Continue.Types: instance (Monad m, Monoid e, Plus f) => MonadPlus (ContinueT e f m)
- Control.Continue.Types: instance (Monad m, Plus f) => Applicative (ContinueT e f m)
- Control.Continue.Types: instance (MonadBase b m, Monoid e, Plus f) => MonadBase b (ContinueT e f m)
- Control.Continue.Types: instance (MonadBaseControl b m, Monoid e, Plus f) => MonadBaseControl b (ContinueT e f m)
- Control.Continue.Types: instance (MonadFix m, Monoid e, Plus f) => MonadFix (ContinueT e f m)
- Control.Continue.Types: instance (MonadIO m, Monoid e, Plus f) => MonadIO (ContinueT e f m)
- Control.Continue.Types: instance (MonadReader r m, Monoid e, Plus f) => MonadReader r (ContinueT e f m)
- Control.Continue.Types: instance (MonadState s m, Monoid e, Plus f) => MonadState s (ContinueT e f m)
- Control.Continue.Types: instance (MonadWriter l m, Monoid e, Plus f) => MonadWriter l (ContinueT e f m)
- Control.Continue.Types: instance Plus f => MonadTrans (ContinueT e f)
- Control.Continue.Types: newtype ContinueT e f m a
- Control.Continue.Types: runContinueT :: ContinueT e f m a -> m (Either e a, f (ContinueT e f m a))
- Control.Continue.Types: type Continue e f = ContinueT e f Identity
- Control.Continue.Types: type LastEx = Last SomeException
- Control.Continue.Utils: addCont_ :: MonadContinue e f m => f (m ()) -> m ()
- Control.Continue.Utils: continue :: MonadContinue e f m => Either e a -> f (Either e a) -> m a
- Control.Continue.Utils: continue_ :: MonadContinue e f m => f () -> m ()
- Control.Continue.Utils: suspend :: MonadContinue e f m => e -> m a
+ Control.Monad.Continue: (<!>) :: Alt f => f a -> f a -> f a
+ Control.Monad.Continue: ContinueT :: m (Either e a, f (ContinueT e f m a)) -> ContinueT e f m a
+ Control.Monad.Continue: class Functor f => Alt (f :: * -> *)
+ Control.Monad.Continue: class Alt f => Plus (f :: * -> *)
+ Control.Monad.Continue: instance (Functor f, Monad m) => Functor (ContinueT e f m)
+ Control.Monad.Continue: instance (Monad m, Monoid e, Plus f) => Alternative (ContinueT e f m)
+ Control.Monad.Continue: instance (Monad m, Monoid e, Plus f) => Monad (ContinueT e f m)
+ Control.Monad.Continue: instance (Monad m, Monoid e, Plus f) => MonadContinue e f (ContinueT e f m)
+ Control.Monad.Continue: instance (Monad m, Monoid e, Plus f) => MonadError e (ContinueT e f m)
+ Control.Monad.Continue: instance (Monad m, Monoid e, Plus f) => MonadPlus (ContinueT e f m)
+ Control.Monad.Continue: instance (Monad m, Plus f) => Applicative (ContinueT e f m)
+ Control.Monad.Continue: instance (MonadBase b m, Monoid e, Plus f) => MonadBase b (ContinueT e f m)
+ Control.Monad.Continue: instance (MonadBaseControl b m, Monoid e, Plus f) => MonadBaseControl b (ContinueT e f m)
+ Control.Monad.Continue: instance (MonadFix m, Monoid e, Plus f) => MonadFix (ContinueT e f m)
+ Control.Monad.Continue: instance (MonadIO m, Monoid e, Plus f) => MonadIO (ContinueT e f m)
+ Control.Monad.Continue: instance (MonadReader r m, Monoid e, Plus f) => MonadReader r (ContinueT e f m)
+ Control.Monad.Continue: instance (MonadState s m, Monoid e, Plus f) => MonadState s (ContinueT e f m)
+ Control.Monad.Continue: instance (MonadWriter l m, Monoid e, Plus f) => MonadWriter l (ContinueT e f m)
+ Control.Monad.Continue: instance Plus f => MonadTrans (ContinueT e f)
+ Control.Monad.Continue: many :: (Alt f, Applicative f) => f a -> f [a]
+ Control.Monad.Continue: mapContinueT :: (Functor f, Monad n) => (forall a. m a -> n a) -> ContinueT e f m a -> ContinueT e f n a
+ Control.Monad.Continue: newtype ContinueT e f m a
+ Control.Monad.Continue: orElse :: (Alt f, Monad m, Monoid e) => ContinueT e f m a -> ContinueT e f m a -> ContinueT e f m a
+ Control.Monad.Continue: runContinue :: Continue e f a -> (Either e a, f (Continue e f a))
+ Control.Monad.Continue: runContinueT :: ContinueT e f m a -> m (Either e a, f (ContinueT e f m a))
+ Control.Monad.Continue: some :: (Alt f, Applicative f) => f a -> f [a]
+ Control.Monad.Continue: type Continue e f = ContinueT e f Identity
+ Control.Monad.Continue: type LastEx = Last SomeException
+ Control.Monad.Continue: zero :: Plus f => f a
+ Control.Monad.Continue.Class: addCont :: MonadContinue e f m => Either e a -> f (m a) -> m a
+ Control.Monad.Continue.Class: addCont_ :: MonadContinue e f m => f (m ()) -> m ()
+ Control.Monad.Continue.Class: class (Plus f, Monad m, Monoid e) => MonadContinue e f m | m -> e, m -> f
+ Control.Monad.Continue.Class: continue :: MonadContinue e f m => Either e a -> f (Either e a) -> m a
+ Control.Monad.Continue.Class: continue_ :: MonadContinue e f m => f () -> m ()
+ Control.Monad.Continue.Class: instance (MonadContinue e f m, Monoid l) => MonadContinue e f (WriterT l m)
+ Control.Monad.Continue.Class: instance MonadContinue e f m => MonadContinue e f (IdentityT m)
+ Control.Monad.Continue.Class: instance MonadContinue e f m => MonadContinue e f (MaybeT m)
+ Control.Monad.Continue.Class: instance MonadContinue e f m => MonadContinue e f (ReaderT r m)
+ Control.Monad.Continue.Class: instance MonadContinue e f m => MonadContinue e f (StateT s m)
+ Control.Monad.Continue.Class: suspend :: MonadContinue e f m => e -> m a
+ Control.Monad.Continue.Class: suspendWith :: MonadContinue e f m => f (m a) -> m a

Files

− Control/Continue.hs
@@ -1,24 +0,0 @@--- |--- Module:     Control.Continue--- Copyright:  (c) 2012 Ertugrul Soeylemez--- License:    BSD3--- Maintainer: Ertugrul Soeylemez <es@ertes.de>------ Proxy to the various modules of the continue package.--module Control.Continue-    ( -- * Continue modules-      module Control.Continue.Class,-      module Control.Continue.Types,-      module Control.Continue.Utils,--      -- * Convenience reexports-      Alt(..),-      Plus(..)-    )-    where--import Control.Continue.Class-import Control.Continue.Types-import Control.Continue.Utils-import Data.Functor.Plus
− Control/Continue/Class.hs
@@ -1,77 +0,0 @@--- |--- Module:     Control.Continue.Class--- Copyright:  (c) 2013 Ertugrul Soeylemez--- License:    BSD3--- Maintainer: Ertugrul Soeylemez <es@ertes.de>--{-# LANGUAGE UndecidableInstances #-}--module Control.Continue.Class-    ( -- * Suspension-      MonadContinue(..)-    )-    where--import qualified Control.Monad.Trans.State.Strict as Ss-import qualified Control.Monad.Trans.Writer.Strict as Ws-import Control.Monad.Trans.Identity-import Control.Monad.Trans.Maybe-import Control.Monad.Trans.Reader-import Control.Monad.Trans.State.Lazy-import Control.Monad.Trans.Writer.Lazy-import Data.Monoid-import Data.Functor.Plus----- | Type class for monads that support suspension and continuation--- spots.--class (Plus f, Monad m, Monoid e) => MonadContinue e f m | m -> e, m -> f where-    -- | Add the given set of continuations and possibly suspend.-    addCont ::-        Either e a       -- ^ What to return now (left suspends).-        -> f (m a)  -- ^ What to run and return when reentering.-        -> m a--instance (MonadContinue e f m) => MonadContinue e f (IdentityT m) where-    addCont mx c = IdentityT $ addCont mx (fmap runIdentityT c)--instance (MonadContinue e f m) => MonadContinue e f (MaybeT m) where-    addCont mx c =-        MaybeT $-            addCont (fmap Just mx) (fmap runMaybeT c)--instance (MonadContinue e f m) => MonadContinue e f (ReaderT r m) where-    addCont mx c =-        ReaderT $ \env ->-            addCont mx (fmap (flip runReaderT env) c)---- | Time travel warning: Captures the current state, not the state at--- reentry!--instance (MonadContinue e f m) => MonadContinue e f (StateT s m) where-    addCont mx c =-        StateT $ \s ->-            addCont (fmap (flip (,) s) mx)-                    (fmap (flip runStateT s) c)---- | Time travel warning: Captures the current state, not the state at--- reentry!--instance (MonadContinue e f m) => MonadContinue e f (Ss.StateT s m) where-    addCont mx c =-        Ss.StateT $ \s ->-            addCont (fmap (flip (,) s) mx)-                    (fmap (flip Ss.runStateT s) c)--instance (MonadContinue e f m, Monoid l) => MonadContinue e f (WriterT l m) where-    addCont mx c =-        WriterT $-            addCont (fmap (flip (,) mempty) mx)-                    (fmap runWriterT c)--instance (MonadContinue e f m, Monoid l) => MonadContinue e f (Ws.WriterT l m) where-    addCont mx c =-        Ws.WriterT $-            addCont (fmap (flip (,) mempty) mx)-                    (fmap Ws.runWriterT c)
− Control/Continue/Types.hs
@@ -1,174 +0,0 @@--- |--- Module:     Control.Continue.Types--- Copyright:  (c) 2012 Ertugrul Soeylemez--- License:    BSD3--- Maintainer: Ertugrul Soeylemez <es@ertes.de>------ Types used in the continue library.--{-# LANGUAGE UndecidableInstances #-}--module Control.Continue.Types-    ( -- * Suspendable computations-      ContinueT(..),-      Continue,--      -- * Convenience types-      LastEx-    )-    where--import qualified Data.Bifunctor as Bi-import Control.Applicative-import Control.Arrow-import Control.Continue.Class-import Control.Exception (SomeException)-import Control.Monad-import Control.Monad.Base-import Control.Monad.Error.Class-import Control.Monad.Identity-import Control.Monad.Reader.Class-import Control.Monad.State.Class-import Control.Monad.Trans-import Control.Monad.Trans.Control-import Control.Monad.Writer.Class-import Data.Functor.Plus-import Data.Monoid----- | This monad transformer adds continuations under @f@ and @e@-typed--- suspensions to @m@.--newtype ContinueT e f m a =-    ContinueT {-      runContinueT :: m (Either e a, f (ContinueT e f m a))-    }--instance (Monad m, Monoid e, Plus f) => Alternative (ContinueT e f m) where-    empty = ContinueT (return (Left mempty, zero))--    ContinueT c1 <|> ContinueT c2 =-        ContinueT $ do-            (mx1, cf1) <- c1-            (mx2, cf2) <- c2-            let mx = either (\ex1 -> Bi.first (ex1 <>) mx2) Right mx1-            return (mx, cf1 <!> cf2)--instance (Monad m, Plus f) => Applicative (ContinueT e f m) where-    pure x = ContinueT (return (Right x, zero))--    ContinueT cf <*> rx@(ContinueT cx) =-        ContinueT $ do-            (mf, cff) <- cf-            case mf of-              Left ex -> return (Left ex, fmap (<*> rx) cff)-              Right f -> do-                  (mx, cfx) <- cx-                  return (fmap f mx, fmap (fmap f) cfx)--instance (Functor f, Monad m) => Functor (ContinueT e f m) where-    fmap f (ContinueT c) = ContinueT (liftM (fmap f *** fmap (fmap f)) c)--instance (Monad m, Monoid e, Plus f) => Monad (ContinueT e f m) where-    return = pure--    ContinueT c >>= f =-        ContinueT $ do-            (mx, cfx') <- c-            let cfx = fmap (>>= f) cfx'-            case mx of-              Left ex -> return (Left ex, cfx)-              Right x -> do-                  (my, cfy) <- runContinueT (f x)-                  return (my, cfx <!> cfy)--    fail _ = ContinueT (return (Left mempty, zero))--instance (MonadBase b m, Monoid e, Plus f) => MonadBase b (ContinueT e f m) where-    liftBase = liftBaseDefault--instance (MonadBaseControl b m, Monoid e, Plus f) => MonadBaseControl b (ContinueT e f m) where-    data StM (ContinueT e f m) a =-        StContinueT (StM m (Either e a, f (ContinueT e f m a)))--    liftBaseWith k =-        ContinueT $ do-            x <--                liftBaseWith $ \runB ->-                    k $ \(ContinueT c) ->-                        liftM StContinueT (runB c)-            return (Right x, zero)--    restoreM (StContinueT s) = ContinueT (restoreM s)--instance (Monad m, Monoid e, Plus f) => MonadContinue e f (ContinueT e f m) where-    addCont mx cf = ContinueT (return (mx, cf))--instance (Monad m, Monoid e, Plus f) => MonadError e (ContinueT e f m) where-    throwError ex = ContinueT (return (Left ex, zero))-    catchError (ContinueT c) h =-        ContinueT $ do-            (mx, cf) <- c-            case mx of-              Left ex -> do-                  (mxh, cfh) <- runContinueT (h ex)-                  return (mxh, cf <!> cfh)-              Right _ -> return (mx, cf)---- | Warning:  If feedback is broken by suspension you get a run-time--- error.--instance (MonadFix m, Monoid e, Plus f) => MonadFix (ContinueT e f m) where-    mfix f =-        ContinueT . mfix $ \ ~(mx, _) ->-            runContinueT . f .-            either (const $ error "Feedback broken by suspension") id $ mx--instance (MonadIO m, Monoid e, Plus f) => MonadIO (ContinueT e f m) where-    liftIO = ContinueT . liftM (\x -> (Right x, zero)) . liftIO--instance (Monad m, Monoid e, Plus f) => MonadPlus (ContinueT e f m) where-    mzero = empty-    mplus = (<|>)--instance (MonadReader r m, Monoid e, Plus f) => MonadReader r (ContinueT e f m) where-    ask = lift ask-    local f (ContinueT c) = ContinueT (local f c)-    reader = ContinueT . liftM (\x -> (Right x, zero)) . reader--instance (MonadState s m, Monoid e, Plus f) => MonadState s (ContinueT e f m) where-    get = lift get-    put = lift . put-    state = lift . state--instance (Plus f) => MonadTrans (ContinueT e f) where-    lift = ContinueT . liftM (\x -> (Right x, zero))--instance (MonadWriter l m, Monoid e, Plus f) => MonadWriter l (ContinueT e f m) where-    listen (ContinueT c) =-        ContinueT $ do-            ((mx, cf), w) <- listen c-            let addLog x = (x, w)-            return (fmap addLog mx, fmap (fmap addLog) cf)--    pass (ContinueT c) =-        ContinueT . pass $ do-            (mx, cf') <- c-            let cf = fmap (fmap fst) cf'-            case mx of-              Left ex      -> return ((Left ex, cf), id)-              Right (x, f) -> return ((Right x, cf), f)--    tell = lift . tell-    writer = lift . writer----- | 'ContinueT' over 'Identity'.--type Continue e f = ContinueT e f Identity----- | Type alias for the common case of using @'Last' 'SomeException'@ as--- the suspension monoid.--type LastEx = Last SomeException
− Control/Continue/Utils.hs
@@ -1,51 +0,0 @@--- |--- Module:     Control.Continue.Utils--- Copyright:  (c) 2012 Ertugrul Soeylemez--- License:    BSD3--- Maintainer: Ertugrul Soeylemez <es@ertes.de>------ Suspension/continuation utilities.--module Control.Continue.Utils-    ( -- * Basic utilities-      addCont_,-      continue,-      continue_,-      suspend-    )-    where--import Control.Continue.Class-import Data.Functor.Plus----- | Add the given set of continuations without suspending.--addCont_ :: (MonadContinue e f m) => f (m ()) -> m ()-addCont_ = addCont (Right ())----- | Allow to continue here with the given value.--continue ::-    (MonadContinue e f m)-    => Either e a      -- ^ What to return now (left suspends).-    -> f (Either e a)  -- ^ What to return when reentering (left suspends).-    -> m a-continue mx = addCont mx . fmap (\mx -> addCont mx zero)----- | Allow to continue here.--continue_ ::-    (MonadContinue e f m)-    => f ()  -- ^ Reentering key.-    -> m ()-continue_ = addCont (Right ()) . fmap (const $ return ())----- | Suspend with the given value.  Does not register any continuation--- spots.  Note that @suspend mempty@ is equivalent to @empty@.--suspend :: (MonadContinue e f m) => e -> m a-suspend ex = addCont (Left ex) zero
+ Control/Monad/Continue.hs view
@@ -0,0 +1,305 @@+-- |+-- Module:     Control.Monad.Continue+-- Copyright:  (c) 2012 Ertugrul Soeylemez+-- License:    BSD3+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>+--+-- This library implements a monad transformer for suspendable+-- computations, similar and related to free comonads.  It allows to+-- write continuation-based web frameworks, command line applications+-- and similar interfaces, where you want to reenter a computation at+-- arbitrary spots.++{-# LANGUAGE UndecidableInstances #-}++module Control.Monad.Continue+    ( -- $doc++      -- * Continue+      Continue,+      runContinue,++      -- * ContinueT+      ContinueT(..),+      mapContinueT,++      -- * Combinators+      orElse,++      -- * Convenience types+      LastEx,++      -- * Reexports+      module Control.Monad.Continue.Class,+      Alt(..),+      Plus(..)+    )+    where++import qualified Data.Bifunctor as Bi+import Control.Applicative+import Control.Arrow+import Control.Exception (SomeException)+import Control.Monad+import Control.Monad.Base+import Control.Monad.Continue.Class+import Control.Monad.Error.Class+import Control.Monad.Fix+import Control.Monad.Identity+import Control.Monad.Reader.Class+import Control.Monad.State.Class+import Control.Monad.Trans+import Control.Monad.Trans.Control+import Control.Monad.Writer.Class+import Data.Functor.Plus+import Data.Monoid+++-- | This monad transformer adds continuations under @f@ and @e@-typed+-- suspensions to @m@.++newtype ContinueT e f m a =+    ContinueT {+      runContinueT :: m (Either e a, f (ContinueT e f m a))+    }++instance (Monad m, Monoid e, Plus f) => Alternative (ContinueT e f m) where+    empty = ContinueT (return (Left mempty, zero))++    ContinueT c1 <|> ContinueT c2 =+        ContinueT $ do+            (mx1, cf1) <- c1+            (mx2, cf2) <- c2+            let mx = either (\ex1 -> Bi.first (ex1 <>) mx2) Right mx1+            return (mx, cf1 <!> cf2)++instance (Monad m, Plus f) => Applicative (ContinueT e f m) where+    pure x = ContinueT (return (Right x, zero))++    ContinueT cf <*> rx@(ContinueT cx) =+        ContinueT $ do+            (mf, cff) <- cf+            case mf of+              Left ex -> return (Left ex, fmap (<*> rx) cff)+              Right f -> do+                  (mx, cfx) <- cx+                  return (fmap f mx, fmap (fmap f) cfx)++instance (Functor f, Monad m) => Functor (ContinueT e f m) where+    fmap f (ContinueT c) = ContinueT (liftM (fmap f *** fmap (fmap f)) c)++instance (Monad m, Monoid e, Plus f) => Monad (ContinueT e f m) where+    return = pure++    ContinueT c >>= f =+        ContinueT $ do+            (mx, cfx') <- c+            let cfx = fmap (>>= f) cfx'+            case mx of+              Left ex -> return (Left ex, cfx)+              Right x -> do+                  (my, cfy) <- runContinueT (f x)+                  return (my, cfx <!> cfy)++    fail _ = ContinueT (return (Left mempty, zero))++instance (MonadBase b m, Monoid e, Plus f) => MonadBase b (ContinueT e f m) where+    liftBase = liftBaseDefault++instance (MonadBaseControl b m, Monoid e, Plus f) => MonadBaseControl b (ContinueT e f m) where+    data StM (ContinueT e f m) a =+        StContinueT (StM m (Either e a, f (ContinueT e f m a)))++    liftBaseWith k =+        ContinueT $ do+            x <-+                liftBaseWith $ \runB ->+                    k $ \(ContinueT c) ->+                        liftM StContinueT (runB c)+            return (Right x, zero)++    restoreM (StContinueT s) = ContinueT (restoreM s)++instance (Monad m, Monoid e, Plus f) => MonadContinue e f (ContinueT e f m) where+    addCont mx cf = ContinueT (return (mx, cf))++instance (Monad m, Monoid e, Plus f) => MonadError e (ContinueT e f m) where+    throwError ex = ContinueT (return (Left ex, zero))+    catchError (ContinueT c) h =+        ContinueT $ do+            (mx, cf) <- c+            case mx of+              Left ex -> do+                  (mxh, cfh) <- runContinueT (h ex)+                  return (mxh, cf <!> cfh)+              Right _ -> return (mx, cf)++-- | Warning: If feedback is broken by suspension you get a run-time+-- error.++instance (MonadFix m, Monoid e, Plus f) => MonadFix (ContinueT e f m) where+    mfix f =+        ContinueT . mfix $ \ ~(mx, _) ->+            runContinueT . f .+            either (const $ error "Feedback broken by suspension") id $ mx++instance (MonadIO m, Monoid e, Plus f) => MonadIO (ContinueT e f m) where+    liftIO = ContinueT . liftM (\x -> (Right x, zero)) . liftIO++instance (Monad m, Monoid e, Plus f) => MonadPlus (ContinueT e f m) where+    mzero = empty+    mplus = (<|>)++instance (MonadReader r m, Monoid e, Plus f) => MonadReader r (ContinueT e f m) where+    ask = lift ask+    local f (ContinueT c) = ContinueT (local f c)+    reader = ContinueT . liftM (\x -> (Right x, zero)) . reader++instance (MonadState s m, Monoid e, Plus f) => MonadState s (ContinueT e f m) where+    get = lift get+    put = lift . put+    state = lift . state++instance (Plus f) => MonadTrans (ContinueT e f) where+    lift = ContinueT . liftM (\x -> (Right x, zero))++instance (MonadWriter l m, Monoid e, Plus f) => MonadWriter l (ContinueT e f m) where+    listen (ContinueT c) =+        ContinueT $ do+            ((mx, cf), w) <- listen c+            let addLog x = (x, w)+            return (fmap addLog mx, fmap (fmap addLog) cf)++    pass (ContinueT c) =+        ContinueT . pass $ do+            (mx, cf') <- c+            let cf = fmap (fmap fst) cf'+            case mx of+              Left ex      -> return ((Left ex, cf), id)+              Right (x, f) -> return ((Right x, cf), f)++    tell = lift . tell+    writer = lift . writer+++-- | 'ContinueT' over 'Identity'.++type Continue e f = ContinueT e f Identity+++-- | Type alias for the common case of using @'Last' 'SomeException'@ as+-- the suspension monoid.++type LastEx = Last SomeException+++-- | Apply the given morphism to the underlying monad.++mapContinueT ::+    (Functor f, Monad n)+    => (forall a. m a -> n a)  -- ^ Monad morphism to apply.+    -> ContinueT e f m a+    -> ContinueT e f n a+mapContinueT mm (ContinueT c) =+    ContinueT $ do+        (mx, cf) <- mm c+        return (mx, fmap (mapContinueT mm) cf)+++-- | Similar to '<|>', but tries the second computation only if the+-- first one actually suspends.  Note that not running the second+-- computation also means that it can't register reentry spots.+--+-- As an operator this function is infixr 3.++orElse ::+    (Alt f, Monad m, Monoid e)+    => ContinueT e f m a+    -> ContinueT e f m a+    -> ContinueT e f m a+orElse (ContinueT c1) (ContinueT c2) =+    ContinueT $ do+        (mx1, cf1) <- c1+        case mx1 of+          Left ex1 -> do+              (mx2, cf2) <- c2+              return (Bi.first (ex1 <>) mx2, cf1 <!> cf2)+          Right _ -> return (mx1, cf1)++infixr 3 `orElse`+++-- | Run the given 'Continue' computation.++runContinue :: Continue e f a -> (Either e a, f (Continue e f a))+runContinue = runIdentity . runContinueT+++{- $doc++A computation of type @'ContinueT' e f m a@ is a computation that may+either conclude with a value of type @a@ or suspend with a value of type+@e@.  Before suspending or concluding it may register a set of reentry+spots of type @f (ContinueT e f m a)@.  These spots are collected and+returned along with the suspension/conclusion value:++> newtype ContinueT e f m a++To run a @ContinueT@ computation you can use the 'runContinueT'+function:++> runContinueT :: ContinueT e f m a+>              -> m (Either e a, f (ContinueT e f m a))++The result is either a suspension value of type @e@ or a conclusion of+type @a@.  In both cases you can reenter the computation at the+registered spots.  Example:++> type MyMonad = ContinueT () (Map String) Identity+>+> myComp :: MyMonad Integer+> myComp = do+>     x <- continue (Right 3) (M.singleton "x" (Right 15))+>     y <- continue (Right 4) (M.singleton "y" (Right 17))+>     return (x + y)++When you first run this computation the result will be the conclusion 3++ 4.  Since 'MyMonad' transforms to 'Identity' we can use the+convenience type alias 'Continue' and the function 'runContinue':++> type MyMonad = Continue () (Map String)+>+> runContinue myComp+> = (Right 7, reentryMap)++Along with the result you will also get a reentry map of type @Map+String (MyMonad Integer)@.  If you run the computation indexed by \"x\",+you will get the result 15 + 4.  This iteration itself will return a new+reentry map on its part.  That map will contain only the reentry spot+\"y\", because the reentry indexed by \"x\" does not register itself+again.++You can use the more general 'addCont' function to register arbitrary+reentry spots, which themselves are allowed to register new spots.  Also+In some kinds of applications you would want to combine the reentry maps+produced.  You can use the '<!>' function to do that:++> let overallReentryMap = reentryMap1 <!> reentryMap2++Since @e@ is required to be a monoid, @ContinueT@ forms a family of+alternative functors that implement choice based on suspension and+conclusion.  The computation 'empty' always suspends with 'mempty'.++> x <|> y++This computation concludes with the conclusion of either @x@ or @y@+trying them in that order, or suspends if both of them suspend.  Note+that both computations are performed to their conclusion or suspension.+This allows @y@ both to have monadic effects as well as to register+reentry points, even if @x@ concludes.++There is also a combinator 'orElse' that tries @y@ only if @x@ actually+suspends.  In that case, if @x@ concludes, then @y@ cannot register+reentry spots or have effects in the underlying monad.++-}
+ Control/Monad/Continue/Class.hs view
@@ -0,0 +1,123 @@+-- |+-- Module:     Control.Monad.Continue.Class+-- Copyright:  (c) 2013 Ertugrul Soeylemez+-- License:    BSD3+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>++{-# LANGUAGE UndecidableInstances #-}++module Control.Monad.Continue.Class+    ( -- * Suspension+      MonadContinue(..),++      -- * Basic utilities+      addCont_,+      continue,+      continue_,+      suspend,+      suspendWith+    )+    where++import qualified Control.Monad.Trans.State.Strict as Ss+import qualified Control.Monad.Trans.Writer.Strict as Ws+import Control.Monad.Trans.Identity+import Control.Monad.Trans.Maybe+import Control.Monad.Trans.Reader+import Control.Monad.Trans.State.Lazy+import Control.Monad.Trans.Writer.Lazy+import Data.Functor.Plus+import Data.Monoid+++-- | Type class for monads that support suspension and continuation+-- spots.++class (Plus f, Monad m, Monoid e) => MonadContinue e f m | m -> e, m -> f where+    -- | Add the given set of continuations and possibly suspend.+    addCont ::+        Either e a       -- ^ What to return now (left suspends).+        -> f (m a)  -- ^ What to run and return when reentering.+        -> m a++instance (MonadContinue e f m) => MonadContinue e f (IdentityT m) where+    addCont mx c = IdentityT $ addCont mx (fmap runIdentityT c)++instance (MonadContinue e f m) => MonadContinue e f (MaybeT m) where+    addCont mx c =+        MaybeT $+            addCont (fmap Just mx) (fmap runMaybeT c)++instance (MonadContinue e f m) => MonadContinue e f (ReaderT r m) where+    addCont mx c =+        ReaderT $ \env ->+            addCont mx (fmap (flip runReaderT env) c)++-- | Time travel warning: Captures the current state, not the state at+-- reentry.  Use 'ContinueT' over 'StateT' instead to fix this.++instance (MonadContinue e f m) => MonadContinue e f (StateT s m) where+    addCont mx c =+        StateT $ \s ->+            addCont (fmap (flip (,) s) mx)+                    (fmap (flip runStateT s) c)++-- | Time travel warning: Captures the current state, not the state at+-- reentry.  Use 'ContinueT' over 'StateT' instead to fix this.++instance (MonadContinue e f m) => MonadContinue e f (Ss.StateT s m) where+    addCont mx c =+        Ss.StateT $ \s ->+            addCont (fmap (flip (,) s) mx)+                    (fmap (flip Ss.runStateT s) c)++instance (MonadContinue e f m, Monoid l) => MonadContinue e f (WriterT l m) where+    addCont mx c =+        WriterT $+            addCont (fmap (flip (,) mempty) mx)+                    (fmap runWriterT c)++instance (MonadContinue e f m, Monoid l) => MonadContinue e f (Ws.WriterT l m) where+    addCont mx c =+        Ws.WriterT $+            addCont (fmap (flip (,) mempty) mx)+                    (fmap Ws.runWriterT c)+++-- | Add the given set of continuations without suspending.++addCont_ :: (MonadContinue e f m) => f (m ()) -> m ()+addCont_ = addCont (Right ())+++-- | Allow to continue here with the given value.++continue ::+    (MonadContinue e f m)+    => Either e a      -- ^ What to return now (left suspends).+    -> f (Either e a)  -- ^ What to return when reentering (left suspends).+    -> m a+continue mx = addCont mx . fmap (\mx -> addCont mx zero)+++-- | Allow to continue here.++continue_ ::+    (MonadContinue e f m)+    => f ()  -- ^ Reentering key.+    -> m ()+continue_ = addCont (Right ()) . fmap (const $ return ())+++-- | Suspend with the given value.  Does not register any continuation+-- spots.  Note that @suspend mempty@ is equivalent to @empty@.++suspend :: (MonadContinue e f m) => e -> m a+suspend ex = addCont (Left ex) zero+++-- | Suspend with 'mempty' and register the given continuations.  Note+-- that @suspendWith zero@ is equivalent to @empty@.++suspendWith :: (MonadContinue e f m) => f (m a) -> m a+suspendWith = addCont (Left mempty)
continue.cabal view
@@ -1,7 +1,7 @@ Name:          continue-Version:       0.1.1+Version:       0.2.0 Category:      Control-Synopsis:      Continuation-based user interaction monad+Synopsis:      Monads with suspension and arbitrary-spot reentry Maintainer:    Ertugrul Söylemez <es@ertes.de> Author:        Ertugrul Söylemez <es@ertes.de> Copyright:     (c) 2012 Ertugrul Söylemez@@ -15,7 +15,8 @@     This library implements a monad transformer for suspendable     computations, similar and related to free comonads.  It allows to     write continuation-based web frameworks, command line applications-    and similar interfaces.+    and similar interfaces, where you want to reenter a computation at+    arbitrary spots.  Source-repository head     type:     git@@ -34,29 +35,39 @@     Default-extensions:         FlexibleInstances         FunctionalDependencies+        RankNTypes         MultiParamTypeClasses         TypeFamilies     Other-extensions:         UndecidableInstances     GHC-Options: -W     Exposed-modules:-        Control.Continue-        Control.Continue.Class-        Control.Continue.Types-        Control.Continue.Utils+        Control.Monad.Continue+        Control.Monad.Continue.Class  -- Test-suite continue-test --     Type: exitcode-stdio-1.0 --     Build-depends: --         base >= 4.5 && < 5,+--         blaze-builder,+--         boomerang, --         conduit, --         containers, --         continue, --         http-types,+--         mtl, --         wai,---         warp+--         warp,+--         web-routes,+--         web-routes-boomerang --     Default-language: Haskell2010 --     Default-extensions:+--         FlexibleInstances+--         MultiParamTypeClasses+--         OverloadedStrings+--         TemplateHaskell+--         TypeOperators+--         UndecidableInstances --     GHC-Options: -threaded -rtsopts --     Hs-source-dirs: test --     Main-is: Main.hs