pandora-0.2.0: Pandora/Pattern/Functor/Covariant.hs
module Pandora.Pattern.Functor.Covariant (Covariant (..)) where
import Pandora.Core.Functor (type (:.), type (>))
import Pandora.Core.Morphism (fix, (.), ($), (!), (?))
infixl 4 <$>, <$, $>
{- |
> When providing a new instance, you should ensure it satisfies the two laws:
> * Identity morphism: comap identity ≡ identity
> * Composition of morphisms: comap (f . g) ≡ comap f . comap g
-}
class Covariant (t :: * -> *) where
{-# MINIMAL (<$>) #-}
-- | Infix version of 'comap'
(<$>) :: (a -> b) -> t a -> t b
-- | Prefix version of '<$>'
comap :: (a -> b) -> t a -> t b
comap f x = f <$> x
-- | Replace all locations in the input with the same value
(<$) :: a -> t b -> t a
(<$) = comap . (!)
-- | Flipped version of '<$'
($>) :: t a -> b -> t b
($>) = (?) (<$)
-- | Discards the result of evaluation
void :: t a -> t ()
void x = () <$ x
-- | Computing a value from a structure of values
loeb :: t (t a -> a) -> t a
loeb tt = fix $ \f -> ($ f) <$> tt
-- | Flipped infix version of 'comap'
(<&>) :: t a -> (a -> b) -> t b
x <&> f = f <$> x
-- | Infix versions of `comap` with various nesting levels
(<$$>) :: 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
(<$$$$>) = (<$>) . (<$>) . (<$>) . (<$>)
-- | Infix flipped versions of `comap` with various nesting levels
(<&&>) :: 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
(<$>) = (.)