[Haskell-cafe] FunDeps and type inference

adam vogt vogt.adam at gmail.com
Wed Apr 15 05:09:10 UTC 2015


Hi Olaf,

You can use ~ to let instances get selected before ghc has deduced that two
types are equal. https://gist.github.com/aavogt/1cb0ca6f1654b09111d3 is
closer to what you're looking for, except "eval (+) (4,5)" doesn't work
unless the result type is given.

Besides the ghc manual, it might also help to look at
http://okmij.org/ftp/Haskell/typecast.html

Regards,
Adam

On Tue, Apr 14, 2015 at 5:12 PM, Olaf Klinke <olf at aatal-apotheke.de> wrote:

> Dear cafe,
>
> I want to write an evaluation function that uncurries its function
> argument as necessary. Examples should include:
>
> eval :: (a -> b) -> a -> b
> eval :: (a -> b -> c) -> a -> (b -> c)
> eval :: (a -> b -> c) -> (a,b) -> c
> and hence have both
> eval (+) 4 5
> eval (+) (4,5)
> typecheck.
>
> My approach is to use a type class:
>
> class Uncurry f a b where
>   eval :: f -> a -> b
> instance Uncurry (a -> b) a b where
>   eval = ($)
> instance (Uncurry f b c) => Uncurry ((->) a) f) (a,b) c where
>   eval f (a,b) = eval (f a) b
>
> 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.
>
> 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
>
> class Uncurry f a b | f a -> b, a b -> f, f b -> a
>
> 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.
> I can see that
> eval max (True,False) :: Bool
> -- by second instance declaration,
> -- when max :: Bool -> Bool -> Bool
> eval max (True,False) :: (Bool,Bool) -> (Bool,Bool)
> -- by first instance declaration
> -- when max :: (Bool,Bool) -> (Bool,Bool) -> (Bool,Bool)
> but this ambiguity is precisely what the dependency a b -> f should help
> to avoid, isn't it?
>
> 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?
>
> Thanks, Olaf
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20150415/23272c02/attachment.html>


More information about the Haskell-Cafe mailing list