Haskell ReplicateM IO
I am trying to create a function that allows the user to enter a list of strings. The function takes a length and allows the user to enter the length of another 1 line. Then each line is checked to make sure it is the same length as the original line. However, I have several problems and cannot find a solution.
The problems are that I can enter more count-1 strings and the length is not calculated as I expected .. for example if I enter [12, 13] and then [121, "13"] an error is given, although they have the same length!
read :: IO [Line]
read = do
line <- getLine
let count = length line
lines <- replicateM (count-1) $ do
line <- getLine
if length line /= count
then fail "too long or too short"
else return line
return $ line : lines
The string is of type String.
readLn gives a parsing error.
source to share
It seems to me that you are confused about the difference between fetching a string as String
well as reading / parsing an input string as a custom type. You use getLine
that which always returns exactly String
what the user enters. For comparison:
Prelude> fmap length getLine
["12","13"]
11
Prelude> length "[\"12\",\"13\"]" -- explanation of the 11
11
Prelude> fmap length (readLn :: IO [String])
["12","13"]
2
Prelude> length ["12", "13"] -- explanation of the 2
2
As shown here, you probably want to use readLn
that first gets the input string and then parses it with read
.
-- defined in the Prelude
readLn = do
s <- getLine
return (read s)
If I change my code to include imports and definitions below:
import Control.Monad
type Line = [String]
... and call readLn
instead getLine
, then I can print literal strings ["12","13"]
and ["121","13"]
no errors.
source to share