{-# LANGUAGE TypeOperators #-} module Control.Categorical.Bifunctor where import qualified Data.Bifunctor as Base import Control.Categorical.Functor import Control.Category.Dual import Data.Functor.Product import Data.Functor.Sum class (Functor r (NT t) f, Category s) => Bifunctor r s t f where bimap :: r aᵣ bᵣ -> s aₛ bₛ -> f aᵣ aₛ `t` f bᵣ bₛ infixr 3 <***>, <⁂> (<***>), (<⁂>) :: Bifunctor r s t f => r aᵣ bᵣ -> s aₛ bₛ -> f aᵣ aₛ `t` f bᵣ bₛ (<***>) = bimap (<⁂>) = bimap instance {-# INCOHERENT #-} (Base.Bifunctor f, Functor (->) (NT (->)) f) => Bifunctor (->) (->) (->) f where bimap = Base.bimap instance Category s => Bifunctor (Dual s) s (->) s where bimap (Dual f) g a = g . a . f instance Bifunctor (NT (->)) (NT (->)) (NT (->)) Product where bimap (NT f) (NT g) = NT (\ (Pair x y) -> Pair (f x) (g y)) instance Bifunctor (NT (->)) (NT (->)) (NT (->)) Sum where bimap (NT f) (NT g) = NT (\ case InL x -> InL (f x) InR y -> InR (g y))