module Data.Functor.Yoneda.Contravariant
( Yoneda(..)
, liftYoneda
, lowerYoneda
, lowerM
) where
import Control.Applicative
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
import Data.Function (on)
import Data.Functor.Bind
import Data.Functor.Plus
import Data.Functor.Adjunction
import Data.Functor.Representable
import Data.Key
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 Yoneda f a where
Yoneda :: (b -> a) -> f b -> Yoneda f a
liftYoneda :: f a -> Yoneda f a
liftYoneda = Yoneda id
lowerYoneda :: Functor f => Yoneda f a -> f a
lowerYoneda (Yoneda f m) = fmap f m
lowerM :: Monad f => Yoneda f a -> f a
lowerM (Yoneda f m) = liftM f m
instance Functor (Yoneda f) where
fmap f (Yoneda g v) = Yoneda (f . g) v
type instance Key (Yoneda f) = Key f
instance Keyed f => Keyed (Yoneda f) where
mapWithKey f (Yoneda k a) = Yoneda id $ mapWithKey (\x -> f x . k) a
instance Apply f => Apply (Yoneda f) where
m <.> n = liftYoneda $ lowerYoneda m <.> lowerYoneda n
instance Applicative f => Applicative (Yoneda f) where
pure = liftYoneda . pure
m <*> n = liftYoneda $ lowerYoneda m <*> lowerYoneda n
instance Zip f => Zip (Yoneda f) where
zipWith f m n = liftYoneda $ zipWith f (lowerYoneda m) (lowerYoneda n)
instance ZipWithKey f => ZipWithKey (Yoneda f) where
zipWithKey f m n = liftYoneda $ zipWithKey f (lowerYoneda m) (lowerYoneda n)
instance Alternative f => Alternative (Yoneda f) where
empty = liftYoneda empty
m <|> n = liftYoneda $ lowerYoneda m <|> lowerYoneda n
instance Alt f => Alt (Yoneda f) where
m <!> n = liftYoneda $ lowerYoneda m <!> lowerYoneda n
instance Plus f => Plus (Yoneda f) where
zero = liftYoneda zero
instance Bind m => Bind (Yoneda m) where
Yoneda f v >>- k = liftYoneda (v >>- lowerYoneda . k . f)
instance Monad m => Monad (Yoneda m) where
return = Yoneda id . return
Yoneda f v >>= k = lift (v >>= lowerM . k . f)
instance MonadTrans Yoneda where
lift = Yoneda id
instance MonadFix f => MonadFix (Yoneda f) where
mfix f = lift $ mfix (lowerM . f)
instance MonadPlus f => MonadPlus (Yoneda f) where
mzero = lift mzero
m `mplus` n = lift $ lowerM m `mplus` lowerM n
instance (Functor f, Lookup f) => Lookup (Yoneda f) where
lookup k f = lookup k (lowerYoneda f)
instance (Functor f, Indexable f) => Indexable (Yoneda f) where
index = index . lowerYoneda
instance Representable f => Representable (Yoneda f) where
tabulate = liftYoneda . tabulate
instance Extend w => Extend (Yoneda w) where
extend k (Yoneda f v) = Yoneda id $ extend (k . Yoneda f) v
instance Comonad w => Comonad (Yoneda w) where
extract (Yoneda f v) = f (extract v)
instance ComonadTrans Yoneda where
lower (Yoneda f a) = fmap f a
instance Foldable f => Foldable (Yoneda f) where
foldMap f (Yoneda k a) = foldMap (f . k) a
instance FoldableWithKey f => FoldableWithKey (Yoneda f) where
foldMapWithKey f (Yoneda k a) = foldMapWithKey (\x -> f x . k) a
instance Foldable1 f => Foldable1 (Yoneda f) where
foldMap1 f (Yoneda k a) = foldMap1 (f . k) a
instance FoldableWithKey1 f => FoldableWithKey1 (Yoneda f) where
foldMapWithKey1 f (Yoneda k a) = foldMapWithKey1 (\x -> f x . k) a
instance Traversable f => Traversable (Yoneda f) where
traverse f (Yoneda k a) = Yoneda id <$> traverse (f . k) a
instance Traversable1 f => Traversable1 (Yoneda f) where
traverse1 f (Yoneda k a) = Yoneda id <$> traverse1 (f . k) a
instance TraversableWithKey f => TraversableWithKey (Yoneda f) where
traverseWithKey f (Yoneda k a) = Yoneda id <$> traverseWithKey (\x -> f x . k) a
instance TraversableWithKey1 f => TraversableWithKey1 (Yoneda f) where
traverseWithKey1 f (Yoneda k a) = Yoneda id <$> traverseWithKey1 (\x -> f x . k) a
instance Distributive f => Distributive (Yoneda f) where
collect f = liftYoneda . collect (lowerYoneda . f)
instance (Functor f, Show (f a)) => Show (Yoneda f a) where
showsPrec d (Yoneda f a) = showParen (d > 10) $
showString "liftYoneda " . showsPrec 11 (fmap f a)
#ifdef __GLASGOW_HASKELL__
instance (Functor f, Read (f a)) => Read (Yoneda f a) where
readPrec = parens $ prec 10 $ do
Ident "liftYoneda" <- lexP
liftYoneda <$> step readPrec
#endif
instance (Functor f, Eq (f a)) => Eq (Yoneda f a) where
(==) = (==) `on` lowerYoneda
instance (Functor f, Ord (f a)) => Ord (Yoneda f a) where
compare = compare `on` lowerYoneda
instance Adjunction f g => Adjunction (Yoneda f) (Yoneda g) where
unit = liftYoneda . fmap liftYoneda . unit
counit = counit . fmap lowerYoneda . lowerYoneda