
GHC's (maybe Haskell98's?) Complex type is defined with a RealFloat constraint on type type itself, rather than on some of the instances and functions: data (RealFloat a) => Complex a = !a :+ !a I think the practice of constraint in type definitions is generally discouraged, and I'm wondering if there are reasons other than history for having the constraint here. Is removing it on the table for Haskell'? I just got bit by what I think is a typical problem. I added a VectorSpace instance for 'Complex a' and discovered that my 'a' must be in RealFloat, even though I use only zero, addition, subtraction, and scaling. I suspect this gripe has been raised before ... Thanks, - Conal

On 21 May 2008, at 9:25 am, Conal Elliott wrote:
I think the practice of constraint in type definitions is generally discouraged,
Is this true? If so, why? If I have a data type that simply doesn't make sense unless some of the type variables belong to certain classes, _shouldn't_ that be stated clearly in the declaration rather than hidden elsewhere? -- "I don't want to discuss evidence." -- Richard Dawkins, in an interview with Rupert Sheldrake. (Fortean times 232, p55.)

From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Richard A. O'Keefe
On 21 May 2008, at 9:25 am, Conal Elliott wrote:
I think the practice of constraint in type definitions is generally discouraged,
Is this true? If so, why? If I have a data type that simply doesn't make sense unless some of the type variables belong to certain classes, _shouldn't_ that be stated clearly in the declaration rather than hidden elsewhere?
I recall this from Graham Klyne, but I think his use case might be a bit different: http://www.ninebynine.org/Software/Learning-Haskell-Notes.html#type-clas ses-and-data I don't know all the pros and cons (are there pros, other than the documentation argument you gave?). I think: 1. adding the constraint has some costs, and very few benefits 2. nobody does it much, if at all. Probably for the first reason. Alistair ***************************************************************** Confidentiality Note: The information contained in this message, and any attachments, may contain confidential and/or privileged material. It is intended solely for the person(s) or entity to which it is addressed. Any review, retransmission, dissemination, or taking of any action in reliance upon this information by persons or entities other than the intended recipient(s) is prohibited. If you received this in error, please contact the sender and delete the material from any computer. *****************************************************************

Richard A. O'Keefe wrote:
I think the practice of constraint in type definitions is generally discouraged,
Is this true? If so, why?
As a practical matter, a Haskell 98 constraint infects every place you might like to use the type. They're like prion proteins, corrupting everything they touch, replicating implacably as they go. Here's the usual pattern that leads to the abandonment of constraints on types by the previously innocent coder. You add the constraint in the one place you think you need it, only to find that the type checker insists that three more are now required on previously pristine code that otherwise never mentions your type. You reluctantly add the constraint to those, and the compiler demands another seven uses. Now your code is littered with meaningless spaghetti constraints that obfuscate your original intent. The same contagion also costs you the ability to derive instances of many useful built-in typeclasses, such as Functor. The constraint on the type requires that a function such as fmap must have the constraint, too, and thus the plague continues. Pre-GADT syntax doesn't have this problem. {-# LANGUAGE GADTs #-} data Foo a = Show a => Foo a foo :: Foo a -> a foo (Foo a) = a Notice the change in the location of the constraint, and the lack of a need for a constraint on the function foo. Real GADTs avoid the problem in a similar way. data Bar a where Bar :: Show a => a -> Bar a bar :: Bar a -> a bar (Bar a) = a

On Tue, 20 May 2008, Conal Elliott wrote:
GHC's (maybe Haskell98's?) Complex type is defined with a RealFloat constraint on type type itself, rather than on some of the instances and functions:
data (RealFloat a) => Complex a = !a :+ !a
I think the practice of constraint in type definitions is generally discouraged, and I'm wondering if there are reasons other than history for having the constraint here. Is removing it on the table for Haskell'?
I just got bit by what I think is a typical problem. I added a VectorSpace instance for 'Complex a' and discovered that my 'a' must be in RealFloat, even though I use only zero, addition, subtraction, and scaling.
I suspect this gripe has been raised before ...
Actually, in NumericPrelude there is no such constraint and Complex is an instance of Module and VectorSpace: http://darcs.haskell.org/numericprelude/src/Number/Complex.hs http://hackage.haskell.org/cgi-bin/hackage-scripts/package/numeric-prelude
participants (5)
-
Bayley, Alistair
-
Bryan O'Sullivan
-
Conal Elliott
-
Henning Thielemann
-
Richard A. O'Keefe