module Data.Functor.Composition.T (T (..)) where import "morphisms" Control.Morphism ((.), ($)) import Control.Functor.Covariant (Covariant ((<$>), comap)) import Control.Functor.Covariant.Extractable (Extractable (extract)) import Control.Functor.Covariant.Exclusive (Exclusive (exclusive)) import Control.Functor.Covariant.Pointable (Pointable (point)) import Control.Functor.Covariant.Alternative (Alternative ((<+>))) import Control.Functor.Covariant.Applicative (Applicative ((<*>), apply)) import Control.Functor.Covariant.Composition.Adjoint (Adjoint (phi, psi)) import Control.Functor.Contravariant (Contravariant ((>$<), contramap)) import Control.Variance (Variant (Co, Contra)) newtype T ct cu t u a = T { t :: t (u a) } instance (Covariant t, Covariant u) => Covariant (T Co Co t u) where f <$> T x = T $ (comap . comap) f x instance (Covariant t, Contravariant u) => Contravariant (T Co Contra t u) where f >$< T x = T $ contramap f <$> x instance (Contravariant t, Covariant u) => Contravariant (T Contra Co t u) where f >$< T x = T $ contramap (comap f) x instance (Contravariant t, Contravariant u) => Covariant (T Contra Contra t u) where f <$> T x = T $ contramap (contramap f) x instance (Applicative t, Applicative u) => Applicative (T Co Co t u) where T f <*> T x = T $ apply <$> f <*> x instance (Alternative t, Covariant u) => Alternative (T Co Co t u) where T x <+> T y = T $ x <+> y instance (Exclusive t, Covariant u) => Exclusive (T Co Co t u) where exclusive = T exclusive instance (Pointable t, Pointable u) => Pointable (T Co Co t u) where point = T . point . point instance (Extractable t, Extractable u) => Extractable (T Co Co t u) where extract = extract . extract . t type Adjunctive t u = (Extractable t, Pointable t, Extractable u, Pointable u, Adjoint t u) instance (Adjunctive t u, Adjunctive v w) => Adjoint (T Co Co t v) (T Co Co u w) where phi f = point . f . point psi f = extract . extract . comap f