module Pandora.Pattern.Functor.Covariant (Covariant (..)) where
import Pandora.Core.Functor (type (:.), type (:=), type (<-|))
import Pandora.Core.Morphism (fix, (.), (!), (%))
infixl 4 <$>, <$, $>
class Covariant (t :: * -> *) where
{-# MINIMAL (<$>) #-}
(<$>) :: (a -> b) -> t a -> t b
comap :: (a -> b) -> t a -> t b
comap f x = f <$> x
(<$) :: a -> t b -> t a
(<$) = comap . (!)
($>) :: t a -> b -> t b
($>) = (%) (<$)
void :: t a -> t ()
void x = () <$ x
loeb :: t (a <-| t) -> t a
loeb tt = fix (\f -> (\g -> g f) <$> tt)
(<&>) :: t a -> (a -> b) -> t b
x <&> f = f <$> x
(<$$>) :: Covariant u => (a -> b) -> t :. u := a -> t :. u := b
(<$$>) = (<$>) . (<$>)
(<$$$>) :: (Covariant u, Covariant v)
=> (a -> b) -> t :. u :. v := a -> t :. u :. v := b
(<$$$>) = (<$>) . (<$>) . (<$>)
(<$$$$>) :: (Covariant u, Covariant v, Covariant w)
=> (a -> b) -> t :. u :. v :. w := a -> t :. u :. v :. w := b
(<$$$$>) = (<$>) . (<$>) . (<$>) . (<$>)
(<&&>) :: Covariant u => t :. u := a -> (a -> b) -> t :. u := b
x <&&> f = f <$$> x
(<&&&>) :: (Covariant u, Covariant v)
=> t :. u :. v := a -> (a -> b) -> t :. u :. v := b
x <&&&> f = f <$$$> x
(<&&&&>) :: (Covariant u, Covariant v, Covariant w)
=> t :. u :. v :. w := a -> (a -> b) -> t :. u :. v :. w := b
x <&&&&> f = f <$$$$> x
instance Covariant ((->) a) where
(<$>) = (.)