#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
#endif
#include "kan-extensions-common.h"
module Data.Functor.Coyoneda
( Coyoneda(..)
, liftCoyoneda, lowerCoyoneda, lowerM, hoistCoyoneda
, coyonedaToLan, lanToCoyoneda
) where
import Control.Applicative as A
import Control.Monad (MonadPlus(..), liftM)
import Control.Monad.Fix
import Control.Monad.Trans.Class
import Control.Comonad
import Control.Comonad.Trans.Class
import Data.Distributive
#if !LIFTED_FUNCTOR_CLASSES
import Data.Function (on)
#endif
import Data.Functor.Adjunction
import Data.Functor.Bind
import Data.Functor.Classes
import Data.Functor.Extend
import Data.Functor.Identity
import Data.Functor.Kan.Lan
import Data.Functor.Plus
import Data.Functor.Rep
import Data.Foldable
import Data.Traversable
import Data.Semigroup.Foldable
import Data.Semigroup.Traversable
import Prelude hiding (sequence, lookup, zipWith)
import Text.Read hiding (lift)
data Coyoneda f a where
Coyoneda :: (b -> a) -> f b -> Coyoneda f a
coyonedaToLan :: Coyoneda f a -> Lan Identity f a
coyonedaToLan (Coyoneda ba fb) = Lan (ba . runIdentity) fb
lanToCoyoneda :: Lan Identity f a -> Coyoneda f a
lanToCoyoneda (Lan iba fb) = Coyoneda (iba . Identity) fb
instance Functor (Coyoneda f) where
fmap f (Coyoneda g v) = Coyoneda (f . g) v
instance Apply f => Apply (Coyoneda f) where
Coyoneda mf m <.> Coyoneda nf n =
liftCoyoneda $ (\mres nres -> mf mres (nf nres)) <$> m <.> n
Coyoneda _ m .> Coyoneda g n = Coyoneda g (m .> n)
Coyoneda f m <. Coyoneda _ n = Coyoneda f (m <. n)
instance Applicative f => Applicative (Coyoneda f) where
pure = liftCoyoneda . pure
Coyoneda mf m <*> Coyoneda nf n =
liftCoyoneda $ (\mres nres -> mf mres (nf nres)) <$> m <*> n
Coyoneda _ m *> Coyoneda g n = Coyoneda g (m *> n)
Coyoneda f m <* Coyoneda _ n = Coyoneda f (m <* n)
instance Alternative f => Alternative (Coyoneda f) where
empty = liftCoyoneda empty
m <|> n = liftCoyoneda $ lowerCoyoneda m <|> lowerCoyoneda n
some = liftCoyoneda . A.some . lowerCoyoneda
many = liftCoyoneda . A.many . lowerCoyoneda
instance Alt f => Alt (Coyoneda f) where
m <!> n = liftCoyoneda $ lowerCoyoneda m <!> lowerCoyoneda n
instance Plus f => Plus (Coyoneda f) where
zero = liftCoyoneda zero
instance Bind m => Bind (Coyoneda m) where
Coyoneda f v >>- k = liftCoyoneda (v >>- lowerCoyoneda . k . f)
instance Monad m => Monad (Coyoneda m) where
#if __GLASGOW_HASKELL__ < 710
return = Coyoneda id . return
Coyoneda _ m >> Coyoneda g n = Coyoneda g (m >> n)
#else
(>>) = (*>)
#endif
Coyoneda f v >>= k = lift (v >>= lowerM . k . f)
instance MonadTrans Coyoneda where
lift = Coyoneda id
instance MonadFix f => MonadFix (Coyoneda f) where
mfix f = lift $ mfix (lowerM . f)
instance MonadPlus f => MonadPlus (Coyoneda f) where
mzero = lift mzero
m `mplus` n = lift $ lowerM m `mplus` lowerM n
instance Representable f => Representable (Coyoneda f) where
type Rep (Coyoneda f) = Rep f
tabulate = liftCoyoneda . tabulate
index = index . lowerCoyoneda
instance Extend w => Extend (Coyoneda w) where
extended k (Coyoneda f v) = Coyoneda id $ extended (k . Coyoneda f) v
instance Comonad w => Comonad (Coyoneda w) where
extend k (Coyoneda f v) = Coyoneda id $ extend (k . Coyoneda f) v
extract (Coyoneda f v) = f (extract v)
instance ComonadTrans Coyoneda where
lower (Coyoneda f a) = fmap f a
instance Foldable f => Foldable (Coyoneda f) where
foldMap f (Coyoneda k a) = foldMap (f . k) a
instance Foldable1 f => Foldable1 (Coyoneda f) where
foldMap1 f (Coyoneda k a) = foldMap1 (f . k) a
instance Traversable f => Traversable (Coyoneda f) where
traverse f (Coyoneda k a) = Coyoneda id <$> traverse (f . k) a
instance Traversable1 f => Traversable1 (Coyoneda f) where
traverse1 f (Coyoneda k a) = Coyoneda id <$> traverse1 (f . k) a
instance Distributive f => Distributive (Coyoneda f) where
collect f = liftCoyoneda . collect (lowerCoyoneda . f)
instance (Functor f, Show1 f) => Show1 (Coyoneda f) where
#if LIFTED_FUNCTOR_CLASSES
liftShowsPrec sp sl d (Coyoneda f a) =
showsUnaryWith (liftShowsPrec sp sl) "liftCoyoneda" d (fmap f a)
#else
showsPrec1 d (Coyoneda f a) = showParen (d > 10) $
showString "liftCoyoneda " . showsPrec1 11 (fmap f a)
#endif
instance (Read1 f) => Read1 (Coyoneda f) where
#if LIFTED_FUNCTOR_CLASSES
liftReadsPrec rp rl = readsData $
readsUnaryWith (liftReadsPrec rp rl) "liftCoyoneda" liftCoyoneda
#else
readsPrec1 d = readParen (d > 10) $ \r' ->
[ (liftCoyoneda f, t)
| ("liftCoyoneda", s) <- lex r'
, (f, t) <- readsPrec1 11 s
]
#endif
instance (Functor f, Show1 f, Show a) => Show (Coyoneda f a) where
showsPrec = showsPrec1
instance Read (f a) => Read (Coyoneda f a) where
#ifdef __GLASGOW_HASKELL__
readPrec = parens $ prec 10 $ do
Ident "liftCoyoneda" <- lexP
liftCoyoneda <$> step readPrec
#else
readsPrec d = readParen (d > 10) $ \r' ->
[ (liftCoyoneda f, t)
| ("liftCoyoneda", s) <- lex r'
, (f, t) <- readsPrec 11 s
]
#endif
instance (Functor f, Eq1 f) => Eq1 (Coyoneda f) where
#if LIFTED_FUNCTOR_CLASSES
liftEq eq = \x y -> liftEq eq (lowerCoyoneda x) (lowerCoyoneda y)
#else
eq1 = eq1 `on` lowerCoyoneda
#endif
instance (Functor f, Ord1 f) => Ord1 (Coyoneda f) where
#if LIFTED_FUNCTOR_CLASSES
liftCompare cmp = \x y -> liftCompare cmp (lowerCoyoneda x) (lowerCoyoneda y)
#else
compare1 = compare1 `on` lowerCoyoneda
#endif
instance (Functor f, Eq1 f, Eq a) => Eq (Coyoneda f a) where
(==) = eq1
instance (Functor f, Ord1 f, Ord a) => Ord (Coyoneda f a) where
compare = compare1
instance Adjunction f g => Adjunction (Coyoneda f) (Coyoneda g) where
unit = liftCoyoneda . fmap liftCoyoneda . unit
counit = counit . fmap lowerCoyoneda . lowerCoyoneda
liftCoyoneda :: f a -> Coyoneda f a
liftCoyoneda = Coyoneda id
lowerCoyoneda :: Functor f => Coyoneda f a -> f a
lowerCoyoneda (Coyoneda f m) = fmap f m
lowerM :: Monad f => Coyoneda f a -> f a
lowerM (Coyoneda f m) = liftM f m
hoistCoyoneda :: (forall a. f a -> g a) -> (Coyoneda f b -> Coyoneda g b)
hoistCoyoneda f (Coyoneda g x) = Coyoneda g (f x)