Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.2k views
in Technique[技术] by (71.8m points)

why cant an Int and a floating point number be added in haskell

why wont this work :-

(length [1,2,3,4]) + 3.2

while this works:-

2+3.3

I understand that in the first case the result is an Int+Float but is that not the same in the second case too, or does Haskell automatically infer the type in the second case to be :- Num+Num whereas it does not do that in the first case?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...