RE: Instances for data types

Haskell's inability to hide instance declarations is an oft-discussed problem. The designers of the language went to some trouble to arrange that equality on (say) URIs could not mean one thing in one place and another thing in another. Lacking that, it matters exactly where in the program the type inference engine resolves the overloading, something that in principle the Haskell type system leaves open. In short, the implicit-ness of instances conflicts in both practical ways (e.g. what do you call them), and theoretical ways, with the desire to localise them. Implicit parameters were developed largely in response to this difficulty; they make instances explicit. My advice would be: use explicit function inside libraries, if you don't want to expose the functions to the library client. Your second suggestion, a more elaborate scheme for default methods, has less by way of theoretical difficulties, I think, though I have never seen the details worked out. As usual, there's the question of whether the benefit in expressiveness is worth the cost in language complexity. And it makes it harder to answer the question "what code is executed by this call to foo", because I have to look down the chain of overlapping instance declarations -- if I can find them. Nevertheless, it may be that the practical utility is so great (at least for some programs) that it'd be worth working out the details. Simon | -----Original Message----- | From: libraries-bounces@haskell.org [mailto:libraries-bounces@haskell.org] On Behalf Of S. Alexander | Jacobson | Sent: 30 April 2004 20:09 | To: Simon Marlow | Cc: libraries | Subject: RE: Instances for data types | | Alternatively, since you can't control the export | of instance declarations, is there a way to | declare a deriving separate from the definition of | a type? | | For example, Network.URI should not have an | Eq instance because some applications may | legitimately want to define URI equivalence | differently (e.g. case sensitivity). OTOH, there | are lots of times when the default behavior is | just fine and having to define readsPrec/showsPrec | manually is just a PITA. | | If there isn't already a way to do this | how about this strawman syntax: | | instance Eq URI default | | And (going slightly OT) as long we are are | simplifying instance declarations, how about | making it easier to specialize them? For example | in my DBMS code, I had stuff like this: | | instance Property BasicProp String | where | emptyProp x = bpEmpty | deleteRecordId = bpDeleteRecordId | insertRecordId = bpInsertRecordId | | instance Property BasicProp Integer | where | emptyProp x = bpEmpty | deleteRecordId = bpDeleteRecordId | insertRecordId = bpInsertRecordId | | instance Property BasicProp Double | where | emptyProp x = bpEmpty | deleteRecordId = bpDeleteRecordId | insertRecordId = bpInsertRecordId | | The actually list of functions is actually much | longer. For some types, I may want to specialize | some of these functions, but for most of them, the | default behavior is good enough. I'd like to | declare default implementations e.g. | | instance Property BasicProp a where | | And then only if I have a more interesting type | do: | | instance Property BasicProp CoolType where | | And only define the functions that are different | from the default behavior for (Propry BasicProp a) | | -Alex- | | _________________________________________________________________ | S. Alexander Jacobson mailto:me@alexjacobson.com | tel:917-770-6565 http://alexjacobson.com | | | On Fri, 30 Apr 2004, Simon Marlow wrote: | | > On 27 April 2004 20:58, Sven Panne wrote: | > | > > Playing around with System.Posix.Terminal, I realized that there are | > > no Read, Show, Eq, Enum, ... instances for the data types defined | > > there (TerminalState, TerminalMode, ...). This is not a very | > > difficult problem to solve in one's | > > own program, but it's not very handy, either. | > | > By all means go ahead and add these instances. | > | > > This raises a general | > > question: What instances should be defined in the standard libraries | > > for types like | > > this? A general policy would be a good thing. IMHO, at least Read, | > > Show, Typeable and Eq could be expected, having Ord, Enum and | > > Bounded, too, would be nice. | > | > Good point. I've been meaning to create a separate document so we have | > somewhere to collect general library policies like this. It's on my | > whiteboard... | > | > Cheers, | > Simon | > _______________________________________________ | > Libraries mailing list | > Libraries@haskell.org | > http://www.haskell.org/mailman/listinfo/libraries | > | | _______________________________________________ | Libraries mailing list | Libraries@haskell.org | http://www.haskell.org/mailman/listinfo/libraries

