<div dir="ltr"><div><div><div>Hi Olaf,<br><br></div><div>You can use ~ to let instances get selected before ghc has deduced that two types are equal. <a href="https://gist.github.com/aavogt/1cb0ca6f1654b09111d3">https://gist.github.com/aavogt/1cb0ca6f1654b09111d3</a> is closer to what you're looking for, except "eval (+) (4,5)" doesn't work unless the result type is given.<br></div><div><br>Besides the ghc manual, it might also help to look at <a href="http://okmij.org/ftp/Haskell/typecast.html">http://okmij.org/ftp/Haskell/typecast.html</a> <br><br></div><div>Regards,<br></div><div>Adam<br></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Apr 14, 2015 at 5:12 PM, Olaf Klinke <span dir="ltr"><<a href="mailto:olf@aatal-apotheke.de" target="_blank">olf@aatal-apotheke.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Dear cafe,<br>
<br>
I want to write an evaluation function that uncurries its function argument as necessary. Examples should include:<br>
<br>
eval :: (a -> b) -> a -> b<br>
eval :: (a -> b -> c) -> a -> (b -> c)<br>
eval :: (a -> b -> c) -> (a,b) -> c<br>
and hence have both<br>
eval (+) 4 5<br>
eval (+) (4,5)<br>
typecheck.<br>
<br>
My approach is to use a type class:<br>
<br>
class Uncurry f a b where<br>
eval :: f -> a -> b<br>
instance Uncurry (a -> b) a b where<br>
eval = ($)<br>
instance (Uncurry f b c) => Uncurry ((->) a) f) (a,b) c where<br>
eval f (a,b) = eval (f a) b<br>
<br>
This works, but not for polymorphic arguments. One must annotate function and argument with concrete types when calling, otherwise the runtime does not know what instance to use.<br>
<br>
Type inference on ($) is able to infer the type of either of f, a or b in the expression b = f $ a if the type of two is known. Thus I am tempted to add functional dependencies<br>
<br>
class Uncurry f a b | f a -> b, a b -> f, f b -> a<br>
<br>
but I get scary errors: With only the first of the three dependencies, the coverage condition fails. Adding UndecidableInstances, the code compiles. Now type inference on the return type b works, but one can not use e.g. (+) as function argument. Adding the second dependency results in the compiler rejecting the code claiming "Functional dependencies conflict between instance declarations". I can not quite see where they would, and the compiler does not tell me its counterexample.<br>
I can see that<br>
eval max (True,False) :: Bool<br>
-- by second instance declaration,<br>
-- when max :: Bool -> Bool -> Bool<br>
eval max (True,False) :: (Bool,Bool) -> (Bool,Bool)<br>
-- by first instance declaration<br>
-- when max :: (Bool,Bool) -> (Bool,Bool) -> (Bool,Bool)<br>
but this ambiguity is precisely what the dependency a b -> f should help to avoid, isn't it?<br>
<br>
Judging by the number of coverage condition posts on this list this one is easy to get wrong and the compiler messages are not always helpful. Is this a kind problem? Would anyone care to elaborate?<br>
<br>
Thanks, Olaf<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
</blockquote></div><br></div>