
Marcin 'Qrczak' Kowalczyk writes:
On Thu, 19 Oct 2000, Tom Pledger wrote:
If you had such a non-standard type, I imagine you'd also declare something like this:
instance Subtype Int8 Int16 where ... instance Subtype Int16 Int24 where ... instance Subtype Int24 Int where ...
and hence literals in the range -128 to 127 would be typed Int8, etc.
What would be the rule for typing integer literals? Currently it's simple: fromIntegral (number::Integer), and Int8 is a completely non-magical type.
With your proposal, assume that the programmer makes a bunch of subtype declarations for his own types... What now?
(Assuming that subtyping can be reasonably embedded in the Haskell's type system at all.)
Of course! There's nothing quite like a nice flight of fancy. :-) A possible rule for typing integer literals is: intLitType x = tryToBeMoreSpecific (x `belongsTo`) IntegerT tryToBeMoreSpecific p t = case filter p (subtypes t) of [] -> t [t'] -> tryToBeMoreSpecific p t' ts -> case filter p (leastSpecificCommonSubtypes ts) of [t''] -> tryToBeMoreSpecific p t'' _ -> --ambiguity It's more complicated for the implementer, but makes things simpler for the programmer because we can then remove the Integral class and some unintuitive dualities like length/genericLength.
A more concrete example. Does 10 have type Int8 or Word8? Is Int8 a subtype of Word8, or the reverse? How could 10 be used as both Int8 and Word8?
There should be no subtype relationship between Int8 and Word8 in either direction, because they denote different things: numbers and encodings respectively. We can say that every Int8 value *is* an Int16 value, but there is no reasonable corresponding statement about Int8 and Word8. Faced with the choice, I'd say that 10 looks like a number, and make it an Int8. If Word8 literals are required, as opposed to terms like fromEnum 10, they should have some other appearance like 10W.
Current Haskell rules and not perfect: 12345::Int8 is legal. Conversions are explicit and there is no distinction between always safe conversions and those that may take an out of range parameter. But I'm happy with it; conversions are rarely used anyway, rules are simple, and there is no need of asking a question like: is every Int representable as Double (the answer may depend on the implementation).
I'd be very cautious about putting Double into any subtype relationship at all, because its meaning is tied back into its representation. If you can't explain that "every X is a Y" without referring to representation issues, you shouldn't be declaring X as a subtype of Y! Admittedly I dodged your general comment and focussed on your example. I need to be more certain that subtyping is a feasible language extension, before I try to tell you what you should be happy with. :-) Regards, Tom