1{-# LANGUAGE CPP #-}
2{-# LANGUAGE RankNTypes #-}
3{-# LANGUAGE TypeOperators #-}
4
5#if __GLASGOW_HASKELL__ >= 704
6{-# LANGUAGE Safe #-}
7#elif __GLASGOW_HASKELL__ >= 702
8{-# LANGUAGE Trustworthy #-}
9#endif
10
11#if __GLASGOW_HASKELL__ >= 706
12{-# LANGUAGE PolyKinds #-}
13#endif
14
15module Data.Bifunctor.Functor
16  ( (:->)
17  , BifunctorFunctor(..)
18  , BifunctorMonad(..)
19  , biliftM
20  , BifunctorComonad(..)
21  , biliftW
22  ) where
23
24-- | Using parametricity as an approximation of a natural transformation in two arguments.
25type (:->) p q = forall a b. p a b -> q a b
26infixr 0 :->
27
28class BifunctorFunctor t where
29  bifmap :: (p :-> q) -> t p :-> t q
30
31class BifunctorFunctor t => BifunctorMonad t where
32  bireturn :: p :-> t p
33  bibind   :: (p :-> t q) -> t p :-> t q
34  bibind f = bijoin . bifmap f
35  bijoin   :: t (t p) :-> t p
36  bijoin = bibind id
37#if __GLASGOW_HASKELL__ >= 708
38  {-# MINIMAL bireturn, (bibind | bijoin) #-}
39#endif
40
41biliftM :: BifunctorMonad t => (p :-> q) -> t p :-> t q
42biliftM f = bibind (bireturn . f)
43{-# INLINE biliftM #-}
44
45class BifunctorFunctor t => BifunctorComonad t where
46  biextract :: t p :-> p
47  biextend :: (t p :-> q) -> t p :-> t q
48  biextend f = bifmap f . biduplicate
49  biduplicate :: t p :-> t (t p)
50  biduplicate =  biextend id
51#if __GLASGOW_HASKELL__ >= 708
52  {-# MINIMAL biextract, (biextend | biduplicate) #-}
53#endif
54
55biliftW :: BifunctorComonad t => (p :-> q) -> t p :-> t q
56biliftW f = biextend (f . biextract)
57{-# INLINE biliftW #-}
58