[Haskell-cafe] [Haskell-beginners] Multi-parameter type classes and ambiguous type variables...
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
"AdditiveGroup" instead, as they're easier to read.)
Chris
>> Thanks,
>>
>> Stu
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
>
>
>
> --
> Regards
>
> Sumit Sahrawat
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>
--
https://lambda.xyz
More information about the Haskell-Cafe
mailing list