conduit 1.0.10 → 1.0.10.1
raw patch · 5 files changed
+112/−18 lines, 5 files
Files
- Data/Conduit/Binary.hs +1/−0
- Data/Conduit/Internal.hs +31/−10
- Data/Conduit/List.hs +54/−6
- conduit.cabal +2/−1
- test/main.hs +24/−1
Data/Conduit/Binary.hs view
@@ -396,3 +396,4 @@ f (S.index bs i) loop (i + 1) | otherwise = return ()+{-# INLINE [1] mapM_ #-}
Data/Conduit/Internal.hs view
@@ -50,6 +50,7 @@ , sourceList , withUpstream , unwrapResumable+ , Data.Conduit.Internal.enumFromTo ) where import Control.Applicative (Applicative (..))@@ -555,21 +556,29 @@ -- -- Since 0.4.1 mapOutput :: Monad m => (o1 -> o2) -> Pipe l i o1 u m r -> Pipe l i o2 u m r-mapOutput f (HaveOutput p c o) = HaveOutput (mapOutput f p) c (f o)-mapOutput f (NeedInput p c) = NeedInput (mapOutput f . p) (mapOutput f . c)-mapOutput _ (Done r) = Done r-mapOutput f (PipeM mp) = PipeM (liftM (mapOutput f) mp)-mapOutput f (Leftover p i) = Leftover (mapOutput f p) i+mapOutput f =+ go+ where+ go (HaveOutput p c o) = HaveOutput (go p) c (f o)+ go (NeedInput p c) = NeedInput (go . p) (go . c)+ go (Done r) = Done r+ go (PipeM mp) = PipeM (liftM (go) mp)+ go (Leftover p i) = Leftover (go p) i+{-# INLINE mapOutput #-} -- | Same as 'mapOutput', but use a function that returns @Maybe@ values. -- -- Since 0.5.0 mapOutputMaybe :: Monad m => (o1 -> Maybe o2) -> Pipe l i o1 u m r -> Pipe l i o2 u m r-mapOutputMaybe f (HaveOutput p c o) = maybe id (\o' p' -> HaveOutput p' c o') (f o) (mapOutputMaybe f p)-mapOutputMaybe f (NeedInput p c) = NeedInput (mapOutputMaybe f . p) (mapOutputMaybe f . c)-mapOutputMaybe _ (Done r) = Done r-mapOutputMaybe f (PipeM mp) = PipeM (liftM (mapOutputMaybe f) mp)-mapOutputMaybe f (Leftover p i) = Leftover (mapOutputMaybe f p) i+mapOutputMaybe f =+ go+ where+ go (HaveOutput p c o) = maybe id (\o' p' -> HaveOutput p' c o') (f o) (mapOutputMaybe f p)+ go (NeedInput p c) = NeedInput (go . p) (go . c)+ go (Done r) = Done r+ go (PipeM mp) = PipeM (liftM (go) mp)+ go (Leftover p i) = Leftover (go p) i+{-# INLINE mapOutputMaybe #-} -- | Apply a function to all the input values of a @Pipe@. --@@ -584,6 +593,18 @@ mapInput _ _ (Done r) = Done r mapInput f f' (PipeM mp) = PipeM (liftM (mapInput f f') mp) mapInput f f' (Leftover p i) = maybe id (flip Leftover) (f' i) $ mapInput f f' p++enumFromTo :: (Enum o, Eq o, Monad m)+ => o+ -> o+ -> Pipe l i o u m ()+enumFromTo start stop =+ loop start+ where+ loop i+ | i == stop = HaveOutput (Done ()) (return ()) i+ | otherwise = HaveOutput (loop (succ i)) (return ()) i+{-# INLINE enumFromTo #-} -- | Convert a list into a source. --
Data/Conduit/List.hs view
@@ -70,6 +70,7 @@ import Data.Monoid (Monoid, mempty, mappend) import qualified Data.Foldable as F import Data.Conduit+import qualified Data.Conduit.Internal as CI import Control.Monad (when, (<=<), liftM) import Control.Monad.Trans.Class (lift) @@ -102,12 +103,8 @@ => a -> a -> Producer m a-enumFromTo start stop =- go start- where- go i- | i == stop = yield i- | otherwise = yield i >> go (succ i)+enumFromTo x = CI.ConduitM . CI.enumFromTo x+{-# INLINE enumFromTo #-} -- | Produces an infinite stream of repeated applications of f to x. iterate :: Monad m => (a -> a) -> a -> Producer m a@@ -180,6 +177,18 @@ -> Consumer a m () mapM_ f = awaitForever $ lift . f +srcMapM_ :: Monad m => Source m a -> (a -> m ()) -> m ()+srcMapM_ (CI.ConduitM src) f =+ go src+ where+ go (CI.Done ()) = return ()+ go (CI.PipeM mp) = mp >>= go+ go (CI.Leftover p ()) = go p+ go (CI.HaveOutput p _ o) = f o >> go p+ go (CI.NeedInput _ c) = go (c ())+{-# INLINE srcMapM_ #-}+{-# RULES "connect to mapM_" forall f src. src $$ mapM_ f = srcMapM_ src f #-}+ -- | Ignore a certain number of values in the stream. This function is -- semantically equivalent to: --@@ -234,7 +243,16 @@ -- Since 0.3.0 map :: Monad m => (a -> b) -> Conduit a m b map f = awaitForever $ yield . f+{-# INLINE [1] map #-} +-- Since a Source never has any leftovers, fusion rules on it are safe.+{-# RULES "source/map fusion $=" forall f src. src $= map f = mapFuseRight src f #-}+{-# RULES "source/map fusion =$=" forall f src. src =$= map f = mapFuseRight src f #-}++mapFuseRight :: Monad m => Source m a -> (a -> b) -> Source m b+mapFuseRight (CI.ConduitM src) f = CI.ConduitM (CI.mapOutput f src)+{-# INLINE mapFuseRight #-}+ {- It might be nice to include these rewrite rules, but they may have subtle@@ -423,12 +441,42 @@ filter :: Monad m => (a -> Bool) -> Conduit a m a filter f = awaitForever $ \i -> when (f i) (yield i) +filterFuseRight :: Monad m => Source m a -> (a -> Bool) -> Source m a+filterFuseRight (CI.ConduitM src) f =+ CI.ConduitM (go src)+ where+ go (CI.Done ()) = CI.Done ()+ go (CI.PipeM mp) = CI.PipeM (liftM go mp)+ go (CI.Leftover p i) = CI.Leftover (go p) i+ go (CI.HaveOutput p c o)+ | f o = CI.HaveOutput (go p) c o+ | otherwise = go p+ go (CI.NeedInput p c) = CI.NeedInput (go . p) (go . c)+-- Intermediate finalizers are dropped, but this is acceptable: the next+-- yielded value would be demanded by downstream in any event, and that new+-- finalizer will always override the existing finalizer.+{-# RULES "source/filter fusion $=" forall f src. src $= filter f = filterFuseRight src f #-}+{-# RULES "source/filter fusion =$=" forall f src. src =$= filter f = filterFuseRight src f #-}+{-# INLINE filterFuseRight #-}+ -- | Ignore the remainder of values in the source. Particularly useful when -- combined with 'isolate'. -- -- Since 0.3.0 sinkNull :: Monad m => Consumer a m () sinkNull = awaitForever $ \_ -> return ()+{-# RULES "connect to sinkNull" forall src. src $$ sinkNull = srcSinkNull src #-}++srcSinkNull :: Monad m => Source m a -> m ()+srcSinkNull (CI.ConduitM src) =+ go src+ where+ go (CI.Done ()) = return ()+ go (CI.PipeM mp) = mp >>= go+ go (CI.Leftover p ()) = go p+ go (CI.HaveOutput p _ _) = go p+ go (CI.NeedInput _ c) = go (c ())+{-# INLINE srcSinkNull #-} -- | A source that outputs no values. Note that this is just a type-restricted -- synonym for 'mempty'.
conduit.cabal view
@@ -1,5 +1,5 @@ Name: conduit-Version: 1.0.10+Version: 1.0.10.1 Synopsis: Streaming data processing library. Description: @conduit@ is a solution to the streaming data problem, allowing for production, transformation, and consumption of streams of data in constant memory. It is an alternative to lazy I\/O which guarantees deterministic resource handling, and fits in the same general solution space as @enumerator@\/@iteratee@ and @pipes@. For a tutorial, please visit <https://haskell.fpcomplete.com/user/snoyberg/library-documentation/conduit-overview>.@@ -48,6 +48,7 @@ Data.Conduit.Lazy Data.Conduit.Internal Data.Conduit.Util+ -- Hiding while some details are worked out Data.Conduit.Lift Build-depends: base >= 4.3 && < 5 , resourcet >= 0.4.3 && < 0.5 , lifted-base >= 0.1
test/main.hs view
@@ -5,6 +5,7 @@ import Test.QuickCheck.Monadic (assert, monadicIO, run) import qualified Data.Conduit as C+-- FIXME import qualified Data.Conduit.Lift as C import qualified Data.Conduit.Util as C import qualified Data.Conduit.Internal as CI import qualified Data.Conduit.List as CL@@ -29,7 +30,7 @@ import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Writer (execWriter, tell, runWriterT)-import Control.Monad.Trans.State (evalStateT, get, put)+import Control.Monad.Trans.State (evalStateT, get, put, modify) import Control.Applicative (pure, (<$>), (<*>)) import Data.Functor.Identity (Identity,runIdentity) import Control.Monad (forever)@@ -1075,6 +1076,28 @@ it "test1" $ verify test1L test1R "p1" "p2" "p3" -- FIXME this is broken it "test2" $ verify test2L test2R "p2" "p1" "p3" it "test3" $ verify test3L test3R "p2" "p3" "p1"++ {- FIXME+ describe "Data.Conduit.Lift" $ do+ it "execStateC" $ do+ let sink = C.execStateC 0 $ CL.mapM_ $ modify . (+)+ src = mapM_ C.yield [1..10 :: Int]+ res <- src C.$$ sink+ res `shouldBe` sum [1..10]++ it "execWriterT" $ do+ let sink = C.execWriterC $ CL.mapM_ $ tell . return+ src = mapM_ C.yield [1..10 :: Int]+ res <- src C.$$ sink+ res `shouldBe` [1..10]++ it "runErrorT" $ do+ let sink = C.runErrorC $ do+ x <- C.catchErrorC (lift $ throwError "foo") return+ return $ x ++ "bar"+ res <- return () C.$$ sink+ res `shouldBe` Right ("foobar" :: String)+ -} it' :: String -> IO () -> Spec it' = it