Num class
Marcin 'Qrczak' Kowalczyk
mk167280@students.mimuw.edu.pl
Thu, 19 Oct 2000 13:11:04 +0200 (CEST)
On Thu, 19 Oct 2000, Tom Pledger wrote:
> = case filter p (subtypes t) of
> [] -> t
> [t'] -> tryToBeMoreSpecific p t'
> ts -> case filter p (leastSpecificCommonSubtypes ts) of
> [t''] -> tryToBeMoreSpecific p t''
> _ -> --ambiguity
Why it is bad:
- Adding a subtype elsewhere may make a program ambiguous. (Well, it is so
with classes too, but at least it occurs only for overlapping instances,
not unrelated subtypes of a generic type.)
- Assuming that "more specific" means something like "subtype", types
are usually put in some ordered sequences. This means that it is not
enough for each type to know a basic framework, but it must also
know a type just above or below it. When various types come from
unrelated sources, it is unlikely that they will know one another
in the right order.
For example when we have sized integer types (Int8 etc.) and
types that are mirrors of C types (CInt, CLong etc.), the sequence
of subtypes is a mix of both families. Should both families know
each other? When Posix types (CPid etc.) are added, they are
again mixed. I can't imagine where all these subtyping instances
would be defined.
What is worse, whether CLong is smaller or larger than Int is
implementation defined. Currently it does not prevent having
an implementation independent set of instances. Conversion in
both directions is explicit anyway, and literals just have the
right type. With your proposal a type that wants to put itself
at the right place in the sequence containing Int and CLong is
in trouble.
Of course some of these types could be defined as synonyms, but
it's not necessarily a good idea in general. It would make
correctness of a code dependent on the implementation, by not
catching code that makes unportable assumptions about type
equivalences.
- When Int and CLong are isomorphic and thus declared subtypes of each
other, wouldn't your proposal make the compiler loop? It's getting
hairier and hairier.
> 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.
I doubt it's simpler fot the programmer. Certainly not simpler for me:
I know how the current rules work but I don't know how subtyping could
work :-)
> There should be no subtype relationship between Int8 and Word8 in
> either direction, because they denote different things: numbers and
> encodings respectively.
I hope we are not misunderstood. Word8 in GHC is an integer type
representing values 0..255. It is definitely a number, in the same sense
as Int8. Only their ranges are not contained in one another.
> If Word8 literals are required, as opposed to terms like fromEnum 10,
> they should have some other appearance like 10W.
And you are saying that your proposal is less ugly than the current
state? :-)
> I'd be very cautious about putting Double into any subtype
> relationship at all, because its meaning is tied back into its
> representation.
But people need to use floating point literals!
Each Double is representable as Rational. Your proposal thus lets 0.125
be typed as Double, which can be implicitly coerced to Rational when
needed. What about 0.1? It would lose precision when going to Rational
through Double. OTOH it should definitely be allowed as a Double value
too. How would you allow 0.1 to be used as either Rational or Double?
> 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!
That's why subtypes are not a right tool for typing numeric literals :-)
(Assuming that they can fit Haskell at all.)
--
Marcin 'Qrczak' Kowalczyk