
On 29 Dec 2007, at 9:31 PM, alex wrote:
Hi there.
If someone can tell me why I am getting type ambiguity in the following code:
class (Ord s, Num s) => Scalar s where zero :: s
class Metric m where delta :: Scalar s => m -> m -> s
(=~) :: m -> m -> Bool (/~) :: m -> m -> Bool
(=~) a b = (delta a b) <= zero (/~) a b = not (a =~ b)
I will scream.
The error I get compiling is:
Ambiguous type variable `s' in the constraint: `Scalar s' arising from a use of `delta' at test.hs:13:23-31 Probable fix: add a type signature that fixes these type variable(s)
If I change "Scalar" to "Num", and "zero" to "0" within the class "Metric", then it works.
I don't get it. "zero" is defined in the "Scalar" class, and "delta" returns a Scalar, and Scalar derives "Ord", so where's the ambiguity?
delta is polymorphic in s; that is, it works for any value of type s in the class Scalar, and has some definition that (presumably) uses the value zero. (And I assume other methods of Scalar). Its value is thus some arbitrary function of the methods of Scalar (and its super classes); to call it, you need a specific type so the function can be supplied with the methods to use. The code is still ambiguous if you switch to Num, but since newcomers to Haskell are frequently confused by Haskell's approach to numeric computations, Haskell 98 has a solution for this case; ambiguous type variables which are constrained to be instances of Num get `defaulted' to particular numeric types. So the ambiguity goes away. jcc