packages feed

monad-control 0.1 → 0.2

raw patch · 4 files changed

+155/−115 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Monad.Trans.Control: type Run t n o = forall b. t n b -> n (t o b)
+ Control.Monad.Trans.Control: type Run t = forall n o b. (Monad n, Monad o, Monad (t o)) => t n b -> n (t o b)
- Control.Monad.IO.Control: controlIO :: MonadControlIO m => (RunInBase m IO -> IO (m b)) -> m b
+ Control.Monad.IO.Control: controlIO :: MonadControlIO m => (RunInBase m IO -> IO (m a)) -> m a
- Control.Monad.IO.Control: liftControlIO :: MonadControlIO m => (RunInBase m IO -> IO b) -> m b
+ Control.Monad.IO.Control: liftControlIO :: MonadControlIO m => (RunInBase m IO -> IO a) -> m a
- Control.Monad.Trans.Control: control :: (Monad n, Monad m, Monad o, Monad (t m), MonadTransControl t) => (Run t n o -> m (t m a)) -> t m a
+ Control.Monad.Trans.Control: control :: (Monad m, Monad (t m), MonadTransControl t) => (Run t -> m (t m a)) -> t m a
- Control.Monad.Trans.Control: idLiftControl :: Monad m => ((forall b. m b -> m (m b)) -> m a) -> m a
+ Control.Monad.Trans.Control: idLiftControl :: Monad m => (RunInBase m m -> m a) -> m a
- Control.Monad.Trans.Control: liftControl :: (MonadTransControl t, Monad m, Monad n, Monad o) => (Run t n o -> m a) -> t m a
+ Control.Monad.Trans.Control: liftControl :: (MonadTransControl t, Monad m) => (Run t -> m a) -> t m a
- Control.Monad.Trans.Control: liftLiftControlBase :: (MonadTransControl t, Monad base, Monad m, Monad (t m)) => ((RunInBase m base -> base a) -> m a) -> ((RunInBase (t m) base -> base a) -> t m a)
+ Control.Monad.Trans.Control: liftLiftControlBase :: (MonadTransControl t, Monad (t m), Monad m, Monad base) => ((RunInBase m base -> base a) -> m a) -> ((RunInBase (t m) base -> base a) -> t m a)

Files

