-------------------------------------------------------------------- -- | -- Module : System.IO.Strict -- Copyright : (c) Nicolas Pouillard 2009 -- License : BSD3 -- -- Maintainer : Nicolas Pouillard -- Stability : provisional -- -- This module wraps the functions of the "System.IO" module at a different type namely 'SIO'. -- -- The purpose of this module is to export only strict /IO/ functions, by strict -- we mean strict in the result. The arguments of these functions may only by partially forced, -- but when the function returns, the arguments can no longer be forced by the function. -- When the type of the value to be forced is polymorphic, a 'NFData' constraint is added -- since we (internally) use 'rnf' to force the value. Then we rely on the behavior -- of 'NFData' instances to provide the fact that any lazy argument passed to a 'SIO' function -- will not leak-out after the call. -- -- These functions do not necessarily use their arguments completely but they do not hold -- or return any value that could depend on these arguments. If the original functions -- from "System.IO" module were already strict, then this module just provides them -- at another type. -- Some functions from the original module are famously lazy like the 'getContents' like -- functions: in this module their results are deeply forced. -- -- In Haskell, monad operations ('return' and '>>=') have to be lazy. Therefore the 'SIO' -- monad is not completely strict (i.e. pure values can still be lazy). So in this module we -- expose the 'return'' function that forces the given value before putting it into the monad. -- -- Since this module uses the same names as "System.IO", it is designed to be imported /qualified/. -- -- @ -- import System.IO.Strict (SIO) -- import qualified System.IO.Strict as SIO -- @ -------------------------------------------------------------------- module System.IO.Strict ( -- * Types SIO, run, return', -- * Functions stricter than there "System.IO" counterparts getContents, -- :: SIO String hGetContents, -- :: Handle -> SIO String readFile, -- :: FilePath -> SIO String read, -- :: (NFData sa, Read sa) => String -> SIO sa readLn, -- :: (NFData sa, Read sa) => SIO sa fix, -- :: NFData sa => (sa -> SIO sa) -> SIO sa withBinaryFile, -- :: NFData sr => FilePath -> IOMode -> (Handle -> SIO sr) -> SIO sr withFile, -- :: NFData sr => FilePath -> IOMode -> (Handle -> SIO sr) -> SIO sr -- * Functions as strict as there "System.IO" counterparts appendFile, -- :: FilePath -> String -> SIO () getChar, -- :: SIO Char getLine, -- :: SIO String hPrint, -- :: (Show a) => Handle -> a -> SIO () hPutStrLn, -- :: Handle -> String -> SIO () hReady, -- :: Handle -> SIO Bool interact, -- :: (String -> String) -> SIO () openBinaryTempFile, -- :: FilePath -> String -> SIO (FilePath, Handle) openTempFile, -- :: FilePath -> String -> SIO (FilePath, Handle) print, -- :: (Show a) => a -> SIO () putChar, -- :: Char -> SIO () putStr, -- :: String -> SIO () putStrLn, -- :: String -> SIO () writeFile, -- :: FilePath -> String -> SIO () hClose, -- :: Handle -> SIO () hFileSize, -- :: Handle -> SIO Integer hFlush, -- :: Handle -> SIO () hGetBuf, -- :: Handle -> Ptr a -> Int -> SIO Int hGetBufNonBlocking, -- :: Handle -> Ptr a -> Int -> SIO Int hGetBuffering, -- :: Handle -> SIO BufferMode hGetChar, -- :: Handle -> SIO Char hGetEcho, -- :: Handle -> SIO Bool hGetLine, -- :: Handle -> SIO String hGetPosn, -- :: Handle -> SIO HandlePosn hIsClosed, -- :: Handle -> SIO Bool hIsEOF, -- :: Handle -> SIO Bool hIsOpen, -- :: Handle -> SIO Bool hIsReadable, -- :: Handle -> SIO Bool hIsSeekable, -- :: Handle -> SIO Bool hIsTerminalDevice, -- :: Handle -> SIO Bool hIsWritable, -- :: Handle -> SIO Bool hLookAhead, -- :: Handle -> SIO Char hPutBuf, -- :: Handle -> Ptr a -> Int -> SIO () hPutBufNonBlocking, -- :: Handle -> Ptr a -> Int -> SIO Int hPutChar, -- :: Handle -> Char -> SIO () hPutStr, -- :: Handle -> String -> SIO () hSeek, -- :: Handle -> SeekMode -> Integer -> SIO () hSetBinaryMode, -- :: Handle -> Bool -> SIO () hSetBuffering, -- :: Handle -> BufferMode -> SIO () hSetEcho, -- :: Handle -> Bool -> SIO () hSetFileSize, -- :: Handle -> Integer -> SIO () hSetPosn, -- :: HandlePosn -> SIO () hShow, -- :: Handle -> SIO String hTell, -- :: Handle -> SIO Integer hWaitForInput, -- :: Handle -> Int -> SIO Bool isEOF, -- :: SIO Bool openBinaryFile, -- :: FilePath -> IOMode -> SIO Handle openFile, -- :: FilePath -> IOMode -> SIO Handle stderr, -- :: Handle stdin, -- :: Handle stdout -- :: Handle ) where import Prelude (Bool, Int, Integer, String, Char, FilePath, Read, Show, (.)) import Control.DeepSeq (NFData(..)) import System.IO (IOMode, Handle, BufferMode, HandlePosn, SeekMode) import GHC.Ptr (Ptr) import System.IO.Strict.Internals (SIO, wrap0, wrap0', wrap1, wrap1', wrap2, wrap3, run, return') import qualified System.IO.Strict.Internals as SIO import qualified System.IO as IO -- | Note that 'getContents' is stricter than its counterpart in "System.IO". getContents :: SIO String getContents = wrap0' IO.getContents -- | Note that 'hGetContents' is stricter than its counterpart in "System.IO". hGetContents :: Handle -> SIO String hGetContents = wrap1' IO.hGetContents -- | Note that 'withBinaryFile' is stricter than its counterpart in "System.IO". withBinaryFile :: NFData sr => FilePath -> IOMode -> (Handle -> SIO sr) -> SIO sr withBinaryFile fp mode kont = wrap0' (IO.withBinaryFile fp mode (SIO.run . kont)) -- | Note that 'withFile' is stricter than its counterpart in "System.IO". withFile :: NFData sr => FilePath -> IOMode -> (Handle -> SIO sr) -> SIO sr withFile fp mode kont = wrap0' (IO.withFile fp mode (SIO.run . kont)) -- | Note that 'fix' is stricter than its counterpart in "System.IO". fix :: NFData sa => (sa -> SIO sa) -> SIO sa fix kont = wrap0' (IO.fixIO (SIO.run . kont)) -- | Note that 'readFile' is stricter than its counterpart in "System.IO". readFile :: FilePath -> SIO String readFile = wrap1' IO.readFile -- | Note that 'read' is stricter than its counterpart in "System.IO". read :: (NFData sa, Read sa) => String -> SIO sa read = wrap1' IO.readIO -- | Note that 'readLn' is stricter than its counterpart in "System.IO". readLn :: (NFData sa, Read sa) => SIO sa readLn = wrap0' IO.readLn getChar :: SIO Char getChar = wrap0 IO.getChar appendFile :: FilePath -> String -> SIO () appendFile = wrap2 IO.appendFile getLine :: SIO String getLine = wrap0 IO.getLine hPrint :: (Show a) => Handle -> a -> SIO () hPrint = wrap2 IO.hPrint hPutStrLn :: Handle -> String -> SIO () hPutStrLn = wrap2 IO.hPutStrLn hReady :: Handle -> SIO Bool hReady = wrap1 IO.hReady interact :: (String -> String) -> SIO () interact = wrap1 IO.interact openBinaryTempFile :: FilePath -> String -> SIO (FilePath, Handle) openBinaryTempFile = wrap2 IO.openBinaryTempFile openTempFile :: FilePath -> String -> SIO (FilePath, Handle) openTempFile = wrap2 IO.openTempFile print :: (Show a) => a -> SIO () print = wrap1 IO.print putChar :: Char -> SIO () putChar = wrap1 IO.putChar putStr :: String -> SIO () putStr = wrap1 IO.putStr putStrLn :: String -> SIO () putStrLn = wrap1 IO.putStrLn writeFile :: FilePath -> String -> SIO () writeFile = wrap2 IO.writeFile hClose :: Handle -> SIO () hClose = wrap1 IO.hClose hFileSize :: Handle -> SIO Integer hFileSize = wrap1 IO.hFileSize hFlush :: Handle -> SIO () hFlush = wrap1 IO.hFlush hGetBuf :: Handle -> Ptr a -> Int -> SIO Int hGetBuf = wrap3 IO.hGetBuf hGetBufNonBlocking :: Handle -> Ptr a -> Int -> SIO Int hGetBufNonBlocking = wrap3 IO.hGetBufNonBlocking hGetBuffering :: Handle -> SIO BufferMode hGetBuffering = wrap1 IO.hGetBuffering hGetChar :: Handle -> SIO Char hGetChar = wrap1 IO.hGetChar hGetEcho :: Handle -> SIO Bool hGetEcho = wrap1 IO.hGetEcho hGetLine :: Handle -> SIO String hGetLine = wrap1 IO.hGetLine hGetPosn :: Handle -> SIO HandlePosn hGetPosn = wrap1 IO.hGetPosn hIsClosed :: Handle -> SIO Bool hIsClosed = wrap1 IO.hIsClosed hIsEOF :: Handle -> SIO Bool hIsEOF = wrap1 IO.hIsEOF hIsOpen :: Handle -> SIO Bool hIsOpen = wrap1 IO.hIsOpen hIsReadable :: Handle -> SIO Bool hIsReadable = wrap1 IO.hIsReadable hIsSeekable :: Handle -> SIO Bool hIsSeekable = wrap1 IO.hIsSeekable hIsTerminalDevice :: Handle -> SIO Bool hIsTerminalDevice = wrap1 IO.hIsTerminalDevice hIsWritable :: Handle -> SIO Bool hIsWritable = wrap1 IO.hIsWritable hLookAhead :: Handle -> SIO Char hLookAhead = wrap1 IO.hLookAhead hPutBuf :: Handle -> Ptr a -> Int -> SIO () hPutBuf = wrap3 IO.hPutBuf hPutBufNonBlocking :: Handle -> Ptr a -> Int -> SIO Int hPutBufNonBlocking = wrap3 IO.hPutBufNonBlocking hPutChar :: Handle -> Char -> SIO () hPutChar = wrap2 IO.hPutChar hPutStr :: Handle -> String -> SIO () hPutStr = wrap2 IO.hPutStr hSeek :: Handle -> SeekMode -> Integer -> SIO () hSeek = wrap3 IO.hSeek hSetBinaryMode :: Handle -> Bool -> SIO () hSetBinaryMode = wrap2 IO.hSetBinaryMode hSetBuffering :: Handle -> BufferMode -> SIO () hSetBuffering = wrap2 IO.hSetBuffering hSetEcho :: Handle -> Bool -> SIO () hSetEcho = wrap2 IO.hSetEcho hSetFileSize :: Handle -> Integer -> SIO () hSetFileSize = wrap2 IO.hSetFileSize hSetPosn :: HandlePosn -> SIO () hSetPosn = wrap1 IO.hSetPosn hShow :: Handle -> SIO String hShow = wrap1 IO.hShow hTell :: Handle -> SIO Integer hTell = wrap1 IO.hTell hWaitForInput :: Handle -> Int -> SIO Bool hWaitForInput = wrap2 IO.hWaitForInput isEOF :: SIO Bool isEOF = wrap0 IO.isEOF openBinaryFile :: FilePath -> IOMode -> SIO Handle openBinaryFile = wrap2 IO.openBinaryFile openFile :: FilePath -> IOMode -> SIO Handle openFile = wrap2 IO.openFile stderr :: Handle stderr = IO.stderr stdin :: Handle stdin = IO.stdin stdout :: Handle stdout = IO.stdout