packages feed

MHask 0.1.0.0 → 0.2.0.0

raw patch · 13 files changed

+227/−126 lines, 13 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

- MHask.Util: (~>) :: (Monad a, Monad b, Monad c) => (a ~> b) -> (b ~> c) -> (a ~> c)
+ MHask.Util: (~<~) :: (Monad a, Monad b, Monad c) => (c <~ b) -> (b <~ a) -> (c <~ a)
+ MHask.Util: (~>~) :: (Monad a, Monad b, Monad c) => (a ~> b) -> (b ~> c) -> (a ~> c)
- MHask.Comonad: class Copointed t => Comonad t where extend f = duplicate ~> fmap f duplicate = extend id
+ MHask.Comonad: class Copointed t => Comonad t where duplicate = extend id extend f = fmap f ~<~ duplicate
- MHask.Comonad: duplicate :: (Comonad t, Monad m, Monad (t m), Monad (t (t m))) => t m ~> t (t m)
+ MHask.Comonad: duplicate :: (Comonad t, Monad m) => t (t m) <~ t m
- MHask.Comonad: extend :: (Comonad t, Monad m, Monad n, Monad (t m), Monad (t n)) => (t m ~> n) -> (t m ~> t n)
+ MHask.Comonad: extend :: (Comonad t, Monad m, Monad n) => (m <~ t n) -> (t m <~ t n)
- MHask.Copointed: extract :: (Copointed t, Monad m, Monad (t m)) => t m ~> m
+ MHask.Copointed: extract :: (Copointed t, Monad m) => m <~ t m
- MHask.Functor: fmap :: (Functor t, Monad m, Monad n, Monad (t m), Monad (t n)) => (m ~> n) -> (t m ~> t n)
+ MHask.Functor: fmap :: (Functor t, Monad m, Monad n) => (m ~> n) -> (t m ~> t n)
- MHask.Indexed.Comonad: class IxCopointed t => IxComonad t where iextend f = iduplicate ~> imap f iduplicate = iextend id
+ MHask.Indexed.Comonad: class IxCopointed t => IxComonad t where iduplicate = iextend id iextend f = imap f ~<~ iduplicate
- MHask.Indexed.Comonad: iduplicate :: (IxComonad t, Monad m, Monad (t i k m), Monad (t i j (t j k m))) => t i k m ~> t i j (t j k m)
+ MHask.Indexed.Comonad: iduplicate :: (IxComonad t, Monad m) => t i j (t j k m) <~ t i k m
- MHask.Indexed.Comonad: iextend :: (IxComonad t, Monad m, Monad n, Monad (t i j m), Monad (t j k n), Monad (t i k m)) => (t j k m ~> n) -> (t i k m ~> t i j n)
+ MHask.Indexed.Comonad: iextend :: (IxComonad t, Monad m, Monad n) => (m <~ t j k n) -> (t i j m <~ t i k n)
- MHask.Indexed.Copointed: iextract :: (IxCopointed t, Monad m, Monad (t i i m)) => t i i m ~> m
+ MHask.Indexed.Copointed: iextract :: (IxCopointed t, Monad m) => m <~ t i i m
- MHask.Indexed.Functor: imap :: (IxFunctor t, Monad m, Monad n, Monad (t i j m), Monad (t i j n)) => (m ~> n) -> (t i j m ~> t i j n)
+ MHask.Indexed.Functor: imap :: (IxFunctor t, Monad m, Monad n) => (m ~> n) -> (t i j m ~> t i j n)
- MHask.Indexed.Monad: class IxPointed t => IxMonad t where ijoin = ibind id ibind f = imap f ~> ijoin
+ MHask.Indexed.Monad: class IxPointed t => IxMonad t where ijoin = ibind id ibind f = imap f ~>~ ijoin
- MHask.Indexed.Monad: ibind :: (IxMonad t, Monad m, Monad (t i j m), Monad n, Monad (t j k n)) => (m ~> t j k n) -> (t i j m ~> t i k n)
+ MHask.Indexed.Monad: ibind :: (IxMonad t, Monad m, Monad n) => (m ~> t j k n) -> (t i j m ~> t i k n)
- MHask.Indexed.Monad: ijoin :: (IxMonad t, Monad m, Monad (t i j (t j k m)), Monad (t i k m)) => t i j (t j k m) ~> t i k m
+ MHask.Indexed.Monad: ijoin :: (IxMonad t, Monad m) => t i j (t j k m) ~> t i k m
- MHask.Indexed.Pointed: ireturn :: (IxPointed t, Monad m, Monad (t i i m)) => m ~> t i i m
+ MHask.Indexed.Pointed: ireturn :: (IxPointed t, Monad m) => m ~> t i i m
- MHask.Monad: bind :: (Monad t, Monad m, Monad (t m), Monad n, Monad (t n)) => (m ~> t n) -> (t m ~> t n)
+ MHask.Monad: bind :: (Monad t, Monad m, Monad n) => (m ~> t n) -> (t m ~> t n)
- MHask.Monad: class Pointed t => Monad t where join = bind id bind f = fmap f ~> join
+ MHask.Monad: class Pointed t => Monad t where join = bind id bind f = fmap f ~>~ join
- MHask.Monad: join :: (Monad t, Monad m, Monad (t m), Monad (t (t m))) => t (t m) ~> t m
+ MHask.Monad: join :: (Monad t, Monad m) => t (t m) ~> t m
- MHask.Pointed: return :: (Pointed t, Monad m, Monad (t m)) => (m ~> t m)
+ MHask.Pointed: return :: (Pointed t, Monad m) => m ~> t m
- MHask.Util: type (~>) m n = forall x. m x -> n x
+ MHask.Util: type (<~) m n = n ~> m

