[Haskell-cafe] Possible bug?

Ryan Ingram ryani.spam at gmail.com
Sat Feb 14 17:38:04 EST 2009

2009/2/13 Peter Verswyvelen <bugfact at gmail.com>:
> No the error I got was
> Could not deduce (Controller m v c)
> from the context (Controller m v c2)
>       arising from a use of `MVC' at NM8\GUI\PanZoom.hs:126:32-65
>     Possible fix:
>       add (Controller m v c) to the context of the constructor `MVC'
>     In the expression: MVC m v (PZC s z (unsafeCoerce c))
>     In the definition of `panZoomedMVC'':
>         panZoomedMVC' s z (MVC m v c) = MVC m v (PZC s z (unsafeCoerce c))
> I got this after adding the type signature of
> panZoomedMVC' :: (Controller m v c, PanZoomable z) =>
>                  State -> z -> MVC m v -> MVC m v

No function with the type signature of panZoomedMVC' can be called
(unless there is a functional dependency that uniquely determines c
from m and v).  It's ambiguous; there's no way to know which instance
to call.

GHC allows such a function to get an inferred type, but then when it
comes time to call it (and provide the Controller instance) or type
check it against a provided signature, it cannot resolve the ambiguity
and you get that error.

What is happening in this case is something along these lines:

1) Infer a type and constraints for panZoomedMVC':

   Controller t1 t2 t3
   PanZoomable t4

   State -> t4 -> MVC t1 t2 -> MVC t1 t2

2) Unify the inferred type signature with your provided signature

   Controller m v t3
   PanZoomable z

   State -> z -> MVC m v -> MVC m v

3) Verify that constraints are sufficient.  This fails, because the
use of Controller in the function (Controller m v t3) doesn't match
the use provided by your constraint (Controller m v c).

However, leaving out the type signature doesn't help you; it just
delays your problem.  Because of the ambiguity, panZoomedMVC' cannot
be called; you'll get the error at the callsite instead.

To solve this problem, either add a dummy argument that fixes "c", or
add a functional dependency or associated type to Controller that
fixes c based on m and v.  For example:

> data Proxy a = Proxy
> panZoomedMVC' :: (Controller m v c, PanZoomable z) =>
>                  Proxy c -> State -> z -> MVC m v -> MVC m v
> panZoomedMVC' _ s z mvc = ...

Then you can pass the proper "Proxy" when calling the function to make
the typechecker happy.


> class Controller m v c | m v -> c where ...


> class Controller m v where
>    type Control m v
>    ...

  -- ryan

More information about the Haskell-Cafe mailing list