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.

+3


source to share


1 answer


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.

+5


source







All Articles