packages feed

streaming-bracketed 0.1.0.0 → 0.1.0.1

raw patch · 6 files changed

+101/−31 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

README.md view
@@ -46,10 +46,10 @@ [CHANGELOG](http://hackage.haskell.org/package/streaming-0.2.1.0/changelog) of the [streaming](http://hackage.haskell.org/package/streaming) package: -> Remove bracketStream, MonadCatch instance, and everything dealing with-> ResourceT. All of these things of sort of broken for Stream since there is no-> guarantee of linear consumption (functions like take can prevent finalizers-> from running).+    Remove bracketStream, MonadCatch instance, and everything dealing with+    ResourceT. All of these things of sort of broken for Stream since there is no+    guarantee of linear consumption (functions like take can prevent finalizers+    from running).  [One Github issue](https://github.com/haskell-streaming/streaming/issues/52). @@ -57,9 +57,9 @@  [Streaming libs exercise/challenge](https://twitter.com/DiazCarrete/status/1016073374458671104): -> Given a list [(Filepath,Int,Int)] of files and line ranges, create a stream-> of lines belonging to the concatenated ranges.+    Given a list [(Filepath,Int,Int)] of files and line ranges, create a stream+    of lines belonging to the concatenated ranges. -> Prompt release of file handles is required. resource-handling monads and-> "withXXX"-style functions are allowed.+    Prompt release of file handles is required. resource-handling monads and+    "withXXX"-style functions are allowed. 
library/Streaming/Bracketed.hs view
@@ -1,8 +1,8 @@ {-| A resource management decorator for `Stream`s. -    Resource-allocating 'Stream's are lifted to values of type `Bracketed` that-    can be combined as such, using an API that is more restricted than-    that of the original 'Stream's and ensures prompt deallocation of+    'Stream's requiring resource allocation are lifted to values of type+    `Bracketed`, which can be combined using an API that is more restricted+    than that of the original 'Stream's and ensures prompt deallocation of     resources.       Values of type `Bracketed` can later be run by supplying a@@ -24,19 +24,19 @@  -} module Streaming.Bracketed (-      -- * Bracketed+    -- * Bracketed       Bracketed-      -- * Lifting streams+    -- * Lifting streams     , clear     , bracketed-      -- * Consuming bracketed streams with continuations+     -- * Consuming bracketed streams with continuations     , with     , with_-      -- * Transforming bracketed streams+     -- * Transforming bracketed streams     , over     , over_     , for -      -- * Reading text files+     -- * Reading text files     , linesFromFile     , concatRanges     ) where@@ -56,3 +56,4 @@ >>> import qualified Streaming.Bracketed           as R  -}+
library/Streaming/Bracketed/Internal.hs view
@@ -12,6 +12,25 @@  import           System.IO +{- $setup++>>> import           Data.Foldable+>>> import           Control.Monad+>>> import           System.IO+>>> import           System.FilePath+>>> import           System.Directory+>>> import           Streaming+>>> import qualified Streaming.Prelude             as S+>>> import qualified Streaming.Bracketed           as R++-}++-- | A resource management decorator for the `Stream` type.+--   +--   @a@ is the type of yielded elements, @r@ the type of the final result.+--+--   It is not parameterized by a base monad because the underlying+--   `Stream`s are always over `IO`. newtype Bracketed a r =      Bracketed { runBracketed :: IORef Finstack -> Stream (Of a) IO r }      deriving Functor@@ -21,6 +40,7 @@     first f (Bracketed b) = Bracketed (S.map f . b)       second = fmap  +-- | `*>` performs sequential composition. instance Applicative (Bracketed a) where     pure = Bracketed . const . pure     Bracketed b <*> Bracketed b' = Bracketed (\finref ->@@ -41,11 +61,26 @@ --   Finalizers at the head of the list correspond to deeper levels of nesting. data Finstack = Finstack !Int [IO ()]   --- | Lift a `Stream` that doesn't perform allocation to a `Bracketed`.+{-| Lift a `Stream` that doesn't perform allocation to a `Bracketed`.+ +>>> R.with (R.clear (S.yield True)) S.toList+[True] :> ()+ +-} clear :: Stream (Of x) IO r -> Bracketed x r clear stream = Bracketed (const stream) --- | Lift a `Stream` that requires resource allocation to a `Bracketed`.+{-| Lift a `Stream` that performs resource allocation to a `Bracketed`.+ +    The first argument allocates the resource, the second is a function+    that deallocates it.+ +>>> R.with (R.bracketed (putStrLn "alloc") (\() -> putStrLn "dealloc") (\() -> S.yield True)) S.toList+alloc+dealloc+[True] :> ()++ -} bracketed :: IO a -> (a -> IO ()) -> (a -> Stream (Of x) IO r) -> Bracketed x r bracketed allocate finalize stream = Bracketed (\finref ->     let open = do @@ -58,30 +93,50 @@           liftIO (mask (\_ -> reset size0 finref))           pure r) --- | Consume a `Bracketed` stream, exhausting it.+{-| Consume a `Bracketed` stream, exhausting it.+    +>>> R.with (pure True) S.toList+[] :> True+     +-} with :: Bracketed a r -> (forall x. Stream (Of a) IO x -> IO (Of b x)) -> IO (Of b r) with (Bracketed b) f =      Control.Exception.bracket (newIORef (Finstack 0 []))                               (reset 0)                                (f . b) --- | Consume a `Bracketed` stream, possibly wihout exhausting it.---   ---   Finalizers lying in unconsumed parts of the stream will not be executed---   until the callback returns, so better not tarry too long if you want---   prompt finalization.+{-| Consume a `Bracketed` stream, possibly wihout exhausting it.+   +    Finalizers lying in unconsumed parts of the stream will not be executed+    until the callback returns, so better not tarry too long if you want+    prompt finalization.++>>> R.with_ (R.clear (S.each "abcd" *> pure True)) (S.toList . S.take 2)+"ab" :> ()++-} with_ :: Bracketed a r -> (Stream (Of a) IO r -> IO b) -> IO b with_ (Bracketed b) f =     Control.Exception.bracket (newIORef (Finstack 0 []))                               (reset 0)                                (f . b) --- | Apply to the underlying stream a transformation that preserves the return value.+{-| Apply to the underlying stream a transformation that preserves the return value, like 'S.map'.++>>> R.with (S.map succ `R.over` R.clear (S.each "abcd")) S.toList+"bcde" :> ()++-} over :: (forall x. Stream (Of a) IO x -> Stream (Of b) IO x) -> Bracketed a r -> Bracketed b r  over transform (Bracketed b) = Bracketed (transform . b) --- | Apply to the underlying stream a transformation that might not preserve---   the return value.+{-| Apply to the underlying stream a transformation that might not preserve+    the return value, like 'S.take'.++>>> R.with (S.take 2 `R.over_` R.clear (S.each "abdc")) S.toList+"ab" :> ()+     +-} over_ :: (Stream (Of a) IO r -> Stream (Of b) IO r') -> Bracketed a r -> Bracketed b r' over_ transform (Bracketed b) = Bracketed (\finref ->     let level = do
streaming-bracketed.cabal view
@@ -1,13 +1,13 @@ name:                streaming-bracketed-version:             0.1.0.0+version:             0.1.0.1 synopsis:            A resource management decorator for "streaming".         description:         This package provides a decorator for the Stream type from-                     the "streaming" package, that lets you perform bracket-like +                     "streaming", that lets you perform bracket-like                       operations that allocate and deallocate resources used                       by the stream.                      .                      By carefully managing the operations that are lifted to-                     the bracketed streams, we can ensure that finalizers are+                     the decorated streams, we can ensure that finalizers are                      promptly called even with operations like "take", which do                      not consume the whole stream. license:             MIT
tests/doctests.hs view
@@ -4,4 +4,4 @@  main :: IO () main = doctest-  ["-ilibrary","library/Streaming/Bracketed.hs"]+  ["-ilibrary","library/Streaming/Bracketed.hs","library/Streaming/Bracketed/Internal.hs"]
tests/tests.hs view
@@ -45,6 +45,7 @@   , testCase "for"          testFor   , testCase "forException" testForException   , testCase "forCleanupException" testForCleanupException+  , testCase "forCleanupException2" testForCleanupException2   , testCase "forTake"      testForTake   , testGroup     "file stuff"@@ -147,6 +148,19 @@        res <- reverse <$> readIORef ref        assertEqual "stream results" "xuijvy" res +testForCleanupException2 :: Assertion+testForCleanupException2 = +    do ref <- newIORef ""+       let b = R.bracketed (modifyIORef' ref ('x':)) +                         (\_ -> modifyIORef' ref ('y':))+                         (\_ -> S.each "ab") +           f _ = R.bracketed (modifyIORef' ref ('u':)) +                         (\_ -> fail "finoops")+                         (\_ -> S.each "ij") +       _ :: Either IOException (Of () ()) <- try (R.with (R.for b f) (\stream ->+           S.foldM (\() c -> modifyIORef' ref (c:)) (pure ()) pure stream))+       res <- reverse <$> readIORef ref+       assertEqual "stream results" "xuijy" res  testForTake :: Assertion testForTake =