One thing I’ve wanted which I haven’t been able to do nicely without existentials is Coyoneda (specialized for a given functor of course). I need it to be able to encode signature functors for free monad macros.
For example (using Haskell notation)
data Exists f = MkEx { runEx :: forall r. (forall a. f a -> r) -> r }
data CoyonedaF f a i = CoyonedaF { k :: i -> a, fi :: f i }
newtype Coyoneda f a = Coyoneda (Exists (CoyonedaF f a))
data Free f a = Return a | Join (f (Free f a))
data Signature r x
= Ask (r -> x)
| Local (r -> r) (Coyoneda (Reader r) x)
deriving (Functor)
newtype Reader r a = Reader { toFree :: Free (Signature r) a }
Some I can do without it:
pub enum Signature<'a, S, X> {
Get(Box<FnOnce<(S,), X> + 'a>),
Put(S, X),
}
monad!(State, Signature, map, [ S, ])
I attempted something with associated types at one point but couldn’t even try it because boxed traits weren’t working with them:
#![feature(associated_types)]
struct F<'a, A>;
trait CoyonedaFT<'a, A:'a> {
type I;
fn k(i: <Self as CoyonedaFT<'a, A>>::I) -> A;
fn fi() -> F<'a, <Self as CoyonedaFT<'a, A>>::I>;
}
type CoyonedaF<'a, A> = Box<CoyonedaFT<'a, A> + 'a>;
If there’s a way to do this using DSTs or something else aside from unsafe casts, I’d be very interested to see how. Even using casts it’s tricky if you want to avoid multiple traversals when you lower to the underlying functor, which kind of kills the whole map fusion thing.