[Haskell-cafe] Automatic instance constraints derivation: how?

Dimitry Golubovsky golubovsky at gmail.com
Fri Dec 19 10:06:02 EST 2008


I am trying to understand, why do I need to place constraints with
class instance declaration while all the information seems to be
already available to the compiler.

I have placed the code in question here:


so anybody can play with it.

The code tries to model evaluation of GRIN-style thunks using Haskell
type classes instead of tag-based pattern matching, as in the GRIN
papers. That is, a thunk is represented as a datatype like

data Ffun a b c = Ffun a b c, and there is some "eval" function which
being applied to such data results in the call fun a b c. Such "eval"
function is a method of class Eval:

class Eval a b | a -> b where
 eval :: (Monad m) => a -> m b

which means that thunks of some type (a) evaluate to values of some
dependent type (b).

The code is monadic because GRIN is a monad, so the code looks similar to GRIN.

The ultimate goal is to make GRIN code understandable by Haskell compiler.

Everything is fine with "simple" types like Int, that is "instance
Eval Int Int" means that Int (and Char, and Bool) do not need in fact
evaluation at all.

instance Eval Int Int where
  eval = return

Everything is fine with thunks encoding calls to primitives. See
instances for FADD and FSUB. All type information for primitives
(primPlusInt, primMinusInt) is specified in the code.

Then, a function "fun" is defined that calls the primitives. The
"main" function illustrates its use, and everything works as expected,
as output shows.

But when I tried to define a thunk for "fun" (instance for Ffun) I was
only able to do that with all constraints on its parameters explicitly

OTOH, even if I comment out the instance Eval for Ffun, and load the
code in Hugs (or GHCi, doesn't matter) then type signature of "fun" is
correctly derived by the compiler.

If I try to define instance for Ffun like this:

instance (Eval x x) => Eval (Ffun a b c) x where
  eval (Ffun a b c) = fun a b c

meaning only the fact that result of the function "fun" will be like
Int or Bool - evaluates to itself, and we don't care about the types
of arguments, I cannot use forall x. with instance declaration, so I
have to say something about x.

I get the error (Hugs):

Error occurred
ERROR line 51 - Instance is more general than a dependency allows
*** Instance         : Eval (Ffun a b c) d
*** For class        : Eval a b
*** Under dependency : a -> b

So, is there a way to define such an instance  for a thunk without any
constraints? Wouldn't it be reasonable to expect that

eval (Ffun a b c) = fun a b c

would allow the compiler to retrieve constraints on a, b, c from those
already known for the called function?


Dimitry Golubovsky

Anywhere on the Web

More information about the Haskell-Cafe mailing list