pipes-safe-1.1.0: Control/Proxy/Safe/Prelude.hs
-- | Prelude of proxies providing simple resource management features
{-# LANGUAGE Rank2Types #-}
module Control.Proxy.Safe.Prelude (
-- * Handle allocation
withFile,
-- * String I/O
-- $string
readFileS,
writeFileD
) where
import Control.Proxy (Proxy(request, respond), Producer)
import Control.Proxy.Safe.Core (SafeIO, ExceptionP, bracket, tryIO)
import qualified System.IO as IO
-- | Safely allocate a 'IO.Handle' within a managed 'Proxy'
withFile
:: (Monad m, Proxy p)
=> (forall x . SafeIO x -> m x) -- ^Monad morphism
-> FilePath -- ^File
-> IO.IOMode -- ^IO Mode
-> (IO.Handle -> ExceptionP p a' a b' b m r) -- ^Continuation
-> ExceptionP p a' a b' b m r
withFile morph file ioMode = bracket morph (IO.openFile file ioMode) IO.hClose
{- $string
Note that 'String's are very inefficient, and I will release future separate
packages with 'ByteString' and 'Text' operations. I only provide these to
allow users to test simple I/O without requiring any additional library
dependencies.
-}
{-| Read from a file, lazily opening the 'IO.Handle' and automatically closing
it afterwards
-}
readFileS
:: (Proxy p) => FilePath -> () -> Producer (ExceptionP p) String SafeIO ()
readFileS file () = withFile id file IO.ReadMode $ \handle -> do
let go = do
eof <- tryIO $ IO.hIsEOF handle
if eof
then return ()
else do
str <- tryIO $ IO.hGetLine handle
respond str
go
go
{-| Write to a file, lazily opening the 'IO.Handle' and automatically closing it
afterwards
-}
writeFileD
:: (Proxy p) => FilePath -> x -> ExceptionP p x String x String SafeIO r
writeFileD file x0 = do
withFile id file IO.WriteMode $ \handle -> do
let go x = do
str <- request x
tryIO $ IO.hPutStrLn handle str
x2 <- respond str
go x2
go x0