    {-# LANGUAGE CPP, NoImplicitPrelude #-}
    module System.IO.Compat (
      module Base
    , getContents'
    , hGetContents'
    , readFile'
    ) where

    import System.IO as Base

    #if !(MIN_VERSION_base(4,15,0))
    import Prelude.Compat

    -- | The 'getContents'' operation returns all user input as a single string,
    -- which is fully read before being returned
    -- (same as 'hGetContents'' 'stdin').
    --
    -- /Since: 4.15.0.0/

    getContents'    :: IO String
    getContents'    =  hGetContents' stdin

    -- | The 'readFile'' function reads a file and
    -- returns the contents of the file as a string.
    -- The file is fully read before being returned, as with 'getContents''.
    --
    -- /Since: 4.15.0.0/

    readFile'       :: FilePath -> IO String
    readFile' name  =  openFile name ReadMode >>= hGetContents'

    -- | The 'hGetContents'' operation reads all input on the given handle
    -- before returning it as a 'String' and closing the handle.
    --
    -- /Since: 4.15.0.0/

    hGetContents'   :: Handle -> IO String
    hGetContents' h =  hGetContents h >>= \s -> length s `seq` return s
     -- NB: The actual implementation of hGetContents' in `base` uses a lot of
     -- low-level code from GHC.IO.Handle.Text. What's worse, a lot of this
     -- low-level code isn't exported, so we'd have to reimplement large chunks
     -- of it in base-compat if we wanted to backport it. For now, I've opted for
     -- the simpler approach of simply defining hGetContents' in terms of
     -- hGetContents, which is the approach that the `extra` and `strict` libraries
     -- use. (Indeed, the code above is taken from `strict`.)
    #endif