Control/Exception/Control.hs view
@@ -169,14 +169,14 @@                            E.handleJust p (\e → runInIO (handler e))                                           (runInIO a) -sequenceEither ∷ Monad m ⇒ Either e (m a) → m (Either e a)-sequenceEither (Left e)  = return $ Left e-sequenceEither (Right m) = liftM Right m - -------------------------------------------------------------------------------- -- ** The @try@ functions --------------------------------------------------------------------------------++sequenceEither ∷ Monad m ⇒ Either e (m a) → m (Either e a)+sequenceEither (Left e)  = return $ Left e+sequenceEither (Right m) = liftM Right m  -- |Generalized version of 'E.try'. try ∷ (MonadControlIO m, Exception e) ⇒ m a → m (Either e a)
Control/Monad/IO/Control.hs view
@@ -66,26 +66,30 @@ -- MonadControlIO -------------------------------------------------------------------------------- --- |@MonadControlIO@ is the class of 'IO'-based monads supporting an--- extra operation 'liftControlIO', enabling control operations on 'IO' to be--- lifted into the monad.+{-|+@MonadControlIO@ is the class of 'IO'-based monads supporting an+extra operation 'liftControlIO', enabling control operations on 'IO' to be+lifted into the monad.+-} class MonadIO m ⇒ MonadControlIO m where-  -- |@liftControlIO@ is a version of @liftControl@ that operates through an-  -- arbitrary stack of monad transformers directly to an inner 'IO'-  -- (analagously to how 'liftIO' is a version of @lift@).  So it can-  -- be used to lift control operations on 'IO' into any-  -- monad in 'MonadControlIO'.  For example:-  ---  -- @-  -- foo :: 'IO' a -> 'IO' a-  -- foo' :: 'MonadControlIO' m => m a -> m a-  -- foo' a = 'controlIO' $ \runInIO ->    -- runInIO :: m a -> 'IO' (m a)-  --            foo $ runInIO a         -- uses foo :: 'IO' (m a) -> 'IO' (m a)-  -- @-  liftControlIO ∷ (RunInBase m IO → IO b) → m b+  {-|+  @liftControlIO@ is a version of @liftControl@ that operates through an+  arbitrary stack of monad transformers directly to an inner 'IO'+  (analagously to how 'liftIO' is a version of @lift@).  So it can+  be used to lift control operations on 'IO' into any+  monad in 'MonadControlIO'.  For example: +  @+  foo :: 'IO' a -> 'IO' a+  foo' :: 'MonadControlIO' m => m a -> m a+  foo' a = 'controlIO' $ \runInIO ->    -- runInIO :: m a -> 'IO' (m a)+             foo $ runInIO a         -- uses foo :: 'IO' (m a) -> 'IO' (m a)+  @+  -}+  liftControlIO ∷ (RunInBase m IO → IO a) → m a+ -- | An often used composition: @controlIO = 'join' . 'liftControlIO'@-controlIO ∷ MonadControlIO m ⇒ (RunInBase m IO → IO (m b)) → m b+controlIO ∷ MonadControlIO m ⇒ (RunInBase m IO → IO (m a)) → m a controlIO = join ∘ liftControlIO  @@ -134,23 +138,26 @@ -- Convenient lifting of two common special cases of control operation types -------------------------------------------------------------------------------- --- |@liftIOOp@ is a particular application of 'liftControlIO' that allows--- lifting control operations of type @(a -> 'IO' b) -> 'IO' b@--- (e.g. @alloca@, @withMVar v@) to--- @'MonadControlIO' m => (a -> m b) -> m b@.------ @liftIOOp f = \\g -> 'controlIO' $ \runInIO -> f $ runInIO . g@+{-|+@liftIOOp@ is a particular application of 'liftControlIO' that allows+lifting control operations of type @(a -> 'IO' b) -> 'IO' b@+(e.g. @alloca@, @withMVar v@) to+@'MonadControlIO' m => (a -> m b) -> m b@. +@liftIOOp f = \\g -> 'controlIO' $ \runInIO -> f $ runInIO . g@+-} liftIOOp ∷ MonadControlIO m          ⇒ ((a → IO (m b)) → IO (m c))          → (a → m b) → m c liftIOOp f = \g → controlIO $ \runInIO → f $ runInIO ∘ g --- |@liftIOOp_@ is a particular application of 'liftControlIO' that allows--- lifting control operations of type @'IO' a -> 'IO' a@--- (e.g. @block@) to @'MonadControlIO' m => m a -> m a@.------ @liftIOOp_ f = \\m -> 'controlIO' $ \runInIO -> f $ runInIO m@+{-|+@liftIOOp_@ is a particular application of 'liftControlIO' that allows+lifting control operations of type @'IO' a -> 'IO' a@+(e.g. @block@) to @'MonadControlIO' m => m a -> m a@.++@liftIOOp_ f = \\m -> 'controlIO' $ \runInIO -> f $ runInIO m@+-} liftIOOp_ ∷ MonadControlIO m           ⇒ (IO (m a) → IO (m b))           → m a → m b
Control/Monad/Trans/Control.hs view
@@ -65,45 +65,46 @@ -- MonadTransControl -------------------------------------------------------------------------------- --- |@MonadTransControl@ is the class of monad transformers supporting an--- extra operation 'liftControl', enabling control operations (functions that--- use monadic actions as input instead of just output) to be lifted--- through the transformer.+{-|+@MonadTransControl@ is the class of monad transformers supporting an+extra operation 'liftControl', enabling control operations (functions that+use monadic actions as input instead of just output) to be lifted+through the transformer.+-} class MonadTrans t ⇒ MonadTransControl t where-  -- |@liftControl@ is used to peel off the outer layer of a transformed-  -- monadic action, allowing an transformed action @t m a@ to be-  -- treated as a base action @m b@.-  ---  -- More precisely, @liftControl@ captures the monadic state of @t@ at the-  -- point where it is bound (in @t n@), yielding a function of type-  -- @'Run' t n o = t n a -> n (t o a)@-  -- this function runs a transformed monadic action @t n a@-  -- in the base monad @n@ using the captured state, and leaves the-  -- result @t o a@ in the monad @n@ after all side effects in @n@-  -- have occurred.-  ---  -- This can be used to lift control operations with types such as-  -- @M a -> M a@ into the transformed monad @t M@:-  ---  -- @-  -- instance Monad M-  -- foo :: M a -> M a-  -- foo' :: ('MonadTransControl' t, 'Monad' (t M)) => t M a -> t M a-  -- foo' a = 'control' $ \run ->    -- run :: t M a -> M (t M a)-  --            foo $ run a       -- uses foo :: M (t M a) -> M (t M a)-  -- @-  ---  -- @liftControl@ is typically used with @m == n == o@, but is required to-  -- be polymorphic for greater type safety: for example, this type-  -- ensures that the result of running the action in @m@ has no-  -- remaining side effects in @m@.-  liftControl ∷ (Monad m, Monad n, Monad o) ⇒ (Run t n o → m a) → t m a+  {-|+  @liftControl@ is used to peel off the outer layer of a transformed+  monadic action, allowing an transformed action @t m a@ to be+  treated as a base action @m a@. -type Run t n o = ∀ b. t n b → n (t o b)+  More precisely, @liftControl@ captures the monadic state of @t@ at the+  point where it is bound (in @t m@), yielding a function of type: +  @'Run' t = forall n o b. (Monad n, Monad o) => t n b -> n (t o b)@++  This function runs a transformed monadic action @t n b@+  in the inner monad @n@ using the captured state, and leaves the+  result @t o b@ in the monad @n@ after all side effects in @n@+  have occurred.++  This can be used to lift control operations with types such as+  @M a -> M a@ into the transformed monad @t M@:++  @+  instance Monad M+  foo :: M a -> M a+  foo' :: ('MonadTransControl' t, 'Monad' (t M)) => t M a -> t M a+  foo' a = 'control' $ \run ->    -- run :: t M a -> M (t M a)+             foo $ run a       -- uses foo :: M (t M a) -> M (t M a)+  @+  -}+  liftControl ∷ Monad m ⇒ (Run t → m a) → t m a++type Run t = ∀ n o b. (Monad n, Monad o, Monad (t o)) ⇒ t n b → n (t o b)+ -- | An often used composition: @control = 'join' . 'liftControl'@-control ∷ (Monad n, Monad m, Monad o, Monad (t m), MonadTransControl t)-        ⇒ (Run t n o → m (t m a)) → t m a+control ∷ (Monad m, Monad (t m), MonadTransControl t)+        ⇒ (Run t → m (t m a)) → t m a control = join ∘ liftControl  @@ -121,13 +122,12 @@ instance MonadTransControl ListT      where liftControl = liftControlNoState ListT  runListT instance MonadTransControl MaybeT     where liftControl = liftControlNoState MaybeT runMaybeT -liftControlNoState ∷ (Monad m, Monad n, Monad o, Monad f)-                   ⇒ (∀ a p. p (f a) → t p a)-                   → (∀ a. t m a → m (f a))-                   → (Run t m o → n b) → t n b-liftControlNoState mkT runT = \f → mkT $ liftM return $ f run-    where-      run = liftM (mkT ∘ return) ∘ runT+liftControlNoState ∷ (Monad m, Monad f)+                   ⇒ (∀ p b. p (f b) → t p b)+                   → (∀ n b. t n b → n (f b))+                   → (Run t → m a) → t m a+liftControlNoState mkT runT = \f → mkT $ liftM return $ f $+                                     liftM (mkT ∘ return) ∘ runT  instance MonadTransControl (ReaderT r) where     liftControl f =@@ -178,51 +178,84 @@ -- Lifting -------------------------------------------------------------------------------- --- |@idLiftControl@ acts as the \"identity\" 'liftControl' operation from a monad--- @m@ to itself.------ @idLiftControl f = f $ liftM return@------ It serves as the base case for a class like @MonadControlIO@, which--- allows control operations in some base monad (here @IO@) to be--- lifted through arbitrary stacks of zero or more monad transformers--- in one call.  For example, "Control.Monad.IO.Control" defines------ @--- class MonadIO m => MonadControlIO m where---     liftControlIO :: (RunInBase m IO -> IO b) -> m b--- @------ @--- instance MonadControlIO IO where---     liftControlIO = idLiftControl--- @-idLiftControl ∷ Monad m ⇒ ((∀ b. m b → m (m b)) → m a) → m a+{-|+@idLiftControl@ acts as the \"identity\" 'liftControl' operation from a monad+@m@ to itself.++@idLiftControl f = f $ liftM return@++It serves as the base case for a class like @MonadControlIO@, which+allows control operations in some base monad (here @IO@) to be+lifted through arbitrary stacks of zero or more monad transformers+in one call.  For example, "Control.Monad.IO.Control" defines:++@+class MonadIO m => MonadControlIO m where+    liftControlIO :: (RunInBase m IO -> IO b) -> m b+@++@+instance MonadControlIO IO where+    liftControlIO = idLiftControl+@+-}+idLiftControl ∷ Monad m ⇒ (RunInBase m m → m a) → m a idLiftControl f = f $ liftM return  type RunInBase m base = ∀ b. m b → base (m b) --- |@liftLiftControlBase@ is used to compose two 'liftControl' operations:--- the outer provided by a 'MonadTransControl' instance,--- and the inner provided as the argument.------ It satisfies @'liftLiftControlBase' 'idLiftControl' == 'liftControl'@.------ It serves as the induction step of a @MonadControlIO@-like class.  For--- example, "Control.Monad.IO.Control" defines------ @--- instance MonadControlIO m => MonadControlIO (StateT s m) where---     liftControlIO = liftLiftControlBase liftControlIO--- @------ using the 'MonadTransControl' instance of @'StateT' s@.-liftLiftControlBase ∷ (MonadTransControl t, Monad base, Monad m, Monad (t m))+{-|+@liftLiftControlBase@ is used to compose two 'liftControl' operations:+the outer provided by a 'MonadTransControl' instance,+and the inner provided as the argument.++It satisfies @'liftLiftControlBase' 'idLiftControl' == 'liftControl'@.++It serves as the induction step of a @MonadControlIO@-like class.  For+example, "Control.Monad.IO.Control" defines:++@+instance MonadControlIO m => MonadControlIO (StateT s m) where+    liftControlIO = liftLiftControlBase liftControlIO+@++using the 'MonadTransControl' instance of @'StateT' s@.++The following shows the recursive structure of 'liftControlIO' applied to a+stack of three monad transformers with IO as the base monad: @t1 (t2 (t3 IO)) a@:++@+liftControlIO+ =+ 'liftLiftControlBase' $+   'liftLiftControlBase' $+     'liftLiftControlBase' $+       'idLiftControl'+  =+   \\f -> 'liftControl' $ \\run1 ->     -- Capture state of t1, run1 :: 'Run' t1+           'liftControl' $ \\run2 ->   -- Capture state of t2, run2 :: 'Run' t2+             'liftControl' $ \\run3 -> -- Capture state of t3, run3 :: 'Run' t3+               let run :: 'RunInBase' (t1 (t2 (t3 IO))) IO+                   run = -- Restore state+                         'liftM' ('join' . 'lift') -- :: IO (           t2 (t3 IO) (t1 (t2 (t3 IO)) a))   -> IO (                       t1 (t2 (t3 IO)) a)+                       . 'liftM' ('join' . 'lift') -- :: IO (    t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)))  -> IO (           t2 (t3 IO) (t1 (t2 (t3 IO)) a))+                         -- Identity conversion+                       . 'liftM' ('join' . 'lift') -- :: IO (IO (t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)))) -> IO (    t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)))+                       . 'liftM' 'return'        -- :: IO (    t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)))  -> IO (IO (t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a))))+                         -- Run     (computation to run:)                              (inner monad:) (restore computation:)+                       . run3 -- ::         t3 IO  (t2 (t3 IO) (t1 (t2 (t3 IO)) a)) ->        IO      (t3 IO (t2 (t3 IO) (t1 (t2 (t3 IO)) a)))+                       . run2 -- ::     t2 (t3 IO)             (t1 (t2 (t3 IO)) a)  ->     t3 IO             (t2 (t3 IO) (t1 (t2 (t3 IO)) a))+                       . run1 -- :: t1 (t2 (t3 IO))                             a   -> t2 (t3 IO)                        (t1 (t2 (t3 IO)) a)+               in f run+@+-}+liftLiftControlBase ∷ (MonadTransControl t, Monad (t m), Monad m, Monad base)                     ⇒ ((RunInBase m     base → base a) →   m a) -- ^ @liftControlBase@ operation                     → ((RunInBase (t m) base → base a) → t m a)-liftLiftControlBase lftCtrlBase = \f → liftControl $ \run →+liftLiftControlBase lftCtrlBase = \f → liftControl $ \run1 →                                          lftCtrlBase $ \runInBase →-                                           f $ liftM (join ∘ lift) ∘ runInBase ∘ run+                                           let run = liftM (join ∘ lift) ∘ runInBase ∘ run1+                                           in f run   -- The End ---------------------------------------------------------------------
monad-control.cabal view
@@ -1,5 +1,5 @@ Name:                monad-control-Version:             0.1+Version:             0.2 Synopsis:            Lift control operations, like exception catching, through monad transformers Description:   This package defines the type class @MonadControlIO@, a subset of@@ -18,8 +18,8 @@   The package includes a copy of the @monad-peel@ testsuite written by Anders Kaseorg.   The tests can be performed by using @cabal test@.   .-  The following @critertion@ based benchmark shows that @monad-control@ is about-  2 times faster than @monad-peel@:+  The following @critertion@ based benchmark shows that @monad-control@+  is on average about 2.5 times faster than @monad-peel@:   .   <http://code.haskell.org/~basvandijk/code/bench-monad-peel-control>