Thanks Ryan.<div><br></div><div>I'm always struggling with functional dependencies since to be honest - I don't really understand how the type inferer figures out all the types and I didn't take the time to study it yet. Your email will help me a bit further with this.</div>
<div><br></div><div>My functional dependency was c -> m v. It can't be m v -> c since for the same model and view type , you can have many controllers types.</div><div><br></div><div><div class="gmail_quote">On Sat, Feb 14, 2009 at 11:38 PM, Ryan Ingram <span dir="ltr"><<a href="mailto:ryani.spam@gmail.com">ryani.spam@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">2009/2/13 Peter Verswyvelen <<a href="mailto:bugfact@gmail.com">bugfact@gmail.com</a>>:<br>
<div class="Ih2E3d">> No the error I got was<br>
> Could not deduce (Controller m v c)<br>
> from the context (Controller m v c2)<br>
> arising from a use of `MVC' at NM8\GUI\PanZoom.hs:126:32-65<br>
> Possible fix:<br>
> add (Controller m v c) to the context of the constructor `MVC'<br>
> In the expression: MVC m v (PZC s z (unsafeCoerce c))<br>
> In the definition of `panZoomedMVC'':<br>
> panZoomedMVC' s z (MVC m v c) = MVC m v (PZC s z (unsafeCoerce c))<br>
> I got this after adding the type signature of<br>
> panZoomedMVC' :: (Controller m v c, PanZoomable z) =><br>
> State -> z -> MVC m v -> MVC m v<br>
<br>
</div>No function with the type signature of panZoomedMVC' can be called<br>
(unless there is a functional dependency that uniquely determines c<br>
from m and v). It's ambiguous; there's no way to know which instance<br>
to call.<br>
<br>
GHC allows such a function to get an inferred type, but then when it<br>
comes time to call it (and provide the Controller instance) or type<br>
check it against a provided signature, it cannot resolve the ambiguity<br>
and you get that error.<br>
<br>
What is happening in this case is something along these lines:<br>
<br>
1) Infer a type and constraints for panZoomedMVC':<br>
<br>
Constraints:<br>
Controller t1 t2 t3<br>
PanZoomable t4<br>
<br>
Type:<br>
State -> t4 -> MVC t1 t2 -> MVC t1 t2<br>
<br>
2) Unify the inferred type signature with your provided signature<br>
<br>
Constraints:<br>
Controller m v t3<br>
PanZoomable z<br>
<br>
Type:<br>
<div class="Ih2E3d"> State -> z -> MVC m v -> MVC m v<br>
<br>
</div>3) Verify that constraints are sufficient. This fails, because the<br>
use of Controller in the function (Controller m v t3) doesn't match<br>
the use provided by your constraint (Controller m v c).<br>
<br>
However, leaving out the type signature doesn't help you; it just<br>
delays your problem. Because of the ambiguity, panZoomedMVC' cannot<br>
be called; you'll get the error at the callsite instead.<br>
<br>
To solve this problem, either add a dummy argument that fixes "c", or<br>
add a functional dependency or associated type to Controller that<br>
fixes c based on m and v. For example:<br>
<br>
> data Proxy a = Proxy<br>
<div class="Ih2E3d">> panZoomedMVC' :: (Controller m v c, PanZoomable z) =><br>
</div>> Proxy c -> State -> z -> MVC m v -> MVC m v<br>
> panZoomedMVC' _ s z mvc = ...<br>
<br>
Then you can pass the proper "Proxy" when calling the function to make<br>
the typechecker happy.<br>
<br>
or<br>
<br>
> class Controller m v c | m v -> c where ...<br>
<br>
or<br>
<br>
> class Controller m v where<br>
> type Control m v<br>
> ...<br>
<font color="#888888"><br>
-- ryan<br>
</font></blockquote></div><br></div>