4

Consider the following function

add1 :: Num a => a -> a
add1 x = x + 1

and the following applications

*Main> add1 2
3
*Main> add1 2.2
3.2
*Main> add1 (read "1")
2
add1 (read "1.5"::Float)
2.5
*Main> add1 (read "1.5")
*** Exception: Prelude.read: no parse

Why does the last invication of add1 fail for floating point numbers, while it works for integers? Why do I have to specify a type in that case?

1 Answer 1

8

GHCi gives it type

> :t add1 (read "1.5")
add1 (read "1.5") :: (Read a, Num a) => a

So, its still polymorphic. However, when evaluated in GHCi, it implicitly printed, so GHCi must pick some concrete type for a. GHCi uses the defaulting rules, and statically chooses a = Integer. Note that this choice is done statically (during type checking, roughly), and only depends on types (e.g. String), not actual values (e.g. "1.5"). Integer is both a Read and a Num, so all static checks pass.

More in detail, GHCi tries types (), Integer, Double -- in that order, unless there is a default declaration saying otherwise.

Then, at run-time the code behaves as

> add1 (read "1.5") :: Integer
*** Exception: Prelude.read: no parse

since the string can not be parsed. By comparison, this would be fine:

> add1 (read "1.5") :: Float
2.5
Sign up to request clarification or add additional context in comments.

3 Comments

I think a key point is that the type is inferred/chosen statically, and does not depend on the string. Also, I believe this defaulting rule is actually standard.
@dfeuer The standard defaulting rule (without GHCi's ExtendedDefaultRules extension) leaves out (), and works in fewer circumstances.
@ØrjanJohansen, I know, but I believe it works in this one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.