On 04/05/2004, at 6:39 PM, Simon Peyton-Jones wrote:
| For example, Network.URI should not have an | Eq instance because some applications may | legitimately want to define URI equivalence | differently (e.g. case sensitivity). OTOH, there | are lots of times when the default behavior is | just fine and having to define readsPrec/showsPrec | manually is just a PITA. | | If there isn't already a way to do this | how about this strawman syntax: | | instance Eq URI default
(Sorry, this message should be in reply to Alex Jacobson's post, but I jumped in on the discussion late and don't have the original message to reply to). There's a paper by Wolfram Kahl and Jan Scheffczyk about "named instances" which targets that exact problem: http://www.informatik.uni-bonn.de/~ralf/hw2001/4.html. Although the functional programming language Haskell has a powerful type class system, users frequently run into situations where they would like to be able to define or adapt instances of type classes only after the remainder of a component has been produced. However, Haskell's type class system essentially only allows late binding of type class constraints on free type variables, and not on uses of type class members at variable-free types. In the current paper we propose a language extension that enhances the late binding capabilities of Haskell type classes, and provides more flexible means for type class instantiation. The latter is achieved via named instances that do not participate in automatic context reduction, but can only be used for late binding. By combining this capability with the automatic aspects of the Haskell type class system, we arrive at an essentially conservative extension that greatly improves flexibility of programming using type classes and opens up new structuring principles for Haskell library design. We exemplify our extension through the sketch of some applications and show how our approach could be used to explain or subsume other language features as for example implicit parameters. We present a typed lambda-calculus for our extension and provide a working prototype type checker on the basis of Mark Jones' ``Typing Haskell in Haskell''. Of course, the changes made to the "Typing Haskell in Haskell" type checker would have to be propagated back to GHC (if that's possible). -- % Andre Pang : trust.in.love.to.save

Hmm. The feature in this paper looks really useful! Right now I am working on log writing/recovery code and running into the difficulty/annoyance of wanting to override the read/show methods for CalendarTime provided by the Time library. I don't want to have to write my own Read/Show for all the various intervening types that eventually contains CalendarTime! (Note: Based on my cursory read, I don't think I can use implicit parameters to solve this problem so if there is a choice between one or the other, I prefer named instances!) I'm not sure, but it also looks like names instances may give you the ability to declare Set as an instance of Monad. Yay! (apropos a prior thread). I can't tell whether it allows me to do the type defaulting that would have been useful for the DBMS code, but if it did, even better! Another nice thing about named instances is that it gets rid of the annoying lack of globality of instance declarations. For some reason it is ok to do: import MyModule (hiding myFunc) import MyModule2 (myFunc) But you can't do the same with instance declarations. Note: I don't know if this means that myFunc means different things in different places, but I don't see why instance declarations should be treated differently. -Alex- _________________________________________________________________ S. Alexander Jacobson mailto:me@alexjacobson.com tel:917-770-6565 http://alexjacobson.com On Tue, 4 May 2004, Andre Pang wrote:
On 04/05/2004, at 6:39 PM, Simon Peyton-Jones wrote:
| For example, Network.URI should not have an | Eq instance because some applications may | legitimately want to define URI equivalence | differently (e.g. case sensitivity). OTOH, there | are lots of times when the default behavior is | just fine and having to define readsPrec/showsPrec | manually is just a PITA. | | If there isn't already a way to do this | how about this strawman syntax: | | instance Eq URI default
(Sorry, this message should be in reply to Alex Jacobson's post, but I jumped in on the discussion late and don't have the original message to reply to).
There's a paper by Wolfram Kahl and Jan Scheffczyk about "named instances" which targets that exact problem:
http://www.informatik.uni-bonn.de/~ralf/hw2001/4.html.
Although the functional programming language Haskell has a powerful type class system, users frequently run into situations where they would like to be able to define or adapt instances of type classes only after the remainder of a component has been produced. However, Haskell's type class system essentially only allows late binding of type class constraints on free type variables, and not on uses of type class members at variable-free types. In the current paper we propose a language extension that enhances the late binding capabilities of Haskell type classes, and provides more flexible means for type class instantiation. The latter is achieved via named instances that do not participate in automatic context reduction, but can only be used for late binding. By combining this capability with the automatic aspects of the Haskell type class system, we arrive at an essentially conservative extension that greatly improves flexibility of programming using type classes and opens up new structuring principles for Haskell library design. We exemplify our extension through the sketch of some applications and show how our approach could be used to explain or subsume other language features as for example implicit parameters. We present a typed lambda-calculus for our extension and provide a working prototype type checker on the basis of Mark Jones' ``Typing Haskell in Haskell''.
Of course, the changes made to the "Typing Haskell in Haskell" type checker would have to be propagated back to GHC (if that's possible).
-- % Andre Pang : trust.in.love.to.save
participants (3)
-
Andre Pang
-
S. Alexander Jacobson
-
Simon Peyton-Jones