More newbie typeclass confusion...

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? Thanks. I will understand Haskell eventually... =) Make the switch to the world's best email. Get the new Yahoo!7 Mail now. www.yahoo7.com.au/worldsbestemail

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

On Dec 30, 2007 3:43 AM, Jonathan Cast
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
Just to clear up common confusion: the caller chooses s here, not the delta function. So delta has to work for any choice of s the caller chooses (as long as it is an instance of Scalar).
(=~) :: m -> m -> Bool (/~) :: m -> m -> Bool
(=~) a b = (delta a b) <= zero
What instance of Scalar do you want delta to return here? There's no way for the compiler to deduce that information. What you probably want is a fundep or associated type, associating a single choice of scalar for each metric: class (Scalar (Field m)) => Metric m where type Field m :: * delta :: m -> m -> Field m ... instance Metric Double where type Field Double = Double delta = (-) ... Luke
participants (3)
-
alex
-
Jonathan Cast
-
Luke Palmer