Files

MHask.cabal view
@@ -1,36 +1,48 @@--- Initial MHask.cabal generated by cabal init.  For further documentation,---  see http://haskell.org/cabal/users-guide/- name:                MHask-version:             0.1.0.0+version:             0.2.0.0 synopsis:            The category of monads-category:            Control description:            MHask is the category where   .-  * The objects are Haskell types of kind (* -> *) that have an instance of Monad-  * An arrow from object m to object n is a Haskell function of the form (forall x. m x -> n x)+  * The objects are Haskell types of kind @(* → *)@ that have an instance of `Prelude.Monad'+  .+  * An arrow from object m to object n is a Haskell function of the form @(forall x. m x → n x)@+  .   * Arrow composition is merely a specialization of Haskell function composition-  * The identity arrow for the object m is the id function in Haskell, specialized to (forall x. m x -> m x)   .-  Functor should actually be called Endofunctor, because if m is an object in MHask,-  then an instance t of Functor can transform object m into object (t m).-  You will see *a lot* of constraints in the type classes defined herein.-  Though daunting at first, you will soon realize that they are *all* Prelude.Monad constraints,-  and their interpretation is simply a guarantee that-  "the objects of MHask are types of kind (* -> *) that have an instance of Monad."+  * The identity arrow for the object m is the `Prelude.id' function in Haskell,+  specialized to @(forall x. m x → m x)@+  .+  It is assumed that any instances of the classes provided here also have an instance+  for Monad of the form @instance (Monad m) ⇒ Monad (t m)@, thus guaranteeing that @(t m)@+  (or @(t i j m)@ for the indexed types) is always a Monad. If it were valid Haskell, I'd write:+  .+  > class (forall m. Monad m ⇒ Monad (t m)) ⇒ Functor t+  .+  'MHask.Functor.Functor' should actually be called Endofunctor, because if m is an object in MHask,+  then an instance t of `Functor' can map object m to object (t m), and arrows from +  m to n get mapped to arrows from (t m) to (t n). + homepage:            https://github.com/DanBurton/MHask#readme license:             BSD3 license-file:        LICENSE author:              Dan Burton maintainer:          danburton.email@gmail.com--- copyright:           --- category:            +category:            Control build-type:          Simple cabal-version:       >=1.8 +source-repository head+  type:     git+  location: git://github.com/DanBurton/MHask.git++source-repository this+  type:     git+  location: git://github.com/DanBurton/MHask.git+  tag:      MHask-0.2.0.0+ library   exposed-modules:     MHask, MHask.Comonad, MHask.Monad, MHask.Copointed, MHask.Pointed, MHask.Util, MHask.Functor, MHask.Indexed.Comonad, MHask.Indexed.Monad, MHask.Indexed.Copointed, MHask.Indexed.Pointed, MHask.Indexed.Functor-  -- other-modules:       -  build-depends:       base == 4.6.*, transformers >= 0.3++  build-depends:       base >= 2 && < 4.7, transformers >= 0.3
MHask.hs view
@@ -1,16 +1,39 @@ -module MHask (module MHask) where+-- | Various abstractions in the category of MHask.+-- This re-exports everything, and should be imported+-- qualified so that the operations and classes+-- do not clash with their Hask counterparts.+-- +-- > import qualified MHask+module MHask (+  -- * Prelimiaries+  module MHask.Util, -import MHask.Util as MHask+  -- * Classes+  module MHask.Functor,+  module MHask.Pointed,+  module MHask.Monad,+  module MHask.Copointed,+  module MHask.Comonad, -import qualified MHask.Functor as MHask-import qualified MHask.Pointed as MHask-import qualified MHask.Monad   as MHask-import qualified MHask.Copointed as MHask-import qualified MHask.Comonad as MHask+  -- * Indexed Classes+  module MHask.Indexed.Functor,+  module MHask.Indexed.Pointed,+  module MHask.Indexed.Monad,+  module MHask.Indexed.Copointed,+  module MHask.Indexed.Comonad,+  ) where -import qualified MHask.Indexed.Functor as MHask-import qualified MHask.Indexed.Pointed as MHask-import qualified MHask.Indexed.Monad   as MHask-import qualified MHask.Indexed.Copointed as MHask-import qualified MHask.Indexed.Comonad as MHask+import MHask.Util++import MHask.Functor+import MHask.Pointed+import MHask.Monad+import MHask.Copointed+import MHask.Comonad++import MHask.Indexed.Functor+import MHask.Indexed.Pointed+import MHask.Indexed.Monad+import MHask.Indexed.Copointed+import MHask.Indexed.Comonad
MHask/Comonad.hs view
@@ -2,27 +2,31 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DefaultSignatures #-} --- Compare to comonad.Control.Comonad (Comonad)+-- | Compare to comonad.Control.Comonad (Comonad) module MHask.Comonad where -import MHask.Util -import Control.Monad.Trans.State-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Writer +import MHask.Util+ import qualified MHask.Functor as MHask import qualified MHask.Copointed as MHask  +-- | Dual of "MHask.Monad" class (MHask.Copointed t) => Comonad t where-  extend :: (Monad m, Monad n, Monad (t m), Monad (t n))-    => (t m ~> n) -> (t m ~> t n)-  default extend :: (Monad m, Monad n, Monad (t m), Monad (t n),-                     Monad (t (t m)))-    => (t m ~> n) -> (t m ~> t n)-  extend f = duplicate ~> MHask.fmap f--  duplicate :: (Monad m, Monad (t m), Monad (t (t m)))-    => t m ~> t (t m)+  duplicate :: (Monad m)+    => t (t m) <~ t m+  default duplicate :: (Monad m, Monad (t m))+    => t (t m) <~ t m   duplicate = extend id++  extend :: (Monad m, Monad n)+    => (m <~ t n) -> (t m <~ t n)+  default extend ::+    (Monad m, Monad n,+     Monad (t m), Monad (t n),+     Monad (t (t n)))+    => (m <~ t n) -> (t m <~ t n)+  extend f = MHask.fmap f ~<~ duplicate+
MHask/Copointed.hs view
@@ -2,31 +2,34 @@ {-# LANGUAGE Rank2Types #-}  --- Compare to todo.Copointed+-- | Compare to comonad.Control.Comonad (Copointed) module MHask.Copointed where + import MHask.Util +import Data.Monoid+import Control.Monad (liftM) import Control.Monad.Trans.State import Control.Monad.Trans.Reader import Control.Monad.Trans.Writer -import Data.Monoid-import Control.Monad (liftM)- import qualified MHask.Functor as MHask  ++-- | The dual of "MHask.Pointed" class (MHask.Functor t) => Copointed t where-  extract :: (Monad m, Monad (t m))-    => t m ~> m+  extract :: (Monad m)+    => m <~ t m  -instance Copointed (WriterT w) where-  extract = liftM fst . runWriterT- instance (Monoid s) => Copointed (StateT s) where   extract = flip evalStateT mempty  instance (Monoid r) => Copointed (ReaderT r) where   extract = flip runReaderT mempty++instance Copointed (WriterT w) where+  extract = liftM fst . runWriterT+
MHask/Functor.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Rank2Types #-} --- Compare to base.Prelude.Functor (Functor)++-- | Compare to base.Prelude.Functor (Functor) module MHask.Functor where  import Prelude hiding (Functor, fmap)@@ -12,8 +13,14 @@ import Control.Monad.Trans.Writer  ++-- | Functor is its own dual. class Functor t where-  fmap :: (Monad m, Monad n, Monad (t m), Monad (t n))+  -- | Flipping the arrows on fmap's type signature+  -- is just the same type signature in disguise.+  -- +  -- > (m <~ n) -> (t m <~ t n)+  fmap :: (Monad m, Monad n)     => (m ~> n) -> (t m ~> t n)  
MHask/Indexed/Comonad.hs view
@@ -2,33 +2,31 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DefaultSignatures #-} --- Compare to indexed.Control.Comonad.Indexed (IxComonad)+-- | Compare to indexed.Control.Comonad.Indexed (IxComonad) module MHask.Indexed.Comonad where -import MHask.Util -import Control.Monad.Trans.State-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Writer +import MHask.Util+ import qualified MHask.Indexed.Functor as MHask import qualified MHask.Indexed.Copointed as MHask -+-- | Indexed version of "MHask.Comonad".+-- Dual of "MHask.Indexed.Monad" class (MHask.IxCopointed t) => IxComonad t where-  iextend :: (Monad m, Monad n,-             Monad (t i j m), Monad (t j k n), Monad (t i k m))-    => (t j k m ~> n) -> (t i k m ~> t i j n)-  default iextend :: (Monad m, Monad n,-             Monad (t i j m), Monad (t j k n), Monad (t i k m),-             Monad (t i j (t j k m)), Monad (t j k m), Monad (t i j n))-    => (t j k m ~> n) -> (t i k m ~> t i j n)-  iextend f = iduplicate ~> MHask.imap f+  iduplicate :: (Monad m)+    => t i j (t j k m) <~ t i k m+  default iduplicate :: (Monad m, Monad (t j k m))+    => t i j (t j k m) <~ t i k m+  iduplicate = iextend id -  iduplicate :: (Monad m, Monad (t i k m), Monad (t i j (t j k m)))-    => t i k m ~> t i j (t j k m)+  iextend :: (Monad m, Monad n)+    => (m <~ t j k n) -> (t i j m <~ t i k n)+  default iextend ::+    (Monad m, Monad n,+     Monad (t i j m), Monad (t j k n), Monad (t i k n),+     Monad (t i j (t j k n)))+    => (m <~ t j k n) -> (t i j m <~ t i k n)+  iextend f = MHask.imap f ~<~ iduplicate -  default iduplicate :: (Monad m, Monad (t i k m), Monad (t i j (t j k m)),-                          (Monad (t j k (t j k m))), (Monad (t i j m)),  (Monad (t j k m)))-    => t i k m ~> t i j (t j k m)-  iduplicate = iextend id
MHask/Indexed/Copointed.hs view
@@ -2,21 +2,27 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DefaultSignatures #-} --- Compare to indexed.Data.Functor.Indexed (IxCopointed)+-- | Compare to indexed.Data.Functor.Indexed (IxCopointed) module MHask.Indexed.Copointed where + import MHask.Util -import Control.Monad.Trans.State-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Writer +++++ import qualified MHask.Copointed as MHask import qualified MHask.Indexed.Functor as MHask +-- | The indexed version of "MHask.Copointed".+-- The dual of "MHask.Indexed.Pointed". class (MHask.IxFunctor t) => IxCopointed t where-  iextract :: (Monad m, Monad (t i i m))-    => t i i m ~> m-  default iextract :: (Monad m, Monad (t i i m), MHask.Copointed (t i i))-    => t i i m ~> m+  iextract :: (Monad m)+    => m <~ t i i m+  default iextract :: (Monad m,+                       MHask.Copointed (t i i))+    => m <~ t i i m   iextract = MHask.extract
MHask/Indexed/Functor.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DefaultSignatures #-} --- Compare to indexed.Data.Functor.Indexed (IxFunctor)+-- | Compare to indexed.Data.Functor.Indexed (IxFunctor) module MHask.Indexed.Functor where  import MHask.Util@@ -13,10 +13,16 @@  import qualified MHask.Functor as MHask +-- | The indexed version of "MHask.Functor".+-- IxFunctor is its own dual. class IxFunctor t where-  imap :: (Monad m, Monad n, Monad (t i j m), Monad (t i j n))+  -- | Flipping the arrows on imap's type signature+  -- is just the same type signature in disguise.+  -- +  -- > (m <~ n) -> (t i j m <~ t i j n)+  imap :: (Monad m, Monad n)     => (m ~> n) -> (t i j m ~> t i j n)-  default imap :: (Monad m, Monad n, Monad (t i j m), Monad (t i j n),-                     MHask.Functor (t i j))+  default imap :: (Monad m, Monad n,+                   MHask.Functor (t i j))     => (m ~> n) -> (t i j m ~> t i j n)   imap = MHask.fmap
MHask/Indexed/Monad.hs view
@@ -2,31 +2,31 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DefaultSignatures #-} --- Compare to indexed.Control.Monad.Indexed (IxMonad)+-- | Compare to indexed.Control.Monad.Indexed (IxMonad) module MHask.Indexed.Monad where -import MHask.Util -import Control.Monad.Trans.State-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Writer -import qualified MHask.Monad as MHask+import MHask.Util+ import qualified MHask.Indexed.Pointed as MHask import qualified MHask.Indexed.Functor as MHask +-- | Indexed version of "MHask.Monad".+-- Dual of "MHask.Indexed.Comonad" class (MHask.IxPointed t) => IxMonad t where-  ijoin :: (Monad m, Monad (t i j (t j k m)), Monad (t i k m))+  ijoin :: (Monad m)     => t i j (t j k m) ~> t i k m-  default ijoin :: (Monad m, Monad (t i j (t j k m)), Monad (t i k m),-                     Monad (t j k m))+  default ijoin :: (Monad m, Monad (t j k m))     => t i j (t j k m) ~> t i k m   ijoin = ibind id --  ibind :: (Monad m, Monad (t i j m), Monad n, Monad (t j k n))+  ibind :: (Monad m, Monad n)     => (m ~> t j k n) -> (t i j m ~> t i k n)-  default ibind :: (Monad m, Monad (t i j m), Monad n, Monad (t j k n),-             Monad (t i k n), Monad (t i j (t j k n)))+  default ibind ::+    (Monad m, Monad n,+     Monad (t i j m), Monad (t j k n), Monad (t i k n),+     Monad (t i j (t j k n)))     => (m ~> t j k n) -> (t i j m ~> t i k n)-  ibind f = MHask.imap f ~> ijoin+  ibind f = MHask.imap f ~>~ ijoin+
MHask/Indexed/Pointed.hs view
@@ -2,21 +2,27 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DefaultSignatures #-} --- Compare to indexed.Data.Functor.Indexed (IxPointed)+-- | Compare to indexed.Data.Functor.Indexed (IxPointed) module MHask.Indexed.Pointed where + import MHask.Util -import Control.Monad.Trans.State-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Writer +++++ import qualified MHask.Pointed as MHask import qualified MHask.Indexed.Functor as MHask +-- | The indexed version of "MHask.Pointed".+-- The dual of "MHask.Indexed.Copointed". class (MHask.IxFunctor t) => IxPointed t where-  ireturn :: (Monad m, Monad (t i i m))+  ireturn :: (Monad m)     => m ~> t i i m-  default ireturn :: (Monad m, Monad (t i i m), MHask.Pointed (t i i))+  default ireturn :: (Monad m,+                      MHask.Pointed (t i i))     => m ~> t i i m   ireturn = MHask.return
MHask/Monad.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DefaultSignatures #-} --- Compare to base.Prelude.Monad+-- | Compare to base.Prelude (Monad) module MHask.Monad where  import Prelude hiding (Monad, join)@@ -12,19 +12,20 @@ import qualified MHask.Functor as MHask import qualified MHask.Pointed as MHask -import Control.Monad.Trans.State-import Control.Monad.Trans.Reader-import Control.Monad.Trans.Writer -+-- | Dual of "MHask.Comonad" class (MHask.Pointed t) => Monad t where-  join :: (P.Monad m, P.Monad (t m), P.Monad (t (t m)))+  join :: (P.Monad m)     => t (t m) ~> t m+  default join :: (P.Monad m, P.Monad (t m))+    => t (t m) ~> t m   join = bind id -  bind :: (P.Monad m, P.Monad (t m), P.Monad n, P.Monad (t n))+  bind :: (P.Monad m, P.Monad n)     => (m ~> t n) -> (t m ~> t n)-  default bind :: (P.Monad m, P.Monad (t m), P.Monad n, P.Monad (t n),-                   P.Monad (t (t n)))+  default bind ::+    (P.Monad m, P.Monad n,+     P.Monad (t m), P.Monad (t n),+     P.Monad (t (t n)))     => (m ~> t n) -> (t m ~> t n)-  bind f = MHask.fmap f ~> join+  bind f = MHask.fmap f ~>~ join
MHask/Pointed.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Rank2Types #-} --- no relevant comparison++-- | Equivalent to transformers.Control.Monad.Trans.Class (MonadTrans) module MHask.Pointed where  import Prelude hiding (return)@@ -12,17 +13,16 @@ import Control.Monad.Trans.State import Control.Monad.Trans.Reader import Control.Monad.Trans.Writer-import Control.Monad.Trans.Class  import qualified MHask.Functor as MHask -class (MHask.Functor t) => Pointed t where-  return :: (Monad m, Monad (t m))-    => (m ~> t m)  --- This is basically MonadTrans--- lift = MHask.return+-- | The dual of "MHask.Copointed"+class (MHask.Functor t) => Pointed t where+  return :: (Monad m)+    => m ~> t m+  instance Pointed (StateT s) where   return mx = StateT $ \s -> liftM (\x -> (x, s)) mx
MHask/Util.hs view
@@ -1,9 +1,44 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Rank2Types #-} +-- | This module sets the stage for the rest of the package.+-- It defines a type synonym @~>@ which cleans up the+-- type signatures,+-- and  @~>~@ which is used in the default implementation+-- of bind. These represent the type of arrows and arrow composition+-- in MHask, respectively.+-- +-- By using @~>@, type signatures for the MHask class operations+-- can be easily compared to their Hask counterparts. However,+-- as a reminder that you are dealing with Monads, where+-- typically you would see @a@ and @b@ in the Hask counterpart,+-- you will instead see @m@ and @n@, and where you would+-- typically see @m@ or @w@, you will instead see @t@,+-- as a mnemonic for Monad transformer.+-- +-- For illustrative purposes, this module also provides+-- @<~@ and @~<~@, to clearly illustrate how duals are+-- nothing more than just \"flipping the arrows\".+-- You are encouraged to compare docs or even source files+-- to see just how similar they are, all the way down+-- to default implementations. module MHask.Util where +-- | The @~>@ type represents arrows in the+-- category of MHask.  type m ~> n = forall x. m x -> n x -(~>) :: (Monad a, Monad b, Monad c) => (a ~> b) -> (b ~> c) -> (a ~> c)-f1 ~> f2 = f2 . f1+-- | It's just @~>@ flipped.+-- +-- > type m <~ n = n ~> m+type m <~ n = n ~> m++-- | Left-to-right composition of arrows in MHask.+(~>~) :: (Monad a, Monad b, Monad c) => (a ~> b) -> (b ~> c) -> (a ~> c)+f1 ~>~ f2 = f2 . f1++-- | It's just @~>~@ flipped.+-- +-- > (~<~) = flip (~>~)+(~<~) :: (Monad a, Monad b, Monad c) => (c <~ b) -> (b <~ a) -> (c <~ a)+(~<~) = flip (~>~)