Num class

Tom Pledger Tom.Pledger@peace.com
Thu, 19 Oct 2000 23:16:18 +1300 (NZDT)


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