{-# LANGUAGE Rank2Types, MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances #-} module Data.Functor.Contravariant.DualAdjunction ( DualAdjunction(..) ) where import Data.Functor.Contravariant -- | An adjunction from Hask to Hask^op -- -- > Hask (f a) b ~ Op a (g b) -- -- > rightAdjunct unit = id -- > leftAdjunct counit = id class (Contravariant f, Contravariant g) => DualAdjunction f g | f -> g, g -> f where unitOp :: g (f a) -> a counitOp :: f (g a) -> a leftAdjunctOp :: (f a -> b) -> g b -> a rightAdjunctOp :: (g b -> a) -> f a -> b unitOp = leftAdjunctOp id counitOp = rightAdjunctOp id leftAdjunctOp f = unitOp . contramap f rightAdjunctOp f = counitOp . contramap f