Reputation: 312
I am trying to learn to write Haskell programs. I am failing to read n
lines input.
The input is
n
a b (<----- n times)
where n
, a
, b
are numbers.
I tried
input = []
readString 0 = return()
readString n =
do
z <- getLine
z:input
readString (n-1)
main = do
n <- getLine
readString n
which throws errors. How do I looped read correctly in Haskell?
Upvotes: 2
Views: 365
Reputation: 152837
Haskell is immutable: once you write
input = []
then input
is []
forever and ever, amen. You could use the same technique you used for having a "changing" value of n
to have a "changing" value of input
, that is, pass it as an argument to readString
:
readString 0 input = return input
readString n input = do
z <- getLine
readString (n-1) (z:input)
If you do this, you will discover that the lines you input get put into input
starting from the end -- so they come out in reverse order! (If your code snippet had worked, it would also have behaved this way.) One easy fix would be to change the base case:
readString 0 input = return (reverse input)
A more idiomatic fix would be to do away with the argument entirely, simply returning things in the right order in the first place:
readString 0 = return []
readString n = do
z <- getLine
zs <- readString (n-1)
return (z:zs)
As you get comfortable with the standard library, you might first graduate to
readString 0 = return []
readString n = liftA2 (:) getLine (readString (n-1))
and then to skipping the definition of readString
entirely in favor of rewriting main
:
main = do
n <- readLn
lines <- replicateM n getLine
...
Upvotes: 8