Chris Wong 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>
> wrote:
>>
>> Hi,
>>
>> 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
>> design?

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
dependency*:

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
and examples.

(By the way, I'd suggest using longer names like "Ring" and

Chris

>> Thanks,
>>
>> Stu
>> _______________________________________________
>> Beginners mailing list
>
>
>
>
> --
> Regards
>
> Sumit Sahrawat
>
> _______________________________________________