
On Jul 26, 2010, at 12:35 PM, John Lato wrote:
Incidentally, there seems to be a consensus that this a Bad Idea [1]. Even when you specify a type class context on a data declaration, Haskell still requires you to specify the context on functions that use that data (Address c a).
This has always puzzled me. Take the obvious data Ord key => BST key val = Empty | Node key val (BST key val) (BST key val) Why would anyone say this if they didn't *want* the constraint implied on every use? If you want the constraint implied on every use of any constructor, including ones where the constructor is used for pattern matching, what do you do if not this? Good software engineering involves *controlled* use of redundancy. Having it *stated* in one place and *checked* in others is an example. Requiring the same information to be repeated everywhere is not.
What's worse is that you need the class restriction for *all* functions that use an Address,
and if you didn't WANT that, you wouldn't say this. Oh sure, something like is_empty (Empty) = True is_empty (Node _ _ _ _) = Fase doesn't happen to make use of any constrained component. But it is part of a *group* of methods which collectively don't make any sense without it, so there's no real practical advantage to having some functions constrained and some not (unless you count delaying error message as an advantage).
and don't export the Address data constructor.
This doesn't help _within_ the defining module where you are pattern matching. In "stupid theta", the only stupidity would seem to be refusing to honour the programmer's evident intent. It's rather like saying "Oh the programmer said this constructor argument must be an Int, but I'll require him to repeat that everywhere".