Jeroen Weijers | 21 Aug 11:45 2012

Problem with default signatures


I am trying to create some code involving type families and default signatures. I am getting a type error
that I do not understand (as far as I can see the error is wrong).

I removed all code that doesn't contribute to the error:

> {-# LANGUAGE DeriveGeneric, UndecidableInstances, DefaultSignatures, TypeOperators, GADTs,
FlexibleContexts, TypeFamilies, FlexibleInstances #-}
> module Database.DSH.Problem where
> import GHC.Generics
> data Exp a where
>  UnitE     :: Exp ()
>  ListE     :: [Exp a] -> Exp [Exp a]
> class GenericQA f where
>  type GRep f
>  type AltGRep f
>  type AltGRep f = [Exp (GRep f)]
>  gToExp :: f a -> Exp (GRep f)
>  emptyAlt :: Exp (AltGRep f)
>  default emptyAlt :: (AltGRep f ~ [Exp (GRep f)]) => Exp (AltGRep f)
>  emptyAlt = ListE [] 
> instance GenericQA U1 where
>  type GRep U1 = ()
>  gToExp U1 = UnitE

(Continue reading)

Nicolas Frisby | 23 Aug 23:21 2012

Re: Problem with default signatures

I've investigated this behavior a bit, and I have two things worth mentioning.

  (1) One of the ingredients in this behavior is the non-injectivity
of type families. If we make the class parameter f accessible in the
signature of emptyAlt, there are no more type errors. For example, if
you can change the signature to emptyAlt :: Proxy f -> Exp (AltGRep f)

   data Proxy (f :: * -> *) = Proxy

(Even if your code had been type checking, you would have found that
emptyAlt would be impossible to use with the signature you gave it —
its type must include at least one occurrence of each class parameter
that isn't inside an argument to a type family. That's what I mean by
"accessible", and its what the dummy parameter "Proxy f" gives us.)

Jeroen Weijers, I think this will be enough for you to get past these
errors. Please let me know if not.

The rest of this email is probably more for GHC hackers.

  (2) The note [Default methods in instances] in TcInstDcls handles
GHC ticket #1061. The key idea is that a default method (those without
special signatures) intuitively results in a method definition in the
instances that rely on the default is a simple equality "method =
default_RHS". #1061 shows a situation in which this won't do; we need
the RHS to be eta-expanded with respect to the class type parameters.
But looking in TcInstDcls.tcInstanceMethods and
TcClassDcl.mkGenericDefMethBind, it seems that generic default
signatures don't do this eta-expansion.
(Continue reading)