Arguments wrapping
We compose functors by treating one of them as an argument of another one:
t (tt a)If we want to get an access to a parameter, we should map twice (yo):
x: t (tt a)
f: a `AR_` o
(x `yo'yo` f): t (tt o)Functor composition is functor too, we can aligh this reasoning with programming by using a special wrapper:
Supertype ((t `T'TT'I` tt) a) ~ (t (tt a))Let me introduce a type operator for saturating polymorphic types:
(t `T'I_` a) ~ (t a))If you want to avoid using parenthesis, you can use that special type operator shown above:
Supertype (t `T'TT'I` tt `T'I_` a) ~ (t (tt a))So that using this wrapper we can map only once:
x: t (tt a)
wrap x: t `T'TT'I` tt `T'I_` a
wrap x `yo` f: t `T'TT'I` tt `T'I_` oThere is also reverse functor composition available, it’s used mostly in internal modules:
Supertype (t `T'TT'I` tt `T'I_` a) ~ (t (tt a))
Supertype (tt `TT'T'I` t `T'I_` a) ~ (t (tt a))Variance of composition
So far we had covariant functors in functor composition. Contravariant functors behave like true values in boolean XOR operation:
(Covariant ... t, Covariant ... tt) => Covariant ... (t `T'TT'I` tt)
(Contraviriant ... t, Covariant ... tt) => Contraviriant ... (t `T'TT'I` tt)
(Covariant ... t, Contraviriant ... tt) => Contraviriant ... (t `T'TT'I` tt)
(Contraviriant ... t, Contraviriant ... tt) => Covariant ... (t `T'TT'I` tt)