
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 8/28/10 06:44 , Greg wrote:
On Aug 27, 2010, at 8:15 PM, Brandon S Allbery KF8NH wrote:
The instance doesn't conform to the class definition; it includes a constraint that the class does not, as the class insists that the type of the result must be independent of the type of the argument, while the instance insists that they must be identical.
I think what you're saying is that not only can an instance do no less than the class has guaranteed, it can do no *more*-- meaning the instance can't further restrict the return type even if that return type still conforms to the class definition. In this case returning a Float breaks the class contract because I've gone and said what type of Floating type will be returned.
Right. You're not the only one vexed by this; one of the advanced Haskell tricks is "restricted monads", which are an attempt to deal with the fact that (for example) a Set is a monad but can't be a Monad because Monad doesn't have an Ord constraint. Another way of thinking about this, btw, is that when you use a typeclass function the only things "visible" about the type are the things defined by the class; so if the instance wants to do something different, there's no way to enforce it. Think of it as a mechanical translator that can faithfully translate specific phrases that it knows about but garbles anything else.
The class definition doesn't mean "div2pi can return any type of Floating value", it means "div2pi *will* return any type of floating value".
More precisely, it means that when something invokes div2pi, it has the right to request any type of floating value at its sole discretion. But the instance says "nuh-uh, you get the same type you feed it, nothing else".
class TwoPi a where div2pi :: (Floating b) => a -> b
is essentially impossible to conform to because b is completely untethered to anything else in the code and not all "(Floating b)"'s are created equal.
It's possible, but you need to use a polymorphic function to produce it. Problem is, there is no standard function that does so for Floating. There are ways to do so for Fractional and for RealFloat (the latter being fairly horrid in practice) but not for Floating which sits in between them in the numeric typeclass hierarchy. (This may be another instance of "the Haskell numeric typeclass hierarchy is woefully misdesigned". You might want to take a look at http://www.haskell.org/haskellwiki/Numeric_Prelude. Warning: "well designed" for Haskellers means "conforms to mathematical theory", so expect to get lost in a soup of groups, rings, fields, and the like :)
I think the intent of the functional dependency in the suggestion you provided in your second email is essentially to tether b to something. Unfortunately if chokes in the second, non-Foo, instance.
Probably; when I write code late at night it's likely to be buggy :)
I think I've mistakenly been thinking of instances as more like subclasses, but that's apparently not quite right (thus the "instance" keyword, I suppose).
The OO terminology is somewhat unfortunate; they don't actually follow any standard OO rules fully, only just enough to cause confusion. - -- brandon s. allbery [linux,solaris,freebsd,perl] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.10 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkx5JYcACgkQIn7hlCsL25VAswCeKNt7/jYXjcWVDKob9kGPqov7 M60An2dgLpI/rpkng/IKcFYSxkBLdr45 =9DKm -----END PGP SIGNATURE-----