How to declare polymorphic instances for higher-kinded types?

Andres Löh andres at well-typed.com
Mon Mar 5 13:40:31 CET 2012


Hi.

> If I get it right, the trick is to use a *-kinded (instead of a
> *->*-kinded) argument for the class & instances and have a "type
> function" that is able to phantom-retag an already applied
> type-constructor `Foo_ Unres` to a differently applied type-constructor
> `Foo_ Res`.

Yes.

> The only thing that disturbs me is that I have to define explicit
> boilerplate type family declarations for all twenty or so
> non-polymorphic instances which'd look always the same, i.e.
>
> type ResFun (t r) a = t a
> type ResArg (t r) a = t ~ a
>
> ...could that be defined as an override-able default somehow?

The only way I can quickly think of that might work is to go via
another type family. However, this requires "UndecidableInstances":

type family GetF e :: Resolved -> *
type instance GetF (f x) = f

-- provides operation to transform an unresolved `Foo_ Unres` to a
resolved `Foo_ Res`
class Resolvable e where
    type ResFun e (a :: Resolved) :: *
    type ResFun e a = GetF e a
    type ResArg e (a :: Resolved) :: Constraint
    type ResArg e a = GetF e a ~ e
    ...

Then, for types like Foo, you can just write:

instance Resolvable (Foo_ r) where
    resolve _ x = return Foo

I.e., you shouldn't need the type family declarations.

Cheers,
  Andres

-- 
Andres Löh, Haskell Consultant
Well-Typed LLP, http://www.well-typed.com



More information about the Glasgow-haskell-users mailing list