pipes-safe 2.3.3 → 2.3.4
raw patch · 3 files changed
+84/−51 lines, 3 filesdep −faildep ~basedep ~containersdep ~exceptions
Dependencies removed: fail
Dependency ranges changed: base, containers, exceptions, mtl, pipes, primitive, transformers
Files
- pipes-safe.cabal +9/−12
- src/Pipes/Safe.hs +4/−35
- src/Pipes/Safe/Prelude.hs +71/−4
pipes-safe.cabal view
@@ -1,5 +1,5 @@ Name: pipes-safe-Version: 2.3.3+Version: 2.3.4 Cabal-Version: >=1.10 Build-Type: Simple License: BSD3@@ -8,7 +8,7 @@ Copyright: 2013, 2014 Gabriel Gonzalez Author: Gabriel Gonzalez Maintainer: Gabriel439@gmail.com-Tested-With: GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3+Tested-With: GHC == 8.10.7, GHC == 9.0.2, GHC == 9.2.1 Bug-Reports: https://github.com/Gabriel439/Haskell-Pipes-Safe-Library/issues Synopsis: Safety for the pipes ecosystem Description:@@ -36,18 +36,15 @@ Library Build-Depends:- base >= 4.8 && < 5 ,- containers >= 0.3.0.0 && < 0.7 ,- exceptions >= 0.6 && < 0.11,- mtl >= 2.1 && < 2.3 ,- transformers >= 0.2.0.0 && < 0.6 ,+ base >= 4.14 && < 4.17,+ containers >= 0.6.2.1 && < 0.7 ,+ exceptions >= 0.10.4 && < 0.11,+ mtl >= 2.2.2 && < 2.3 ,+ transformers >= 0.5.6.2 && < 0.6 , transformers-base >= 0.4.4 && < 0.5 , monad-control >= 1.0.0.4 && < 1.1 ,- primitive >= 0.6.2.0 && < 0.8 ,- pipes >= 4.3.0 && < 4.4- if impl(ghc < 8.0)- Build-Depends:- fail < 4.10+ primitive >= 0.7.0.0 && < 0.8 ,+ pipes >= 4.3.10 && < 4.4 Exposed-Modules: Pipes.Safe, Pipes.Safe.Prelude
src/Pipes/Safe.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE RankNTypes, TypeFamilies, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, ScopedTypeVariables,- GeneralizedNewtypeDeriving, CPP, Trustworthy #-}+ GeneralizedNewtypeDeriving, Trustworthy #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {-| This module provides an orphan 'MonadMask' instance for 'Proxy' of the@@ -86,16 +86,14 @@ , module Control.Exception ) where -import Control.Applicative (Applicative, Alternative)+import Control.Applicative (Alternative) import Control.Exception(Exception(..), SomeException(..)) import qualified Control.Monad.Catch as C import Control.Monad.Catch ( MonadCatch(..) , MonadThrow(..) , MonadMask(..)-#if MIN_VERSION_exceptions(0,10,0) , ExitCase(..)-#endif , mask_ , uninterruptibleMask_ , catchAll@@ -114,7 +112,6 @@ , SomeException ) import Control.Monad (MonadPlus, liftM)-import Control.Monad.Fail (MonadFail) import Control.Monad.Fix (MonadFix) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Trans.Control (MonadBaseControl(..))@@ -134,13 +131,9 @@ import qualified Control.Monad.Trans.Writer.Lazy as W import qualified Control.Monad.Trans.Writer.Strict as W' import qualified Control.Monad.Writer.Class as WC-#if MIN_VERSION_base(4,6,0) import Data.IORef (IORef, newIORef, readIORef, writeIORef, atomicModifyIORef')-#else-import Data.IORef (IORef, newIORef, readIORef, writeIORef, atomicModifyIORef)-#endif+import Data.Kind (Type) import qualified Data.Map as M-import Data.Monoid (Monoid) import Pipes (Proxy, Effect, Effect', runEffect) import Pipes.Internal (Proxy(..)) @@ -189,7 +182,6 @@ uninterruptibleMask = liftMask uninterruptibleMask -#if MIN_VERSION_exceptions(0,10,0) generalBracket acquire release_ use = mask $ \unmasked -> do a <- acquire let action = do@@ -204,7 +196,6 @@ -- | This is to avoid an unnecessary partial pattern match in `generalBracket` data ExitCase_ a = ExitCaseSuccess_ a | ExitCaseException_ SomeException-#endif data Finalizers m = Finalizers { _nextKey :: !Integer@@ -225,9 +216,7 @@ , Monad -- The derived instance for `MonadFail` requires a `MonadFail` instance for -- `ReaderT` which is first available in `transformers-0.5.0.0`-#if MIN_VERSION_transformers(0,5,0) , MonadFail-#endif , MonadPlus , MonadFix , EC.MonadError e@@ -245,19 +234,11 @@ lift m = SafeT (lift m) instance MonadBaseControl b m => MonadBaseControl b (SafeT m) where-#if MIN_VERSION_monad_control(1,0,0) type StM (SafeT m) a = StM m a liftBaseWith f = SafeT $ R.ReaderT $ \reader' -> liftBaseWith $ \runInBase -> f $ runInBase . (\(SafeT r) -> R.runReaderT r reader' ) restoreM = SafeT . R.ReaderT . const . restoreM-#else- newtype StM (SafeT m) a = StMT (StM m a)- liftBaseWith f = SafeT $ R.ReaderT $ \reader' ->- liftBaseWith $ \runInBase ->- f $ liftM StMT . runInBase . \(SafeT r) -> R.runReaderT r reader'- restoreM (StMT base) = SafeT $ R.ReaderT $ const $ restoreM base-#endif instance Prim.PrimMonad m => Prim.PrimMonad (SafeT m) where type PrimState (SafeT m) = Prim.PrimState m@@ -271,11 +252,7 @@ runSafeT m = C.bracket (liftIO $ newIORef $! Just $! Finalizers 0 M.empty) (\ioref -> do-#if MIN_VERSION_base(4,6,0) mres <- liftIO $ atomicModifyIORef' ioref $ \val ->-#else- mres <- liftIO $ atomicModifyIORef ioref $ \val ->-#endif (Nothing, val) case mres of Nothing -> error "runSafeT's resources were freed by another"@@ -303,7 +280,7 @@ {-| The monad used to run resource management actions, corresponding to the monad directly beneath 'SafeT' -}- type Base (m :: * -> *) :: * -> *+ type Base (m :: Type -> Type) :: Type -> Type -- | Lift an action from the 'Base' monad liftBase :: Base m r -> m r@@ -329,11 +306,7 @@ register io = do ioref <- SafeT R.ask liftIO $ do-#if MIN_VERSION_base(4,6,0) n <- atomicModifyIORef' ioref $ \val ->-#else- n <- atomicModifyIORef ioref $ \val ->-#endif case val of Nothing -> error "register: SafeT block is closed" Just (Finalizers n fs) ->@@ -342,11 +315,7 @@ release key = do ioref <- SafeT R.ask-#if MIN_VERSION_base(4,6,0) liftIO $ atomicModifyIORef' ioref $ \val ->-#else- liftIO $ atomicModifyIORef ioref $ \val ->-#endif case val of Nothing -> error "release: SafeT block is closed" Just (Finalizers n fs) ->
src/Pipes/Safe/Prelude.hs view
@@ -5,25 +5,64 @@ module Pipes.Safe.Prelude ( -- * Handle management withFile,+ withBinaryFile,+ openFile,+ openBinaryFile, -- * String I/O -- $strings readFile,- writeFile+ writeFile,++ -- * Registering/releasing+ allocate,+ allocate_ ) where +import Control.Monad.Catch (mask_) import Control.Monad.IO.Class (MonadIO(liftIO)) import Pipes (Producer', Consumer')-import Pipes.Safe (bracket, MonadSafe)+import Pipes.Safe (bracket, liftBase, register, Base, MonadSafe, ReleaseKey) import qualified Pipes.Prelude as P import qualified System.IO as IO import Prelude hiding (readFile, writeFile) --- | Acquire a 'IO.Handle' within 'MonadSafe'-withFile :: (MonadSafe m) => FilePath -> IO.IOMode -> (IO.Handle -> m r) -> m r+{- | Acquire a 'IO.Handle' within 'MonadSafe'++ The file is opened in text mode. See also: 'withBinaryFile'+-}+withFile :: MonadSafe m => FilePath -> IO.IOMode -> (IO.Handle -> m r) -> m r withFile file ioMode = bracket (liftIO $ IO.openFile file ioMode) (liftIO . IO.hClose) {-# INLINABLE withFile #-} +{- | Like 'withFile', but open the file in binary mode++ See 'System.IO.hSetBinaryMode' for the differences between binary and text mode.+-}+withBinaryFile :: MonadSafe m => FilePath -> IO.IOMode -> (IO.Handle -> m r) -> m r+withBinaryFile file ioMode = bracket (liftIO $ IO.openBinaryFile file ioMode) (liftIO . IO.hClose)+{-# INLINABLE withBinaryFile #-}++{- | Acquire a 'IO.Handle' within 'MonadSafe'++ The 'ReleaseKey' can be used to close the handle with 'Pipes.Safe.release';+ otherwise the handle will be closed automatically at the conclusion of the+ 'MonadSafe' block.++ The file is opened in text mode. See also: 'openBinaryFile'+-}+openFile :: MonadSafe m => FilePath -> IO.IOMode -> m (ReleaseKey, IO.Handle)+openFile file ioMode = allocate (liftIO $ IO.openFile file ioMode) (liftIO . IO.hClose)+{-# INLINABLE openFile #-}++{- | Like 'openFile', but open the file in binary mode++ See 'System.IO.hSetBinaryMode' for the differences between binary and text mode.+-}+openBinaryFile :: MonadSafe m => FilePath -> IO.IOMode -> m (ReleaseKey, IO.Handle)+openBinaryFile file ioMode = allocate (liftIO $ IO.openBinaryFile file ioMode) (liftIO . IO.hClose)+{-# INLINABLE openBinaryFile #-}+ {- $strings Note that 'String's are very inefficient, and I will release future separate packages with 'Data.ByteString.ByteString' and 'Data.Text.Text' operations.@@ -44,3 +83,31 @@ writeFile :: MonadSafe m => FilePath -> Consumer' String m r writeFile file = withFile file IO.WriteMode $ \h -> P.toHandle h {-# INLINABLE writeFile #-}++{- | Acquire some resource with a guarantee that it will eventually be released++ The 'ReleaseKey' can be passed to 'Pipes.Safe.release' to+ release the resource manually. If this has not been done by the end+ of the 'MonadSafe' block, the resource will be released automatically.+-}+allocate :: MonadSafe m =>+ Base m a -- ^ Acquire+ -> (a -> Base m ()) -- ^ Release+ -> m (ReleaseKey, a)+allocate acq rel = mask_ $ do+ a <- liftBase acq+ key <- register (rel a)+ return (key, a)++{- | Like 'allocate', but for when the resource itself is not needed++ The acquire action runs immediately. The 'ReleaseKey' can be passed+ to 'Pipes.Safe.release' to run the release action. If this has not been+ done by the end of the 'MonadSafe' block, the release action will be+ run automatically.+-}+allocate_ :: MonadSafe m =>+ Base m a -- ^ Acquire+ -> (Base m ()) -- ^ Release+ -> m ReleaseKey+allocate_ acq rel = fmap fst (allocate acq (const rel))