I was playing around with the FunctionalDependencies-Extension of Haskell, along with MultiParamTypeClasses. I defined the following:
class Add a b c | a b -> c where
(~+) :: a -> b -> c
(~-) :: a -> b -> c
neg :: a -> a
zero :: a
which works fine (I've tried with instances for Int and Double with the ultimate goal of being able to add Int and Doubles without explicit conversion).
When I try to define default implementations for neg or (~-) like so:
class Add ...
...
neg n = zero ~- n
GHCi (7.0.4) tells me the following:
Ambiguous type variables `a0', `b0', `c0' in the constraint:
(Add a0 b0 c0) arising from a use of `zero'
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `(~-)', namely `zero'
In the expression: zero ~- n
In an equation for `neg': neg n = zero ~- n
Ambiguous type variable `a0' in the constraint:
(Add a0 a a) arising from a use of `~-'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: zero ~- n
In an equation for `neg': neg n = zero ~- n
I think I do understand the problem here. GHC does not know which zero to use, since it could be any zero yielding anything which in turn is fed into a ~- which we only know of, that it has an a in it's right argument and yields an a.
So how can I specify that it should be the zero from the very same instance, i.e. how can I express something like:
neg n = (zero :: Add a b c) ~- n
I think the a, b and c here are not the a b c form the surrounding class, but any a b and c, so how can I express a type which is a reference to the local type variables?