{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Trustworthy #-}
#endif
module Data.Functor.Contravariant.Coyoneda
( Coyoneda(..)
, liftCoyoneda
, lowerCoyoneda
) where
import Control.Arrow
import Data.Functor.Contravariant
import Data.Functor.Contravariant.Adjunction
import Data.Functor.Contravariant.Rep
data Coyoneda f a where
Coyoneda :: (a -> b) -> f b -> Coyoneda f a
instance Contravariant (Coyoneda f) where
contramap f (Coyoneda g m) = Coyoneda (g.f) m
{-# INLINE contramap #-}
instance Representable f => Representable (Coyoneda f) where
type Rep (Coyoneda f) = Rep f
tabulate = liftCoyoneda . tabulate
{-# INLINE tabulate #-}
index (Coyoneda ab fb) a = index fb (ab a)
{-# INLINE index #-}
contramapWithRep beav (Coyoneda ac fc) = Coyoneda (left ac . beav) (contramapWithRep id fc)
{-# INLINE contramapWithRep #-}
instance Adjunction f g => Adjunction (Coyoneda f) (Coyoneda g) where
leftAdjunct f = liftCoyoneda . leftAdjunct (lowerCoyoneda . f)
{-# INLINE leftAdjunct #-}
rightAdjunct f = liftCoyoneda . rightAdjunct (lowerCoyoneda . f)
{-# INLINE rightAdjunct #-}
liftCoyoneda :: f a -> Coyoneda f a
liftCoyoneda = Coyoneda id
{-# INLINE liftCoyoneda #-}
lowerCoyoneda :: Contravariant f => Coyoneda f a -> f a
lowerCoyoneda (Coyoneda f m) = contramap f m
{-# INLINE lowerCoyoneda #-}