mmorph 1.0.6 → 1.0.7
raw patch · 2 files changed
+30/−26 lines, 2 filesdep ~basedep ~mtlPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base, mtl
API changes (from Hackage documentation)
+ Control.Monad.Morph: infixl 2 |>=
+ Control.Monad.Morph: infixr 2 =<|
- Control.Monad.Morph: hoist :: (MFunctor t, Monad m) => (forall a. m a -> n a) -> t m b -> t n b
+ Control.Monad.Morph: hoist :: (MFunctor t, Functor m) => (forall a. m a -> n a) -> t m b -> t n b
Files
- mmorph.cabal +1/−1
- src/Control/Monad/Morph.hs +29/−25
mmorph.cabal view
@@ -1,5 +1,5 @@ Name: mmorph-Version: 1.0.6+Version: 1.0.7 Cabal-Version: >= 1.8.0.2 Build-Type: Simple License: BSD3
src/Control/Monad/Morph.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, RankNTypes #-}+{-# LANGUAGE CPP, RankNTypes, PolyKinds #-} {-| A monad morphism is a natural transformation: @@ -8,13 +8,13 @@ > morph $ do x <- m = do x <- morph m > f x morph (f x)-> +> > morph (return x) = return x ... which are equivalent to the following two functor laws: > morph . (f >=> g) = morph . f >=> morph . g-> +> > morph . return = return Examples of monad morphisms include:@@ -81,7 +81,7 @@ import qualified Control.Monad.Trans.Reader as R import qualified Control.Monad.Trans.RWS.Lazy as RWS import qualified Control.Monad.Trans.RWS.Strict as RWS'-import qualified Control.Monad.Trans.State.Lazy as S +import qualified Control.Monad.Trans.State.Lazy as S import qualified Control.Monad.Trans.State.Strict as S' import qualified Control.Monad.Trans.Writer.Lazy as W' import qualified Control.Monad.Trans.Writer.Strict as W@@ -100,14 +100,18 @@ {-| A functor in the category of monads, using 'hoist' as the analog of 'fmap': > hoist (f . g) = hoist f . hoist g-> +> > hoist id = id -} class MFunctor t where {-| Lift a monad morphism from @m@ to @n@ into a monad morphism from @(t m)@ to @(t n)@ -}- hoist :: (Monad m) => (forall a . m a -> n a) -> t m b -> t n b+#if MIN_VERSION_base(4,8,0)+ hoist :: Functor m => (forall a . m a -> n a) -> t m b -> t n b+#else+ hoist :: Monad m => (forall a . m a -> n a) -> t m b -> t n b+#endif instance MFunctor (E.ErrorT e) where hoist nat m = E.ErrorT (nat (E.runErrorT m))@@ -167,9 +171,9 @@ analog of 'return' and 'embed' as the analog of ('=<<'): > embed lift = id-> +> > embed f (lift m) = f m-> +> > embed g (embed f t) = embed (\m -> embed g (f m)) t -} class (MFunctor t, MonadTrans t) => MMonad t where@@ -231,7 +235,7 @@ {-# INLINABLE (|>=) #-} instance (E.Error e) => MMonad (E.ErrorT e) where- embed f m = E.ErrorT (do + embed f m = E.ErrorT (do x <- E.runErrorT (f (E.runErrorT m)) return (case x of Left e -> Left e@@ -239,7 +243,7 @@ Right (Right a) -> Right a ) ) instance MMonad (Ex.ExceptT e) where- embed f m = Ex.ExceptT (do + embed f m = Ex.ExceptT (do x <- Ex.runExceptT (f (Ex.runExceptT m)) return (case x of Left e -> Left e@@ -286,7 +290,7 @@ Imagine that some library provided the following 'S.State' code: > import Control.Monad.Trans.State-> +> > tick :: State Int () > tick = modify (+1) @@ -313,23 +317,23 @@ to be any monad: > import Data.Functor.Identity-> +> > generalize :: (Monad m) => Identity a -> m a > generalize m = return (runIdentity m) ... which we can 'hoist' to change @tick@'s base monad: > hoist :: (Monad m, MFunctor t) => (forall a . m a -> n a) -> t m b -> t n b-> +> > hoist generalize :: (Monad m, MFunctor t) => t Identity b -> t m b-> +> > hoist generalize tick :: (Monad m) => StateT Int m () This lets us mix @tick@ alongside 'IO' using 'lift': > import Control.Monad.Morph > import Control.Monad.Trans.Class-> +> > tock :: StateT Int IO () > tock = do > hoist generalize tick :: (Monad m) => StateT Int m ()@@ -348,29 +352,29 @@ morphism laws: > generalize (return x)-> +> > -- Definition of 'return' for the Identity monad > = generalize (Identity x)-> +> > -- Definition of 'generalize' > = return (runIdentity (Identity x))-> +> > -- runIdentity (Identity x) = x > = return x > generalize $ do x <- m > f x-> +> > -- Definition of (>>=) for the Identity monad > = generalize (f (runIdentity m))-> +> > -- Definition of 'generalize' > = return (runIdentity (f (runIdentity m)))-> +> > -- Monad law: Left identity > = do x <- return (runIdentity m) > return (runIdentity (f x))-> +> > -- Definition of 'generalize' in reverse > = do x <- generalize m > generalize (f x)@@ -384,7 +388,7 @@ For example, we might want to combine the following @save@ function: > import Control.Monad.Trans.Writer-> +> > -- i.e. :: StateT Int (WriterT [Int] Identity) () > save :: StateT Int (Writer [Int]) () > save = do@@ -405,7 +409,7 @@ generalizing @save@'s base monad: > import Control.Monad-> +> > program :: StateT Int (WriterT [Int] IO) () > program = replicateM_ 4 $ do > hoist lift tock@@ -429,7 +433,7 @@ > import Control.Exception > import Control.Monad.Trans.Class > import Control.Monad.Trans.Error-> +> > check :: IO a -> ErrorT IOException IO a > check io = ErrorT (try io)