[Haskell] Partially applied type class functions
iavor.diatchki at gmail.com
Fri Aug 5 14:06:16 EDT 2005
On 8/5/05, Paul Govereau <govereau at eecs.harvard.edu> wrote:
> I have encountered a type error that I find quite puzzling. I would
> appreciate it if someone could help me understand what is going wrong.
> Here is the program:
> > data Expr = Var String | Const Int
> > data Constraint = Zero Expr | AndL Constraint
> > class AbSyn a where
> > subst :: Expr -> String -> a -> a
> > instance AbSyn Expr where subst e n expr = expr
> > instance AbSyn Constraint where
> > subst e n constr =
> > let sub = subst e n -- :: AbSyn a => a -> a
> > in case constr
> > of Zero expr -> Zero (sub expr)
> > AndL cs -> AndL (sub cs)
> GHC 6.4 (as well as Hugs March 2005) produces this error:
> Couldn't match `Constraint' against `Expr'
> Expected type: Constraint
> Inferred type: Expr
> In the application `sub cs'
> In the first argument of `AndL', namely `(sub cs)'
> If I replace the last line with this one, everything is fine:
> AndL cs -> AndL (subst e n cs)
> It looks sort of like sub is being monomorphised -- or something?
This is exactly right, you have encountered the 'monomorphism restriction'.
It says that definitions that do not syntactically look like
functions (i.e. they don't have arguments) should not be overloaded,
unless the programmer provides an explicit type signature. You can
fix your program by:
(i) adding an argument to 'sub' to make it look like a function:
sub x = subst e n x -- :: AbSyn a => a -> a
(ii) write the type signature explicitly to indicate that you are
aware of the overloading:
sub :: AbSyb a => a -> a
sub = subst e n
This rule was introduced to avoid accidental loss sharing. You can
read more about it at the Haskell wiki, although the author of the
article was quite clearly against the monomorphism restriction :-)
More information about the Haskell