How to input several values in one line in haskell

haskell

Solution

Read a line with `getLine`, split it into `words`, and `read` each:

readInts :: IO [Int]
readInts = fmap (map read.words) getLine

it reads any number of Ints:

ghci> readInts
1 2 3
[1,2,3]
ghci> readInts
1 2 3 4 5 6
[1,2,3,4,5,6]

You could restrict to three:

read3Ints :: IO [Int]
read3Ints = do
     ints <- readInts
     if length ints == 3 then return ints else do
         putStrLn ("sorry, could you give me exactly three integers, "
                  ++ "separated by spaces?")
         read3Ints

which looks like this:

ghci> read3Ints
1 2
sorry, could you give me exactly three integers, separated by spaces?
1 23 , 5, 6
sorry, could you give me exactly three integers, separated by spaces?
1,2,3
sorry, could you give me exactly three integers, separated by spaces?
1 3 6

The secrets of `fmap`

`fmap` works a bit like `map`, but you can use it more widely:

ghci> fmap (*10) [1,2,3,4]
[10,20,30,40]
ghci> fmap (*10) (Just 5)
Just 50
ghci> map (fmap (*10)) [Left 'b', Right 4, Left 'c', Right 7]
[Left 'b',Right 40,Left 'c',Right 70]
ghci> fmap words getLine
Hello there me hearties!
["Hello","there","me","hearties!"]

In `getInts`, I did `fmap (map read.words)` to split the line by spaces, then `map read` to turn each one into an `Int`. The compiler knows I wanted `Int` because of the type signature - I'd get an error if I omitted it.

Problem

For example, I want to write a program which will take 3 integers as input from command line. The functions I have learned is `readLn` to read values from entire line. But `readLn` seems to parse the entire line as a single value. How can I get the three values of one line with haskell?

Original source