    {-# LANGUAGE Safe #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  System.IO.Strict
    -- Copyright   :  (c) Don Stewart 2007
    -- License     :  BSD-style (see the file libraries/base/LICENSE)
    --
    -- Maintainer  :  dons@galois.com
    -- Stability   :  stable
    -- Portability :  portable
    --
    -- The standard IO input functions using strict IO.
    --
    -----------------------------------------------------------------------------

    module System.IO.Strict (

        -- * Strict Handle IO
        hGetContents,              -- :: Handle -> IO [Char]

        -- * Strict String IO wrappers
        getContents,               -- :: IO String
        readFile,                  -- :: FilePath -> IO String
        interact                   -- :: (String -> String) -> IO ()

      ) where

    import Prelude ( String, (>>=), seq, return, (.), (=<<), FilePath, length)
    import System.IO (IO)
    import qualified System.IO as IO

    -- -----------------------------------------------------------------------------
    -- Strict hGetContents

    -- | Computation 'hGetContents' @hdl@ returns the list of characters
    -- corresponding to the unread portion of the channel or file managed
    -- by @hdl@, which is immediate closed.
    --
    -- Items are read strictly from the input Handle.
    --
    -- This operation may fail with:
    --
    --  * 'isEOFError' if the end of file has been reached.

    hGetContents    :: IO.Handle -> IO.IO String
    hGetContents :: Handle -> IO String
    hGetContents Handle
    h  = Handle -> IO String
    IO.hGetContents Handle
    h IO String -> (String -> IO String) -> IO String
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \String
    s -> String -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    s Int -> IO String -> IO String
    forall a b. a -> b -> b
    `seq` String -> IO String
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return String
    s

    -- -----------------------------------------------------------------------------
    -- Standard IO

    -- | The 'getContents' operation returns all user input as a single string,
    -- which is read stirctly (same as 'hGetContents' 'stdin').

    getContents     :: IO String
    getContents :: IO String
    getContents     =  Handle -> IO String
    hGetContents Handle
    IO.stdin
    {-# INLINE getContents #-}

    -- | The 'interact' function takes a function of type @String->String@
    -- as its argument.  The entire input from the standard input device is
    -- passed to this function as its argument, and the resulting string is
    -- output on the standard output device.

    interact        ::  (String -> String) -> IO ()
    interact :: (String -> String) -> IO ()
    interact String -> String
    f      =   String -> IO ()
    IO.putStr (String -> IO ()) -> (String -> String) -> String -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> String
    f (String -> IO ()) -> IO String -> IO ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< IO String
    getContents
    {-# INLINE interact #-}

    -- | The 'readFile' function reads a file and
    -- returns the contents of the file as a string.
    -- The file is read strictly, as with 'getContents'.

    readFile        :: FilePath -> IO String
    readFile :: String -> IO String
    readFile String
    name   =  String -> IOMode -> IO Handle
    IO.openFile String
    name IOMode
    IO.ReadMode IO Handle -> (Handle -> IO String) -> IO String
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Handle -> IO String
    hGetContents
    {-# INLINE readFile #-}