-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Bifunctors over monad transformers.
--   
--   Bifunctors over monad transformers.
@package transformers-bifunctors
@version 0.1

module Control.Monad.Trans.Bifunctor

-- | Class of monad transformers which are bifunctors.
--   
--   You can implement a <a>BifunctorTrans</a> by either defining
--   <a>bimapT</a> or by defining both <a>firstT</a> and <a>secondT</a>.
--   
--   If you supply <a>bimapT</a>, you should ensure that:
--   
--   <pre>
--   <a>bimapT</a> <a>id</a> <a>id</a> ≡ <a>id</a>
--   </pre>
--   
--   If you supply <tt>first</tt> and <tt>second</tt>, ensure:
--   
--   <pre>
--   <a>firstT</a>  <a>id</a> ≡ <a>id</a>
--   <a>secondT</a> <a>id</a> ≡ <a>id</a>
--   </pre>
--   
--   If you supply both, you should also ensure:
--   
--   <pre>
--   <a>bimapT</a> f g ≡ <a>firstT</a> f <a>.</a> <a>secondT</a> g
--   </pre>
--   
--   These ensure by parametricity:
--   
--   <pre>
--   <a>bimapT</a>  (f <a>.</a> g) (h <a>.</a> i) ≡ <a>bimapT</a> f h <a>.</a> <a>bimapT</a> g i
--   <a>firstT</a>  (f <a>.</a> g) ≡ <a>firstT</a>  f <a>.</a> <a>firstT</a>  g
--   <a>secondT</a> (f <a>.</a> g) ≡ <a>secondT</a> f <a>.</a> <a>secondT</a> g
--   </pre>
class BifunctorTrans t

-- | Map over both arguments at the same time.
--   
--   <pre>
--   <tt>bimap</tt> f g ≡ <tt>first</tt> f <a>.</a> <tt>second</tt> g
--   </pre>
bimapT :: (BifunctorTrans t, Functor f) => (x -> y) -> (a -> b) -> t x f a -> t y f b

-- | Map covariantly over the first argument.
--   
--   <pre>
--   <a>firstT</a> f ≡ <a>bimapT</a> f <a>id</a>
--   </pre>
firstT :: (BifunctorTrans t, Functor f) => (x -> y) -> t x f a -> t y f a

-- | Map covariantly over the second argument.
--   
--   <pre>
--   <tt>second</tt> ≡ <tt>bimap</tt> <a>id</a>
--   </pre>
secondT :: (BifunctorTrans t, Functor f) => (a -> b) -> t x f a -> t x f b

-- | Map over two stacked transformer bifunctors, unifying their type and
--   squashing the result.
bimapX :: (BifunctorTrans t, MMonad (t z), Monad (t y m), Monad m) => (x -> z) -> (y -> z) -> t x (t y m) a -> t z m a

-- | Map over the first of two stacked transformer bifunctors, unifying
--   their type and squashing the result.
firstX :: (BifunctorTrans t, MMonad (t y), Functor (t y m), Monad m) => (x -> y) -> t x (t y m) a -> t y m a

-- | Map over the second of two stacked transformer bifunctors, unifying
--   their type and squashing the result.
secondX :: (BifunctorTrans t, MMonad (t x), Monad (t y m), Monad m) => (y -> x) -> t x (t y m) a -> t x m a
instance Control.Monad.Trans.Bifunctor.BifunctorTrans Control.Monad.Trans.Except.ExceptT
instance Control.Monad.Trans.Bifunctor.BifunctorTrans Control.Monad.Trans.Writer.Lazy.WriterT
instance Control.Monad.Trans.Bifunctor.BifunctorTrans Control.Monad.Trans.Writer.Strict.WriterT
