How to declare polymorphic instances for higher-kinded types?

Nicolas Frisby nicolas.frisby at gmail.com
Fri Mar 16 19:59:59 CET 2012


Here's another alternative.

> newtype Comp f g a = Comp {unComp :: f (g a)}
>
> instance Resolvable e => Resolvable (Maybe `Comp` e) where
>   resolve db = fmap Comp . resolveMaybe db . unComp

One disadvantage of this approach is that it requires you to pepper
your types with explicit compositions of *->* types via Comp.

On Mon, Mar 5, 2012 at 3:14 AM, Herbert Valerio Riedel <hvr at gnu.org> wrote:>
> Fair enough, but trying to workaround this by defining a type-synonym to
> get an (*->*)-kinded expression didn't work either, as currying doesn't
> seem to be supported at the type-level (is there a language-extension
> for that?):

The Comp newtype provides the type-level currying you were after,
which cannot be done with type synonyms. There is no
language-extension for that that I'm aware of. If you want to venture
down that rabbit hole, maybe take a look at Her.
https://personal.cis.strath.ac.uk/~conor/pub/she/

The other disadvantage of this approach is that Comp only works for a
fixed number of arguments. Thus *->*->* types, like pairs, requires Comp2.

> newtype Comp2 f g h a = Comp2 {unComp2 :: f (g a) (h a)}
>
> instance (Resolvable e0, Resolvable e1) => Resolvable (Comp2 (,) e0 e1) where
>   resolve db = fmap Comp2 . resolvePair db . unComp2

So, if you don't mind adding types like Comp, Comp2, etc throughout
the types in your program/library, this let's you keep Resolvable's
parameter as (* -> *) and avoids the type families and constraint
kinds.

I personally prefer the implicitness and generality of Löh's approach,
but I also know that some people (perhaps your users) are shy to the
newer type extensions.

HTH



More information about the Glasgow-haskell-users mailing list