Search code examples
haskellio-monad

How to read three consecutive integers from stdin in Haskell?


I want to read an input like 12 34 56 into three integers using Haskell.

For a single integer, one might use myInteger <- readLn. But for this case, I have not found any solution, except the one of first reading a line, then replacing all spaces with ,, (using something like:

spaceToCommas str =
  let repl ' ' = ','
      repl  c =   c
  in map repl str

) and then calling read '[' ++ str ++ ']' which feels very hackish. Also, it does not allow me to state that I want to read three integers, it will attempt to read any amount of integers from stdin.

There has to be a better way.

Note that I would like a solution that does not rely on external packages. Using e.g. Parsec is of course great, but this simple example should not require the use of a full-fledged Parser Combinator framework, right?


Solution

  • What about converting the string like:

    convert :: Read a => String -> [a]
    convert = map read . words
    

    words splits the given string into a list of strings (the "words") and then we perform a read on every element using map.

    and for instance use it like:

    main = do
        line <- getLine
        let [a,b,c] = convert line :: [Int] in putStrLn (show (c,a,b))
    

    or if you for instance want to read the first three elements and don't care about the rest (yes this apparently requires super-creativity skills):

    main = do
        line <- getLine
        let (a:b:c:_) = convert line :: [Int] in putStrLn (show (c,a,b))
    

    I here returned a tuple that is rotated one place to the right to show parsing is done.