RE: Strange error in show for datatype
| So, obviously, the next version of Haskell should have a type system | with subtyping, don't you agree? :-) It's always delightful to find that some awkward fumbling has been Done Properly by someone else earlier. My claim was that forall a. Show a => T could be implemented by passing a bottom dictionary for Show. I didn't say this, but the obvious thing to do is to fix 'a' to be some vacuous type Empty, and arrange that Empty is an instance of every class, with a bottom dictionary. And you're telling us that the subtyping folk worked this out yonks ago. Excellent! (Reference, for this particular point?) In a system with subtyping this would work even if T contained a free, as you say. But even in a system *without* subtyping, if 'a' is not free in T, we can safely remove the 'forall a' and fix a=Empty. (A calling context can only "see" the types in T, so this places no constraints on the calling context, which is why we don't need subtyping.) I think this is what your PPS suggested, yes? So in fact, all we need do is: for each class, find the variance of each of its parameters in an ambiguous type, zap any positive parameters to Empty That sounds pretty easy. We don't need Haskell 2 for that. I feel a little implementation coming on. Hmm. One question. Suppose I have forall a. C (a->Int) Int => T and C is positive in its first parameter. Can I zap 'a' to Empty? It looks as if it still occurs positively. What about data types? | PS In some previous version of Haskell (1.3?), the Prelude defined an | empty type called Void, but it has since been removed. Apparently, | people didn't see the potential of Void... Void was a type with one element. What we really want here is a type with no elements. It's also useful to be able to introduce such empty types for phantom-type purposes, so GHC now lets you say data T and get a type T with no values. Simon
On Thu, Oct 04, 2001 at 12:36:55AM -0700, Simon Peyton-Jones wrote:
So in fact, all we need do is: for each class, find the variance of each of its parameters in an ambiguous type, zap any positive parameters to Empty
That sounds pretty easy. We don't need Haskell 2 for that. I feel a little implementation coming on.
This is, nevertheless, an extension to the language, right? Or is the class system poorly enough specified that it's unclear?
Void was a type with one element. What we really want here is a type with no elements. It's also useful to be able to introduce such empty types for phantom-type purposes, so GHC now lets you say
data T
and get a type T with no values.
Ah, excellent! I've frequently wanted to do this. Best, Dylan Thurston
My claim was that
forall a. Show a => T
could be implemented by passing a bottom dictionary for Show.
Excuse me, but Jan-Willem Maessen has already shown that this implementation can give unexpected results. A simple example: instance Show MyType where shows _ = ("element of my type" : ) Then show (undefined :: MyType) yields "element of my type" and with the suggested implementation show undefined would yield undefined The instance may look a bit weird, but in general you cannot assume that the functions of all instances of all classes are strict. In fact, some Haskell systems (e.g. nhc98) extend class Show by another method showsType :: a -> String; the function is non-strict in all instances. Anyway, I find all these suggestions about occurrence and variance of type variables rather complicated. Worse than the monomorphic restriction. Admittedly, many Haskell beginners fall into the `show []' trap. However, this is a chance for the teacher to discuss the problem (possibly before they fall into the trap). Any type system that prevents you from making some mistakes has to reject some perfectly sound programs (because the absence of mistakes is not decidable). Hopefully the type system is simple enough to enable the programmer to understand why a program is rejected. And fortunately in this special case there is a simple way around the problem (specify a type). By the way, I'm sure some months (a year?) ago there was a similar discussion about replacing dictionaries by bottom dictionaries on a Haskell mailing list or comp.lang.functional. Unfortunately I don't find it anymore. Ciao, Olaf -- OLAF CHITIL, Dept. of Computer Science, University of York, York YO10 5DD, UK. URL: http://www.cs.york.ac.uk/~olaf/ Tel: +44 1904 434756; Fax: +44 1904 432767
Olaf Chitil wrote: | Admittedly, many Haskell beginners fall into the `show | []' trap. Indeed. And this is a perfect example of the fact that all this bottom-dictionary passing does not work. The type of the list still matters though: Hugs> show ([] :: [Char]) "\"\"" Hugs> show ([] :: [Int]) "[]" /Koen
Koen Cleassen wrote:
Indeed. And this is a perfect example of the fact that all this bottom-dictionary passing does not work. The type of the list still matters though:
Hugs> show ([] :: [Char]) "\"\""
Hugs> show ([] :: [Int]) "[]"
Koen is absolutely right. A fundamental property of type-classes is that you can *not* assign a meaning to the program independent of its types. A haskell program is not always typeable when I erase all type signatures because some programs are inherently ambigious, like showing the empty list. As Koen shows, by giving a type signature I can disambiguate the program and it indeed gives quite different results with different type signatures. A good discussion about this property of type-classes can be found in: A Second Look at Overloading, Martin Odersky, Philip Wadler, and Martin Wehr. In Proceedings, ACM Conference on Functional Programming and Computer Architecture, La Jolla, CA, June 1995. All the best, Daan.
participants (5)
-
Daan Leijen -
Dylan Thurston -
Koen Claessen -
Olaf Chitil -
Simon Peyton-Jones