module Pandora.Pattern.Functor.Contravariant (Contravariant (..)) where
import Pandora.Core.Functor (type (:.:), type (><))
import Pandora.Core.Morphism ((.), (!), (?))
infixl 4 >$<, $<, >$
class Contravariant (t :: * -> *) where
{-# MINIMAL (>$<) #-}
(>$<) :: (a -> b) -> t b -> t a
contramap :: (a -> b) -> t b -> t a
contramap f x = f >$< x
(>$) :: b -> t b -> t a
(>$) = contramap . (!)
($<) :: t b -> b -> t a
($<) = (?) (>$)
full :: t () -> t a
full x = () >$ x
(>&<) :: t b -> (a -> b) -> t a
x >&< f = f >$< x
(>$$<) :: Contravariant u => (a -> b) -> t :.: u >< a -> t :.: u >< b
(>$$<) = (>$<) . (>$<)
(>$$$<) :: (Contravariant u, Contravariant v)
=> (a -> b) -> t :.: u :.: v >< b -> t :.: u :.: v >< a
(>$$$<) = (>$<) . (>$<) . (>$<)
(>$$$$<) :: (Contravariant u, Contravariant v, Contravariant w)
=> (a -> b) -> t :.: u :.: v :.: w >< a -> t :.: u :.: v :.: w >< b
(>$$$$<) = (>$<) . (>$<) . (>$<) . (>$<)
(>&&<) :: Contravariant u => t :.: u >< a -> (a -> b) -> t :.: u >< b
x >&&< f = f >$$< x
(>&&&<) :: (Contravariant u, Contravariant v)
=> t :.: u :.: v >< b -> (a -> b) -> t :.: u :.: v >< a
x >&&&< f = f >$$$< x
(>&&&&<) :: (Contravariant u, Contravariant v, Contravariant w)
=> t :.: u :.: v :.: w >< a -> (a -> b) -> t :.: u :.: v :.: w >< b
x >&&&&< f = f >$$$$< x