{-# LANGUAGE CPP #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
#if __GLASGOW_HASKELL__ >= 704
{-# LANGUAGE Safe #-}
#elif __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Trustworthy #-}
#endif
#if __GLASGOW_HASKELL__ >= 706
{-# LANGUAGE PolyKinds #-}
#endif
module Data.Bifunctor.Functor
( (:->)
, BifunctorFunctor(..)
, BifunctorMonad(..)
, biliftM
, BifunctorComonad(..)
, biliftW
) where
type (:->) p q = forall a b. p a b -> q a b
infixr 0 :->
class BifunctorFunctor t where
bifmap :: (p :-> q) -> t p :-> t q
class BifunctorFunctor t => BifunctorMonad t where
bireturn :: p :-> t p
bibind :: (p :-> t q) -> t p :-> t q
bibind f = bijoin . bifmap f
bijoin :: t (t p) :-> t p
bijoin = bibind id
#if __GLASGOW_HASKELL__ >= 708
{-# MINIMAL bireturn, (bibind | bijoin) #-}
#endif
biliftM :: BifunctorMonad t => (p :-> q) -> t p :-> t q
biliftM f = bibind (bireturn . f)
{-# INLINE biliftM #-}
class BifunctorFunctor t => BifunctorComonad t where
biextract :: t p :-> p
biextend :: (t p :-> q) -> t p :-> t q
biextend f = bifmap f . biduplicate
biduplicate :: t p :-> t (t p)
biduplicate = biextend id
#if __GLASGOW_HASKELL__ >= 708
{-# MINIMAL biextract, (biextend | biduplicate) #-}
#endif
biliftW :: BifunctorComonad t => (p :-> q) -> t p :-> t q
biliftW f = biextend (f . biextract)
{-# INLINE biliftW #-}