Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MultiParamTypeClasses, FunctionalDependencies, and calling ambiguous functions

With functional dependencies, I can declare the Foo class:

class Foo a b c | a -> b where
    foo1 :: a -> b -> c
    foo2 :: a -> c

and when I call foo2, everything works fine. The compiler knows which instance to use because of the dependency.

But if I remove the dependency to create Foo':

class Foo' a b c where
    foo1' :: a -> b -> c
    foo2' :: a -> c

everything still compiles fine, but now whenever I try to call foo2' GHC throws an error about not being able to resolve which instance to use because b is ambiguous.

Is it ever possible to call foo2' without error? If so, how? If not, why doesn't it generate a compilation error?

like image 411
Mike Izbicki Avatar asked Jan 30 '26 11:01

Mike Izbicki


1 Answers

It is impossible to call foo2' in this context, because, as Daniel Fischer says, there is no way to determine which instance to use. For example, if you had:

instance Foo' Int Int Int where
    foo2' x = x

instance Foo' Int Bool Int where
    foo2' x = x + 1

Both of these foo2's have the same type signature, so there is no way to determine which one to call.

The usual way around this problem is to use a proxy:

data Proxy a = Proxy

class Foo'' a b c = where
    foo2'' :: Proxy b -> a -> c

Which you use like so to select which instance:

foo'' (Proxy :: Proxy Bool) 42
like image 120
luqui Avatar answered Feb 02 '26 03:02

luqui



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!