Search code examples
haskellio

Is there a getInt function on Haskell?


I would like to have a getInt :: IO Int function on Haskell. It would be a function that would take an integer from stdin, leaving the rest of the buffer intact.

The library function with this type I have found, readLn :: IO Int, for example, would not work with an input like:

2
3 4

Because it would take the entire line 3 4, instead of taking 3 and leaving 4 for the next getInt. Although I know I could read the complete string and then split it using words, I would like to ask if there is a way which does not consume the buffer.

Is there any function on the standard libraries doing this? Is there any simple/obvious way to create a getInt I am missing?


Solution

  • Here I turn my comment into an answer, since it seems the original asker is okay with consuming separators. First we will define a getWord analog to getLine; then we will readIO the result. We will be careful to catch EOF exceptions in case they occur.

    import Control.Exception
    import Control.Applicative
    import Data.Char
    import System.IO.Error
    
    getWord :: IO String
    getWord = handle handleEOF $ do
      c <- getChar
      if isSpace c then return [] else (c:) <$> getWord
      where
      handleEOF e = if isEOFError e then return [] else throwIO e
    
    readWord :: Read a => IO a
    readWord = getWord >>= readIO
    

    Beware: this will of course not work well for values to be read that have a space in them (like Data.Maps or other complex data types).