Read single line from stdin in Haskell using IO.readLn
Solution 1
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 ()
.
Solution 2
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
Solution 3
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.
Betamos
Web developer and full time computer science student in Stockholm, Sweden. Interested in various programming languages like PHP, java, JavaScript. Currently I'm excited by game development in JavaScript and Drupal. I'm also very familiar with the 3D-tools Cinema 4D and Maxwell Render.
Updated on December 22, 2021Comments
-
Betamos over 2 years
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
toputStrLn 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