Haskell never does implicit type conversion for you. +
only ever works on two numbers of the same type, and gives you that type as the result as well. Any other usage of +
is an error, as you saw with your (length [1,2,3,4]) + 3.2
example.
However, numeric literals are overloaded in Haskell. 2
could be any numeric type, and 3.3
could be any fractional type. So when Haskell sees the expression 2 + 3.3
it can try to find a type which is both "numeric" and "fractional", and treat both numbers as that type so that the addition will work.
Speaking more precisely, +
has the type Num a => a -> a -> a
. 2
on its own is of type Num a => a
and 3.3
on its own is of type Fractional a => a
. Putting those 3 types together, the in the expression 2 + 3.3
both numbers can be given the type Fractional a => a
, because all Fractional
types are also Num
types, and this then also satisfies the type of +
. (If you type this expression into GHCi the a
gets filled in as Double
, because GHC has to default the type to something in order to evaluate it)
In the expression (length [1,2,3,4]) + 3.2
, the 3.2
is still overloaded (and in isolation would have type Fractional a => a
). But length [1,2,3,4]
has type Int
. Since one side is a fixed concrete type, the only way to satisfy the type for +
would be to fill in the a
on the other type with Int
, but that violates the Fractional
constraint; there's no way for 3.2
to be an Int
. So this expression is not well-typed.
However, any Integral
type (of which Int
is one) can be converted to any Num
type by applying fromIntegral
(this is actually how the integer literals like 2
can be treated as any numeric type). So (fromIntegral $ length [1,2,3,4]) + 3.2
will work.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…