Send Beginners mailing list submissions to
[email protected]
To subscribe or unsubscribe via the World Wide Web, visit
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
[email protected]
You can reach the person managing the list at
[email protected]
When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."
Today's Topics:
1. Re: [Haskell-cafe] Multi-parameter type classes and
ambiguous type variables... (Stuart Hungerford)
----------------------------------------------------------------------
Message: 1
Date: Sun, 22 Mar 2015 07:15:52 +1100
From: Stuart Hungerford <[email protected]>
To: Chris Wong <[email protected]>
Cc: The Haskell-Beginners Mailing List - Discussion of primarily
beginner-level topics related to Haskell <[email protected]>,
Haskell-cafe Cafe <[email protected]>
Subject: Re: [Haskell-beginners] [Haskell-cafe] Multi-parameter type
classes and ambiguous type variables...
Message-ID:
<cag+kmrhr6vtuvjcmvk+pzxda8mha-h0apaw8wmh8hgkgpml...@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8
On Sat, Mar 21, 2015 at 7:31 PM, Chris Wong <[email protected]> wrote:
> [...]
>>> 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.
Thanks for this excellent explanation.
> (By the way, I'd suggest using longer names like "Ring" and
> "AdditiveGroup" instead, as they're easier to read.)
Yes -- I stripped the example down, including the full names of the
type classes, for explaining the issue. I could well have left the
full names though.
Stu
------------------------------
Subject: Digest Footer
_______________________________________________
Beginners mailing list
[email protected]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
------------------------------
End of Beginners Digest, Vol 81, Issue 52
*****************************************