[Haskell-cafe] [Haskell-beginners] Multi-parameter type classes and ambiguous type variables...
lambda.fairy at gmail.com
Sat Mar 21 08:31:23 UTC 2015
On Sat, Mar 21, 2015 at 8:37 PM, Sumit Sahrawat, Maths & Computing,
IIT (BHU) <sumit.sahrawat.apm13 at iitbhu.ac.in> wrote:
> This might be better answered at the haskell-cafe. Sending to cafe.
> On 21 March 2015 at 03:09, Stuart Hungerford <stuart.hungerford at gmail.com>
>> As a learning exercise I'm modelling some algebraic structures as
>> Haskell typeclasses. Some of these are multi-parameter type classes.
>> Here's a very simplified version of the type class relationships:
>> class MM a where
>> one :: a
>> class AM a where
>> zero :: a
>> class (AM a, MM a) => SR a
>> class (AM a) => AG a where
>> inv :: a -> a
>> class (SR a) => R a where
>> neg :: a -> a
>> class (R r, AG g) => M r g where
>> sca :: r -> g -> g
>> check :: (Eq g, M r g) => g -> Bool
>> check x = sca one x == x
>> The problem I have is that GHC is finding the "r" type variable in the
>> "check" function ambiguous. Given my still limited Haskell knowledge
>> I'm not surprised this is happening. What I would like to know is how
>> experienced Haskellers handle this situation in practice: is there an
>> idiomatic way of disambiguating "r" or is it a sign of poor type class
In the type signature:
check :: (Eq g, M r g) => g -> Bool
you fix the type `g`, but not the type `r`. This causes an ambiguity
in the program because if you had e.g.
instance M Float Vector where ...
instance M Int Vector where ...
both in the same program, and you passed a Vector to `check`, GHC
won't know which instance to choose.
To solve this ambiguity, either fix `r` with an extra parameter:
check :: (Eq g, M r g) => r -> g -> Bool
check one' x = sca one' x == x
Or declare that `r` is uniquely determined by `g` using a *functional
class (R r, AG g) => M r g | g -> r where
sca :: r -> g -> g
Or equivalently, using *associated types*:
class (AG g, R (Scalar g)) => M g where
type Scalar g :: *
sca :: Scalar g -> g -> g
check :: (Eq g, M g) => g -> Bool
check x = -- as before
A Google search for these two terms should yield plenty of tutorials
(By the way, I'd suggest using longer names like "Ring" and
"AdditiveGroup" instead, as they're easier to read.)
>> Beginners mailing list
>> Beginners at haskell.org
> Sumit Sahrawat
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
More information about the Haskell-Cafe