I wrote this code :
calculIOTest :: IO ()
calculIOTest = do
putStrLn "Give me two numbers"
l1 <- getLine
let x1 = read l1
l2 <- getLine
let x2 = read l2
print (x1 + x2)
I wanted code that takes two numbers and returns the sum. If I test my function with two integers it works but if I put a float then there is a problem with the error:
***Exception: Prelude.read: no parse
I would have understood with a string and a number but here I have trouble understanding what is causing the problem.
I tried to review how read works and indeed if I do:
(read 10000.9) + (read 1115)
It gives me the errors:
Could not deduce (Fractional String)
arising from the literal ‘10000.9’
from the context: (Read a, Num a)
bound by the inferred type of it :: (Read a, Num a) => a
at <interactive>:135:1-28
and
Could not deduce (Num String) arising from the literal ‘1115’
from the context: (Read a, Num a)
bound by the inferred type of it :: (Read a, Num a) => a
at <interactive>:135:1-28
I would like to understand why it does not work in my code and where does the error prevent with the read?
Since you're adding x1
and x2
the compiler can infer that those have to have a Num
instance and the default type for Num a
is Integer
. So implicitly your code is equivalent to the following:
calculIOTest :: IO ()
calculIOTest = do
putStrLn "Give me two numbers"
l1 <- getLine
let x1 = (read l1 :: Integer)
l2 <- getLine
let x2 = (read l2 :: Integer)
print (x1 + x2)
and obviously you can't parse a float representation as an Integer
.
To accept Double
s all you have to do is explicitly annotate that type:
calculIOTest :: IO ()
calculIOTest = do
putStrLn "Give me two numbers"
l1 <- getLine
let x1 = (read l1 :: Double)
l2 <- getLine
let x2 = (read l2 :: Double)
print (x1 + x2)
Your bare reads (read 10000.9) + (read 1115)
would suffer from the same problem had you included the necessary "
(read
takes a String
not floats or ints)
read "10000.9" + read "1115"
too results in ***Exception: Prelude.read: no parse
and the fix is the same, annotate the type you want.