-- | Functions and types for safely working with 'IO.Handle's in 'Scoped' blocks -- -- @since 0.1.0.0 module Control.Monad.Scoped.Handle ( -- * Scoped 'IO.Handle' ScopedHandle -- * Allocating a new 'ScopedHandle' in a 'Scoped' block , file -- * Working with 'ScopedHandle' , IO.IOMode (..) , hPutStrLn , hPutStr , hGetLine , hGetContents ) where import Control.Monad.Scoped.Internal (Scoped (UnsafeMkScoped), ScopedResource (UnsafeMkScopedResource, unsafeUnwrapScopedResource), (:<)) import Data.Text (Text) import Data.Text.IO qualified as TIO import System.IO qualified as IO import UnliftIO (MonadIO (liftIO), MonadUnliftIO) import UnliftIO.IO qualified as IOU -- | Just like 'IO.Handle' but bound to a 'Scoped' block -- -- @since 0.1.0.0 type ScopedHandle s = ScopedResource s IO.Handle -- | Given a 'FilePath', safely allocates and deallocates a 'ScopedHandle' in a 'Scoped' block -- -- @since 0.1.0.0 file :: MonadUnliftIO m => FilePath -> IO.IOMode -> Scoped (s : ss) m (ScopedHandle s) file path mode = UnsafeMkScoped \k -> IOU.withFile path mode (k . UnsafeMkScopedResource) -- | Like 'IO.hPutStrLn' but for 'ScopedHandle' -- -- @since 0.1.0.0 hPutStrLn :: (MonadIO m, s :< ss) => ScopedHandle s -> Text -> Scoped ss m () hPutStrLn h s = liftIO (TIO.hPutStrLn (unsafeUnwrapScopedResource h) s) -- | Like 'IO.hPutStr' but for 'ScopedHandle' -- -- @since 0.1.0.0 hPutStr :: (MonadIO m, s :< ss) => ScopedHandle s -> Text -> Scoped ss m () hPutStr h s = liftIO (TIO.hPutStr (unsafeUnwrapScopedResource h) s) -- | Like 'IO.hGetLine' but for 'ScopedHandle' -- -- @since 0.1.0.0 hGetLine :: (MonadIO m, s :< ss) => ScopedHandle s -> Scoped ss m Text hGetLine h = liftIO (TIO.hGetLine (unsafeUnwrapScopedResource h)) -- | Like 'IO.hGetContents' but for 'ScopedHandle' -- -- @since 0.1.0.0 hGetContents :: (MonadIO m, s :< ss) => ScopedHandle s -> Scoped ss m Text hGetContents h = liftIO (TIO.hGetContents (unsafeUnwrapScopedResource h))