9.5. Select: Synchronous I/O multiplexing

The Select interface provides a Haskell wrapper for the select() OS call supplied by many modern UNIX variants. Select exports the following:

type TimeOut = Maybe Int
  -- Nothing => wait indefinitely.
  -- Just x | x >= 0    => block waiting for 'x' micro seconds.
  --        | otherwise => block waiting for '-x' micro seconds.

hSelect :: [Handle]
        -> [Handle]
        -> [Handle]
        -> TimeOut
        -> IO SelectResult

type SelectResult
 = ( [Handle]  -- input  handles ready
   , [Handle]  -- output handles ready
   , [Handle]  -- exc.   handles ready

Here's an example of how it could be used:

module Main(main) where

import Select
import IO

main :: IO ()
main = do
  hSetBuffering stdin NoBuffering
  putStrLn "waiting for input to appear"
  hSelect [stdin] [] [] Nothing
  putStrLn "input ready, let's try reading"
  x <- getChar
  print x

where the call to hSelect makes the process go to sleep until there's input available on stdin.

Notice that this particular use of hSelect is now really a no-op with GHC compiled code, as its implementation of IO will take care to avoid blocking the process (i.e., all running Haskell threads), and call select() for you, if needs be. However, hSelect exposes functionality that is useful in other contexts (e.g., you want to wait for input on two Handles for 3 seconds, but no longer.)