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
If you have a String that you want to print to the screen, you should use putStrLn . If you have something other than a String that you want to print, you should use print . Look at the types! putStrLn :: String -> IO () and print :: Show a => a -> IO () .
Haskell separates pure functions from computations where side effects must be considered by encoding those side effects as values of a particular type. Specifically, a value of type (IO a) is an action, which if executed would produce a value of type a .
readLn as the type: Read a => IO a
. It reads a line from the user, and then parses the string into type a
. What is type a
? It is whatever you want (as long as it is an instance of Read
). For example:
readAInt :: IO Int
readAInt = readLn
readABool :: IO Bool
readABool = readLn
print
has the type Show a => a -> IO ()
. It takes a type that is an instance of Show
, and prints it out. For example, to print True
, you can use print True
. To print the Int 42, you can use print 42
.
In your example, you are using print and readLn together. This doesn't work, as haskell can't figure out what type readLn
should return. print
can take any type that is showable, so it doesn't restrict to one what type would be returned. This makes the return type of readLn
ambiguous 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 use putStrLn
instead of print
to just print a String. putStrLn
has the type String -> IO ()
.
This is what you changed your code to, right?
import System.IO
main = do
z <- readLn
putStrLn z
putStrLn
writes a String
to stdout, so z
is a String
. Therefore readLn
will read a String
from stdin.
BUT... readLn
expects to read a Haskell-formatted value from stdin. i.e. instead of expecting you to type something like This is a string
, it anticipates it in quote marks: "This is a string"
.
To fix, replace readLn
with getLine
, which reads in literal text, not a Haskell-formatted string.
import System.IO
main = do
z <- getLine
putStrLn z
readLn reads back a type that you specify, and so can't be used in this way: it needs to be used in a function that specifies its type. getLine, on the other hand, always returns a String, so it does what you want.
It's worth noting that you might want to use putStrLn instead of print as well; print will add quotation marks.
Thus do { z <- getLine; putStrLn z; }
in GHCi should do what you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With