Users of Apply will not be able to derive that Self::Outter is also an Apply since we are not able to update the bounds.
A simple example where this can show up is creating a general function to test homomorphisms:
fn applicative_homomorphism<T, A, B, F>(a: A, mut f: T<F>)
where
T : Applicative,
A : Copy,
B : std::fmt::Debug + std::cmp::PartialEq,
F : Copy + FnMut(A) -> B,
{
assert_eq!(T::pure(a).apply(f), f.apply(T::pure(|mut fun: F| fun(a))));
}
In the current setup, all we know about a general T::pure(a) is that it is a type that implements Functor. We aren't
able to automatically derive that it is also an Apply and Applicative. Representing this bounds would get exponentially
more complicated.
With this in mind we started looking for a new representation for the typeclases.
Based on the original post motivating GATs plus some experimentation we were able to derive a new representation that is able to work for generic
functions with a nice-enough API that could be improved as GAT support improves.
One issue with the current representation is that we can't properly create bounds for a typeclass hierarchy:
Users of
Apply
will not be able to derive thatSelf::Outter
is also anApply
since we are not able to update the bounds.A simple example where this can show up is creating a general function to test homomorphisms:
In the current setup, all we know about a general
T::pure(a)
is that it is a type that implementsFunctor
. We aren't able to automatically derive that it is also an Apply and Applicative. Representing this bounds would get exponentially more complicated.With this in mind we started looking for a new representation for the typeclases.
Based on the original post motivating GATs plus some experimentation we were able to derive a new representation that is able to work for generic functions with a nice-enough API that could be improved as GAT support improves.
Proof of concept implementation: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=cdcb8961e9d8d41b14d137625d33b1ad