This code does not compile in GHC 7.0.3:
import System.IO
main = do
z <- readLn
print z
My intention is to read one line from stdin and store it in z, to do more advanced stuff with it later on. Error message looks like:
test.hs:5:9:
Ambiguous type variable `a0' in the constraints:
(Show a0) arising from a use of `print' at test.hs:5:9-13
(Read a0) arising from a use of `readLn' at test.hs:4:14-19
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' expression: print z
In the expression:
do { z <- readLn;
print z;
return () }
In an equation for `main':
main
= do { z <- readLn;
print z;
return () }
Obviously there is something fundamental I haven’t understood yet; please explain to me why it doesn’t work and how to fix it.
EDIT1: I fixed the compile error by changing print z to putStrLn z, so GHC understands that I want to read a string. But when I run the program, I get a runtime error which I can’t understand:
$ ./test
hello!
test: user error (Prelude.readIO: no parse)
$
I just typed “hello!” and then enter. Note that I’m running x86_64 GHC on OS X, which is considered unstable.
EDIT2: I changed readLn to getLine and it magically works for no reason. I would like to know why, but I’m happy it works.
Final code:
import System.IO
main = do
z <- getLine
print z
readLn as the type:
Read a => IO a. It reads a line from the user, and then parses the string into typea. What is typea? It is whatever you want (as long as it is an instance ofRead). For example:printhas the typeShow a => a -> IO (). It takes a type that is an instance ofShow, and prints it out. For example, to printTrue, you can useprint True. To print the Int 42, you can useprint 42.In your example, you are using print and readLn together. This doesn’t work, as haskell can’t figure out what type
readLnshould return.printcan take any type that is showable, so it doesn’t restrict to one what type would be returned. This makes the return type ofreadLnambiguous as haskell can’t figure out the type. This is what the error message is saying.What you probably what it to store just the string being entered by the user, rather than reading it into your own type. You can do this with getLine, which has the type
getLine :: IO String. Similarily you can useputStrLninstead ofprintto just print a String.putStrLnhas the typeString -> IO ().