# Revamping the numeric classes

Tom Pledger Tom.Pledger@peace.com
Fri, 9 Feb 2001 17:29:09 +1300

```Marcin 'Qrczak' Kowalczyk writes:
| On Thu, 8 Feb 2001, Tom Pledger wrote:
|
| > nice answer: give the numeric literal 10 the range type 10..10, which
| > is defined implicitly and is a subtype of both -128..127 (Int8) and
| > 0..255 (Word8).
|
| What are the inferred types for
|     f = map (\x -> x+10)
|     g l = l ++ f l
| ? I hope I can use them as [Int] -> [Int].

f, g :: (Subtype a b, Subtype 10..10 b, Num b) => [a] -> [b]
Yes, because of the substitution {Int/a, Int/b}.

| >         x + y + z                 -- as above
| >
| >     --> (x + y) + z               -- left-associativity of (+)
| >
| >     --> realToFrac (x + y) + z    -- injection (or treating up) done
| >                                   -- conservatively, i.e. only where needed
|
| What does it mean "where needed"? Type inference does not proceed
| inside-out.

In the expression

(x + y) + z

we know from the explicit type signature (in your question that I was
responding to) that x,y::Int and z::Double.  Type inference does not
need to treat x or y up, because it can take the first (+) to be Int
addition.  However, it must treat the result (x + y) up to the most
specific supertype which can be added to a Double.

|     h f = f (1::Int) == (2::Int)
| Can I apply f

h?

| to a function of type Int->Double?

Yes.

| If no, then it's a pity, because I could inline it (the comparison
| would be done on Doubles).  If yes, then what is the inferred type
| for h? Note that Int->Double is not a subtype of Int->Int, so if h
| :: (Int->Int)->Bool, then I can't imagine how h can be applied to
| something :: Int->Double.

There's no explicit type signature for the result of applying f to
(1::Int), so...

h :: (Subtype a b, Subtype Int b, Eq b) => (Int -> a) -> Bool

That can be inferred by following the structure of the term.  Function
terms do seem prone to an accumulation of deferred subtype
constraints.

Regards,
Tom

```