packages feed

conduit 1.2.1 → 1.2.2

raw patch · 9 files changed

+1401/−339 lines, 9 filesdep +safePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: safe

API changes (from Hackage documentation)

- Data.Conduit.Internal: Emit :: s -> o -> Step s o r
- Data.Conduit.Internal: Skip :: s -> Step s o r
- Data.Conduit.Internal: Stop :: r -> Step s o r
- Data.Conduit.Internal: Stream :: (s -> m (Step s o r)) -> (m s) -> Stream m o r
- Data.Conduit.Internal: data Step s o r
- Data.Conduit.Internal: data Stream m o r
- Data.Conduit.Internal: data StreamConduit i o m r
- Data.Conduit.Internal: streamConduit :: ConduitM i o m r -> (Stream m i () -> Stream m o r) -> StreamConduit i o m r
- Data.Conduit.Internal: streamSource :: Monad m => Stream m o () -> StreamConduit i o m ()
- Data.Conduit.Internal: streamSourcePure :: Monad m => Stream Identity o () -> StreamConduit i o m ()
- Data.Conduit.Internal: unstream :: StreamConduit i o m r -> ConduitM i o m r
+ Data.Conduit.Internal.Fusion: Emit :: s -> o -> Step s o r
+ Data.Conduit.Internal.Fusion: Skip :: s -> Step s o r
+ Data.Conduit.Internal.Fusion: Stop :: r -> Step s o r
+ Data.Conduit.Internal.Fusion: Stream :: (s -> m (Step s o r)) -> (m s) -> Stream m o r
+ Data.Conduit.Internal.Fusion: data ConduitWithStream i o m r
+ Data.Conduit.Internal.Fusion: data Step s o r
+ Data.Conduit.Internal.Fusion: data Stream m o r
+ Data.Conduit.Internal.Fusion: instance Functor (Step s o)
+ Data.Conduit.Internal.Fusion: streamConduit :: ConduitM i o m r -> (Stream m i () -> Stream m o r) -> ConduitWithStream i o m r
+ Data.Conduit.Internal.Fusion: streamSource :: Monad m => Stream m o () -> ConduitWithStream i o m ()
+ Data.Conduit.Internal.Fusion: streamSourcePure :: Monad m => Stream Identity o () -> ConduitWithStream i o m ()
+ Data.Conduit.Internal.Fusion: type StreamConduit i m o = StreamConduitM i o m ()
+ Data.Conduit.Internal.Fusion: type StreamConduitM i o m r = Stream m i () -> Stream m o r
+ Data.Conduit.Internal.Fusion: type StreamConsumer i m r = forall o. StreamConduitM i o m r
+ Data.Conduit.Internal.Fusion: type StreamProducer m o = forall i. StreamConduitM i o m ()
+ Data.Conduit.Internal.Fusion: type StreamSink i m r = StreamConduitM i Void m r
+ Data.Conduit.Internal.Fusion: type StreamSource m o = StreamConduitM () o m ()
+ Data.Conduit.Internal.Fusion: unstream :: ConduitWithStream i o m r -> ConduitM i o m r
+ Data.Conduit.Internal.List.Stream: GBDone :: GroupByState a b s
+ Data.Conduit.Internal.List.Stream: GBLoop :: ([a] -> [a]) -> a -> b -> s -> GroupByState a b s
+ Data.Conduit.Internal.List.Stream: GBStart :: s -> GroupByState a b s
+ Data.Conduit.Internal.List.Stream: catMaybesS :: Monad m => StreamConduit (Maybe a) m a
+ Data.Conduit.Internal.List.Stream: concatMapAccumMS :: Monad m => (a -> accum -> m (accum, [b])) -> accum -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: concatMapAccumS :: Monad m => (a -> accum -> (accum, [b])) -> accum -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: concatMapMS :: Monad m => (a -> m [b]) -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: concatMapS :: Monad m => (a -> [b]) -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: concatS :: (Monad m, Foldable f) => StreamConduit (f a) m a
+ Data.Conduit.Internal.List.Stream: consumeS :: Monad m => StreamConsumer a m [a]
+ Data.Conduit.Internal.List.Stream: data GroupByState a b s
+ Data.Conduit.Internal.List.Stream: dropS :: Monad m => Int -> StreamConsumer a m ()
+ Data.Conduit.Internal.List.Stream: enumFromToS :: (Enum a, Ord a, Monad m) => a -> a -> StreamProducer m a
+ Data.Conduit.Internal.List.Stream: enumFromToS_int :: (Integral a, Monad m) => a -> a -> StreamProducer m a
+ Data.Conduit.Internal.List.Stream: filterS :: Monad m => (a -> Bool) -> StreamConduit a m a
+ Data.Conduit.Internal.List.Stream: foldMS :: Monad m => (b -> a -> m b) -> b -> StreamConsumer a m b
+ Data.Conduit.Internal.List.Stream: foldS :: Monad m => (b -> a -> b) -> b -> StreamConsumer a m b
+ Data.Conduit.Internal.List.Stream: groupBy1S :: Monad m => (a -> b) -> (b -> b -> Bool) -> StreamConduit a m (a, [a])
+ Data.Conduit.Internal.List.Stream: groupByS :: Monad m => (a -> a -> Bool) -> StreamConduit a m [a]
+ Data.Conduit.Internal.List.Stream: groupOn1S :: (Monad m, Eq b) => (a -> b) -> StreamConduit a m (a, [a])
+ Data.Conduit.Internal.List.Stream: headS :: Monad m => StreamConsumer a m (Maybe a)
+ Data.Conduit.Internal.List.Stream: isolateS :: Monad m => Int -> StreamConduit a m a
+ Data.Conduit.Internal.List.Stream: iterMS :: Monad m => (a -> m ()) -> StreamConduit a m a
+ Data.Conduit.Internal.List.Stream: iterateS :: Monad m => (a -> a) -> a -> StreamProducer m a
+ Data.Conduit.Internal.List.Stream: mapAccumMS :: Monad m => (a -> s -> m (s, b)) -> s -> StreamConduitM a b m s
+ Data.Conduit.Internal.List.Stream: mapAccumS :: Monad m => (a -> s -> (s, b)) -> s -> StreamConduitM a b m s
+ Data.Conduit.Internal.List.Stream: mapFoldableMS :: (Monad m, Foldable f) => (a -> m (f b)) -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: mapFoldableS :: (Monad m, Foldable f) => (a -> f b) -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: mapMS :: Monad m => (a -> m b) -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: mapM_S :: Monad m => (a -> m ()) -> StreamConsumer a m ()
+ Data.Conduit.Internal.List.Stream: mapMaybeMS :: Monad m => (a -> m (Maybe b)) -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: mapMaybeS :: Monad m => (a -> Maybe b) -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: mapS :: Monad m => (a -> b) -> StreamConduit a m b
+ Data.Conduit.Internal.List.Stream: replicateMS :: Monad m => Int -> m a -> StreamProducer m a
+ Data.Conduit.Internal.List.Stream: replicateS :: Monad m => Int -> a -> StreamProducer m a
+ Data.Conduit.Internal.List.Stream: sinkNullS :: Monad m => StreamConsumer a m ()
+ Data.Conduit.Internal.List.Stream: sourceListS :: Monad m => [a] -> StreamProducer m a
+ Data.Conduit.Internal.List.Stream: sourceNullS :: Monad m => StreamProducer m a
+ Data.Conduit.Internal.List.Stream: takeS :: Monad m => Int -> StreamConsumer a m [a]
+ Data.Conduit.Internal.List.Stream: unfoldMS :: Monad m => (b -> m (Maybe (a, b))) -> b -> StreamProducer m a
+ Data.Conduit.Internal.List.Stream: unfoldS :: Monad m => (b -> Maybe (a, b)) -> b -> StreamProducer m a

Files

Data/Conduit/Internal/Conduit.hs view
@@ -735,7 +735,7 @@ ($=) :: Monad m => Conduit a m b -> ConduitM b c m r -> ConduitM a c m r ($=) = (=$=) {-# INLINE [0] ($=) #-}-{-# RULES "$= is =$=" ($=) = (=$=) #-}+{-# RULES "conduit: $= is =$=" ($=) = (=$=) #-}  -- | Right fuse, combining a conduit and a sink together into a new sink. --@@ -751,7 +751,7 @@ (=$) :: Monad m => Conduit a m b -> ConduitM b c m r -> ConduitM a c m r (=$) = (=$=) {-# INLINE [0] (=$) #-}-{-# RULES "=$ is =$=" (=$) = (=$=) #-}+{-# RULES "conduit: =$ is =$=" (=$) = (=$=) #-}  -- | Fusion operator, combining two @Conduit@s together into a new @Conduit@. --@@ -801,7 +801,7 @@     (\i -> unConduitM (g i) rest)     (const $ unConduitM f rest) {-# INLINE await' #-}-{-# RULES "await >>= maybe" forall x y. await >>= maybe x y = await' x y #-}+{-# RULES "conduit: await >>= maybe" forall x y. await >>= maybe x y = await' x y #-}  -- | Send a value downstream to the next component to consume. If the -- downstream component terminates, this call will never return control. If you@@ -1179,14 +1179,14 @@ -- Rewrite rules  {- FIXME-{-# RULES "ConduitM: lift x >>= f" forall m f. lift m >>= f = ConduitM (PipeM (liftM (unConduitM . f) m)) #-}-{-# RULES "ConduitM: lift x >> f" forall m f. lift m >> f = ConduitM (PipeM (liftM (\_ -> unConduitM f) m)) #-}+{-# RULES "conduit: ConduitM: lift x >>= f" forall m f. lift m >>= f = ConduitM (PipeM (liftM (unConduitM . f) m)) #-}+{-# RULES "conduit: ConduitM: lift x >> f" forall m f. lift m >> f = ConduitM (PipeM (liftM (\_ -> unConduitM f) m)) #-} -{-# RULES "ConduitM: liftIO x >>= f" forall m (f :: MonadIO m => a -> ConduitM i o m r). liftIO m >>= f = ConduitM (PipeM (liftM (unConduitM . f) (liftIO m))) #-}-{-# RULES "ConduitM: liftIO x >> f" forall m (f :: MonadIO m => ConduitM i o m r). liftIO m >> f = ConduitM (PipeM (liftM (\_ -> unConduitM f) (liftIO m))) #-}+{-# RULES "conduit: ConduitM: liftIO x >>= f" forall m (f :: MonadIO m => a -> ConduitM i o m r). liftIO m >>= f = ConduitM (PipeM (liftM (unConduitM . f) (liftIO m))) #-}+{-# RULES "conduit: ConduitM: liftIO x >> f" forall m (f :: MonadIO m => ConduitM i o m r). liftIO m >> f = ConduitM (PipeM (liftM (\_ -> unConduitM f) (liftIO m))) #-} -{-# RULES "ConduitM: liftBase x >>= f" forall m (f :: MonadBase b m => a -> ConduitM i o m r). liftBase m >>= f = ConduitM (PipeM (liftM (unConduitM . f) (liftBase m))) #-}-{-# RULES "ConduitM: liftBase x >> f" forall m (f :: MonadBase b m => ConduitM i o m r). liftBase m >> f = ConduitM (PipeM (liftM (\_ -> unConduitM f) (liftBase m))) #-}+{-# RULES "conduit: ConduitM: liftBase x >>= f" forall m (f :: MonadBase b m => a -> ConduitM i o m r). liftBase m >>= f = ConduitM (PipeM (liftM (unConduitM . f) (liftBase m))) #-}+{-# RULES "conduit: ConduitM: liftBase x >> f" forall m (f :: MonadBase b m => ConduitM i o m r). liftBase m >> f = ConduitM (PipeM (liftM (\_ -> unConduitM f) (liftBase m))) #-}  {-# RULES     "yield o >> p" forall o (p :: ConduitM i o m r). yield o >> p = ConduitM (HaveOutput (unConduitM p) (return ()) o)@@ -1198,6 +1198,6 @@         if b then p else ConduitM (HaveOutput (unConduitM p) (return ()) o)   ; "lift m >>= yield" forall m. lift m >>= yield = yieldM m    #-}-{-# RULES "leftover l >> p" forall l (p :: ConduitM i o m r). leftover l >> p =+{-# RULES "conduit: leftover l >> p" forall l (p :: ConduitM i o m r). leftover l >> p =     ConduitM (Leftover (unConduitM p) l) #-}     -}
Data/Conduit/Internal/Fusion.hs view
@@ -1,11 +1,18 @@ {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveFunctor #-} module Data.Conduit.Internal.Fusion     ( -- ** Types       Step (..)     , Stream (..)+    , ConduitWithStream+    , StreamConduitM     , StreamConduit+    , StreamSource+    , StreamProducer+    , StreamSink+    , StreamConsumer       -- ** Functions     , streamConduit     , streamSource@@ -16,9 +23,6 @@ import Data.Conduit.Internal.Conduit import Data.Conduit.Internal.Pipe (Pipe (..)) import Data.Functor.Identity (Identity (runIdentity))-import Control.Monad.Trans.Identity (IdentityT, runIdentityT)-import Control.Monad.Trans.Class (MonadTrans, lift)-import Control.Monad (liftM) import Data.Void (Void, absurd)  -- | This is the same as stream fusion\'s Step. Constructors are renamed to@@ -27,34 +31,47 @@     = Emit s o     | Skip s     | Stop r+    deriving Functor  data Stream m o r = forall s. Stream     (s -> m (Step s o r))     (m s) -data StreamConduit i o m r = StreamConduit+data ConduitWithStream i o m r = ConduitWithStream     (ConduitM i o m r)-    (Stream m i () -> Stream m o r)+    (StreamConduitM i o m r) -unstream :: StreamConduit i o m r -> ConduitM i o m r-unstream (StreamConduit c _) = c+type StreamConduitM i o m r = Stream m i () -> Stream m o r++type StreamConduit i m o = StreamConduitM i o m ()++type StreamSource m o = StreamConduitM () o m ()++type StreamProducer m o = forall i. StreamConduitM i o m ()++type StreamSink i m r = StreamConduitM i Void m r++type StreamConsumer i m r = forall o. StreamConduitM i o m r++unstream :: ConduitWithStream i o m r -> ConduitM i o m r+unstream (ConduitWithStream c _) = c {-# INLINE [0] unstream #-}  fuseStream :: Monad m-           => StreamConduit a b m ()-           -> StreamConduit b c m r-           -> StreamConduit a c m r-fuseStream (StreamConduit a x) (StreamConduit b y) = StreamConduit (a =$= b) (y . x)+           => ConduitWithStream a b m ()+           -> ConduitWithStream b c m r+           -> ConduitWithStream a c m r+fuseStream (ConduitWithStream a x) (ConduitWithStream b y) = ConduitWithStream (a =$= b) (y . x) {-# INLINE fuseStream #-} -{-# RULES "fuseStream" forall left right.+{-# RULES "conduit: fuseStream" forall left right.         unstream left =$= unstream right = unstream (fuseStream left right)   #-}  runStream :: Monad m-          => StreamConduit () Void m r+          => ConduitWithStream () Void m r           -> m r-runStream (StreamConduit _ f) =+runStream (ConduitWithStream _ f) =     run $ f $ Stream emptyStep (return ())   where     emptyStep _ = return $ Stop ()@@ -69,15 +86,15 @@                 Emit _ o -> absurd o {-# INLINE runStream #-} -{-# RULES "runStream" forall stream.+{-# RULES "conduit: runStream" forall stream.         runConduit (unstream stream) = runStream stream   #-}  connectStream :: Monad m-              => StreamConduit () i    m ()-              -> StreamConduit i  Void m r+              => ConduitWithStream () i    m ()+              -> ConduitWithStream i  Void m r               -> m r-connectStream (StreamConduit _ stream) (StreamConduit _ f) =+connectStream (ConduitWithStream _ stream) (ConduitWithStream _ f) =     run $ f $ stream $ Stream emptyStep (return ())   where     emptyStep _ = return $ Stop ()@@ -92,15 +109,15 @@                 Emit _ o -> absurd o {-# INLINE connectStream #-} -{-# RULES "connectStream" forall left right.+{-# RULES "conduit: connectStream" forall left right.         unstream left $$ unstream right = connectStream left right   #-}  connectStream1 :: Monad m-               => StreamConduit () i    m ()-               -> ConduitM      i  Void m r+               => ConduitWithStream () i    m ()+               -> ConduitM          i  Void m r                -> m r-connectStream1 (StreamConduit _ fstream) (ConduitM sink0) =+connectStream1 (ConduitWithStream _ fstream) (ConduitM sink0) =     case fstream $ Stream (const $ return $ Stop ()) (return ()) of         Stream step ms0 ->             let loop _ (Done r) _ = return r@@ -117,7 +134,7 @@              in ms0 >>= loop [] (sink0 Done) {-# INLINE connectStream1 #-} -{-# RULES "connectStream1" forall left right.+{-# RULES "conduit: connectStream1" forall left right.         unstream left $$ right = connectStream1 left right   #-} @@ -129,9 +146,9 @@  connectStream2 :: Monad m                => ConduitM      () i    m ()-               -> StreamConduit i  Void m r+               -> ConduitWithStream i  Void m r                -> m r-connectStream2 (ConduitM src0) (StreamConduit _ fstream) =+connectStream2 (ConduitM src0) (ConduitWithStream _ fstream) =     run $ fstream $ Stream step' $ return (return (), src0 Done)   where     step' (_, Done ()) = return $ Stop ()@@ -148,23 +165,23 @@                 Skip s' -> loop s' {-# INLINE connectStream2 #-} -{-# RULES "connectStream2" forall left right.+{-# RULES "conduit: connectStream2" forall left right.         left $$ unstream right = connectStream2 left right   #-} -}  streamConduit :: ConduitM i o m r               -> (Stream m i () -> Stream m o r)-              -> StreamConduit i o m r-streamConduit = StreamConduit+              -> ConduitWithStream i o m r+streamConduit = ConduitWithStream {-# INLINE CONLIKE streamConduit #-}  streamSource     :: Monad m     => Stream m o ()-    -> StreamConduit i o m ()+    -> ConduitWithStream i o m () streamSource str@(Stream step ms0) =-    StreamConduit con (const str)+    ConduitWithStream con (const str)   where     con = ConduitM $ \rest -> PipeM $ do         s0 <- ms0@@ -180,9 +197,9 @@ streamSourcePure     :: Monad m     => Stream Identity o ()-    -> StreamConduit i o m ()+    -> ConduitWithStream i o m () streamSourcePure (Stream step ms0) =-    StreamConduit con (const $ Stream (return . runIdentity . step) (return s0))+    ConduitWithStream con (const $ Stream (return . runIdentity . step) (return s0))   where     s0 = runIdentity ms0     con = ConduitM $ \rest ->
+ Data/Conduit/Internal/List/Stream.hs view
@@ -0,0 +1,475 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE RankNTypes #-}+module Data.Conduit.Internal.List.Stream where++import           Control.Monad (liftM)+import           Data.Conduit.Internal.Fusion+import qualified Data.Foldable as F++--FIXME: Should streamSource / streamSourcePure be used for sources?++unfoldS :: Monad m+        => (b -> Maybe (a, b))+        -> b+        -> StreamProducer m a+unfoldS f s0 _ =+    Stream step (return s0)+  where+    step s = return $+        case f s of+            Nothing -> Stop ()+            Just (x, s') -> Emit s' x+{-# INLINE unfoldS #-}++unfoldMS :: Monad m+         => (b -> m (Maybe (a, b)))+         -> b+         -> StreamProducer m a+unfoldMS f s0 _ =+    Stream step (return s0)+  where+    step s = do+        ms' <- f s+        return $ case ms' of+            Nothing -> Stop ()+            Just (x, s') -> Emit s' x+{-# INLINE unfoldMS #-}++sourceListS :: Monad m => [a] -> StreamProducer m a+sourceListS xs0 _ =+    Stream (return . step) (return xs0)+  where+    step [] = Stop ()+    step (x:xs) = Emit xs x+{-# INLINE sourceListS #-}++enumFromToS :: (Enum a, Prelude.Ord a, Monad m)+            => a+            -> a+            -> StreamProducer m a+enumFromToS x0 y _ =+    Stream step (return x0)+  where+    step x = return $ if x Prelude.> y+        then Stop ()+        else Emit (Prelude.succ x) x+{-# INLINE [0] enumFromToS #-}++enumFromToS_int :: (Prelude.Integral a, Monad m)+                => a+                -> a+                -> StreamProducer m a+enumFromToS_int x0 y _ = x0 `seq` y `seq` Stream step (return x0)+  where+    step x | x <= y    = return $ Emit (x Prelude.+ 1) x+           | otherwise = return $ Stop ()+{-# INLINE enumFromToS_int #-}++{-# RULES "conduit: enumFromTo<Int>" forall f t.+      enumFromToS f t = enumFromToS_int f t :: Monad m => StreamProducer m Int+  #-}++iterateS :: Monad m => (a -> a) -> a -> StreamProducer m a+iterateS f x0 _ =+    Stream (return . step) (return x0)+  where+    step x = Emit x' x+      where+        x' = f x+{-# INLINE iterateS #-}++replicateS :: Monad m => Int -> a -> StreamProducer m a+replicateS cnt0 a _ =+    Stream step (return cnt0)+  where+    step cnt+        | cnt <= 0  = return $ Stop ()+        | otherwise = return $ Emit (cnt - 1) a+{-# INLINE replicateS #-}++replicateMS :: Monad m => Int -> m a -> StreamProducer m a+replicateMS cnt0 ma _ =+    Stream step (return cnt0)+  where+    step cnt+        | cnt <= 0  = return $ Stop ()+        | otherwise = Emit (cnt - 1) `liftM` ma+{-# INLINE replicateMS #-}++foldS :: Monad m => (b -> a -> b) -> b -> StreamConsumer a m b+foldS f b0 (Stream step ms0) =+    Stream step' (liftM (b0, ) ms0)+  where+    step' (!b, s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop b+            Skip s' -> Skip (b, s')+            Emit s' a -> Skip (f b a, s')+{-# INLINE foldS #-}++foldMS :: Monad m => (b -> a -> m b) -> b -> StreamConsumer a m b+foldMS f b0 (Stream step ms0) =+    Stream step' (liftM (b0, ) ms0)+  where+    step' (!b, s) = do+        res <- step s+        case res of+            Stop () -> return $ Stop b+            Skip s' -> return $ Skip (b, s')+            Emit s' a -> do+                b' <- f b a+                return $ Skip (b', s')+{-# INLINE foldMS #-}++mapM_S :: Monad m+       => (a -> m ())+       -> StreamConsumer a m ()+mapM_S f (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        case res of+          Stop () -> return $ Stop ()+          Skip s' -> return $ Skip s'+          Emit s' x -> f x >> return (Skip s')+{-# INLINE [1] mapM_S #-}++dropS :: Monad m+      => Int+      -> StreamConsumer a m ()+dropS n0 (Stream step ms0) =+    Stream step' (liftM (, n0) ms0)+  where+    step' (_, n) | n <= 0 = return $ Stop ()+    step' (s, n) = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip (s', n)+            Emit s' _ -> Skip (s', n - 1)+{-# INLINE dropS #-}++takeS :: Monad m+      => Int+      -> StreamConsumer a m [a]+takeS n0 (Stream step s0) =+    Stream step' (liftM (id, n0,) s0)+  where+    step' (output, n, _) | n <= 0 = return $ Stop (output [])+    step' (output, n, s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop (output [])+            Skip s' -> Skip (output, n, s')+            Emit s' x -> Skip (output . (x:), n - 1, s')+{-# INLINE takeS #-}++headS :: Monad m => StreamConsumer a m (Maybe a)+headS (Stream step s0) =+    Stream step' s0+  where+    step' s = do+        res <- step s+        return $ case res of+            Stop () -> Stop Nothing+            Skip s' -> Skip s'+            Emit _ x -> Stop (Just x)+{-# INLINE headS #-}++mapS :: Monad m => (a -> b) -> StreamConduit a m b+mapS f (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        return $ case res of+            Stop r -> Stop r+            Emit s' a -> Emit s' (f a)+            Skip s' -> Skip s'+{-# INLINE mapS #-}++mapMS :: Monad m => (a -> m b) -> StreamConduit a m b+mapMS f (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        case res of+            Stop r -> return $ Stop r+            Emit s' a -> Emit s' `liftM` f a+            Skip s' -> return $ Skip s'+{-# INLINE mapMS #-}++iterMS :: Monad m => (a -> m ()) -> StreamConduit a m a+iterMS f (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        case res of+            Stop () -> return $ Stop ()+            Skip s' -> return $ Skip s'+            Emit s' x -> f x >> return (Emit s' x)+{-# INLINE iterMS #-}++mapMaybeS :: Monad m => (a -> Maybe b) -> StreamConduit a m b+mapMaybeS f (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip s'+            Emit s' x ->+                case f x of+                    Just y -> Emit s' y+                    Nothing -> Skip s'+{-# INLINE mapMaybeS #-}++mapMaybeMS :: Monad m => (a -> m (Maybe b)) -> StreamConduit a m b+mapMaybeMS f (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        case res of+            Stop () -> return $ Stop ()+            Skip s' -> return $ Skip s'+            Emit s' x -> do+                my <- f x+                case my of+                    Just y -> return $ Emit s' y+                    Nothing -> return $ Skip s'+{-# INLINE mapMaybeMS #-}++catMaybesS :: Monad m => StreamConduit (Maybe a) m a+catMaybesS (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip s'+            Emit s' Nothing -> Skip s'+            Emit s' (Just x) -> Emit s' x+{-# INLINE catMaybesS #-}++concatS :: (Monad m, F.Foldable f) => StreamConduit (f a) m a+concatS (Stream step ms0) =+    Stream step' (liftM ([], ) ms0)+  where+    step' ([], s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip ([], s')+            Emit s' x -> Skip (F.toList x, s')+    step' ((x:xs), s) = return (Emit (xs, s) x)+{-# INLINE concatS #-}++concatMapS :: Monad m => (a -> [b]) -> StreamConduit a m b+concatMapS f (Stream step ms0) =+    Stream step' (liftM ([], ) ms0)+  where+    step' ([], s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip ([], s')+            Emit s' x -> Skip (f x, s')+    step' ((x:xs), s) = return (Emit (xs, s) x)+{-# INLINE concatMapS #-}++concatMapMS :: Monad m => (a -> m [b]) -> StreamConduit a m b+concatMapMS f (Stream step ms0) =+    Stream step' (liftM ([], ) ms0)+  where+    step' ([], s) = do+        res <- step s+        case res of+            Stop () -> return $ Stop ()+            Skip s' -> return $ Skip ([], s')+            Emit s' x -> do+                xs <- f x+                return $ Skip (xs, s')+    step' ((x:xs), s) = return (Emit (xs, s) x)+{-# INLINE concatMapMS #-}++concatMapAccumS :: Monad m => (a -> accum -> (accum, [b])) -> accum -> StreamConduit a m b+concatMapAccumS f  initial (Stream step ms0) =+    Stream step' (liftM (initial, [], ) ms0)+  where+    step' (accum, [], s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip (accum, [], s')+            Emit s' x ->+                let (accum', xs) = f x accum+                in Skip (accum', xs, s')+    step' (accum, (x:xs), s) = return (Emit (accum, xs, s) x)+{-# INLINE concatMapAccumS #-}++mapAccumS :: Monad m => (a -> s -> (s, b)) -> s -> StreamConduitM a b m s+mapAccumS f initial (Stream step ms0) =+    Stream step' (liftM (initial, ) ms0)+  where+    step' (accum, s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop accum+            Skip s' -> Skip (accum, s')+            Emit s' x ->+                let (accum', r) = f x accum+                in Emit (accum', s') r+{-# INLINE mapAccumS #-}++mapAccumMS :: Monad m => (a -> s -> m (s, b)) -> s -> StreamConduitM a b m s+mapAccumMS f initial (Stream step ms0) =+    Stream step' (liftM (initial, ) ms0)+  where+    step' (accum, s) = do+        res <- step s+        case res of+            Stop () -> return $ Stop accum+            Skip s' -> return $ Skip (accum, s')+            Emit s' x -> do+                (accum', r) <- f x accum+                return $ Emit (accum', s') r+{-# INLINE mapAccumMS #-}++concatMapAccumMS :: Monad m => (a -> accum -> m (accum, [b])) -> accum -> StreamConduit a m b+concatMapAccumMS f  initial (Stream step ms0) =+    Stream step' (liftM (initial, [], ) ms0)+  where+    step' (accum, [], s) = do+        res <- step s+        case res of+            Stop () -> return $ Stop ()+            Skip s' -> return $ Skip (accum, [], s')+            Emit s' x -> do+                (accum', xs) <- f x accum+                return $ Skip (accum', xs, s')+    step' (accum, (x:xs), s) = return (Emit (accum, xs, s) x)+{-# INLINE concatMapAccumMS #-}++mapFoldableS :: (Monad m, F.Foldable f) => (a -> f b) -> StreamConduit a m b+mapFoldableS f (Stream step ms0) =+    Stream step' (liftM ([], ) ms0)+  where+    step' ([], s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip ([], s')+            Emit s' x -> Skip (F.toList (f x), s')+    step' ((x:xs), s) = return (Emit (xs, s) x)+{-# INLINE mapFoldableS #-}++mapFoldableMS :: (Monad m, F.Foldable f) => (a -> m (f b)) -> StreamConduit a m b+mapFoldableMS f (Stream step ms0) =+    Stream step' (liftM ([], ) ms0)+  where+    step' ([], s) = do+        res <- step s+        case res of+            Stop () -> return $ Stop ()+            Skip s' -> return $ Skip ([], s')+            Emit s' x -> do+                y <- f x+                return $ Skip (F.toList y, s')+    step' ((x:xs), s) = return (Emit (xs, s) x)+{-# INLINE mapFoldableMS #-}++consumeS :: Monad m => StreamConsumer a m [a]+consumeS (Stream step ms0) =+    Stream step' (liftM (id,) ms0)+  where+    step' (front, s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop (front [])+            Skip s' -> Skip (front, s')+            Emit s' a -> Skip (front . (a:), s')+{-# INLINE consumeS #-}++groupByS :: Monad m => (a -> a -> Bool) -> StreamConduit a m [a]+groupByS f = mapS (Prelude.uncurry (:)) . groupBy1S id f+{-# INLINE groupByS #-}++groupOn1S :: (Monad m, Eq b) => (a -> b) -> StreamConduit a m (a, [a])+groupOn1S f = groupBy1S f (==)+{-# INLINE groupOn1S #-}++data GroupByState a b s+     = GBStart s+     | GBLoop ([a] -> [a]) a b s+     | GBDone++groupBy1S :: Monad m => (a -> b) -> (b -> b -> Bool) -> StreamConduit a m (a, [a])+groupBy1S f eq (Stream step ms0) =+    Stream step' (liftM GBStart ms0)+  where+    step' (GBStart s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip (GBStart s')+            Emit s' x0 -> Skip (GBLoop id x0 (f x0) s')+    step' (GBLoop rest x0 fx0 s) = do+        res <- step s+        return $ case res of+            Stop () -> Emit GBDone (x0, rest [])+            Skip s' -> Skip (GBLoop rest x0 fx0 s')+            Emit s' x+                | fx0 `eq` f x -> Skip (GBLoop (rest . (x:)) x0 fx0 s')+                | otherwise -> Emit (GBLoop id x (f x) s') (x0, rest [])+    step' GBDone = return $ Stop ()+{-# INLINE groupBy1S #-}++isolateS :: Monad m => Int -> StreamConduit a m a+isolateS count (Stream step ms0) =+    Stream step' (liftM (count,) ms0)+  where+    step' (n, _) | n <= 0 = return $ Stop ()+    step' (n, s) = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip (n, s')+            Emit s' x -> Emit (n - 1, s') x+{-# INLINE isolateS #-}++filterS :: Monad m => (a -> Bool) -> StreamConduit a m a+filterS f (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip s'+            Emit s' x+                | f x -> Emit s' x+                | otherwise -> Skip s'++sinkNullS :: Monad m => StreamConsumer a m ()+sinkNullS (Stream step ms0) =+    Stream step' ms0+  where+    step' s = do+        res <- step s+        return $ case res of+            Stop () -> Stop ()+            Skip s' -> Skip s'+            Emit s' _ -> Skip s'+{-# INLINE sinkNullS #-}++sourceNullS :: Monad m => StreamProducer m a+sourceNullS _ = Stream (\_ -> return (Stop ())) (return ())+{-# INLINE sourceNullS #-}
Data/Conduit/Internal/Pipe.hs view
@@ -220,7 +220,7 @@ -- Since 0.5.0 await :: Pipe l i o u m (Maybe i) await = NeedInput (Done . Just) (\_ -> Done Nothing)-{-# RULES "CI.await >>= maybe" forall x y. await >>= maybe x y = NeedInput y (const x) #-}+{-# RULES "conduit: CI.await >>= maybe" forall x y. await >>= maybe x y = NeedInput y (const x) #-} {-# INLINE [1] await #-}  -- | This is similar to @await@, but will return the upstream result value as@@ -229,7 +229,7 @@ -- Since 0.5.0 awaitE :: Pipe l i o u m (Either u i) awaitE = NeedInput (Done . Right) (Done . Left)-{-# RULES "awaitE >>= either" forall x y. awaitE >>= either x y = NeedInput y x #-}+{-# RULES "conduit: awaitE >>= either" forall x y. awaitE >>= either x y = NeedInput y x #-} {-# INLINE [1] awaitE #-}  -- | Wait for input forever, calling the given inner @Pipe@ for each piece of@@ -286,7 +286,7 @@ leftover :: l -> Pipe l i o u m () leftover = Leftover (Done ()) {-# INLINE [1] leftover #-}-{-# RULES "leftover l >> p" forall l (p :: Pipe l i o u m r). leftover l >> p = Leftover p l #-}+{-# RULES "conduit: leftover l >> p" forall l (p :: Pipe l i o u m r). leftover l >> p = Leftover p l #-}  -- | Perform some allocation and run an inner @Pipe@. Two guarantees are given -- about resource finalization:@@ -628,5 +628,5 @@     go (Leftover p l) = Leftover (go p) l {-# INLINE generalizeUpstream #-} -{-# RULES "Pipe: lift x >>= f" forall m f. lift m >>= f = PipeM (liftM f m) #-}-{-# RULES "Pipe: lift x >> f" forall m f. lift m >> f = PipeM (liftM (\_ -> f) m) #-}+{-# RULES "conduit: Pipe: lift x >>= f" forall m f. lift m >>= f = PipeM (liftM f m) #-}+{-# RULES "conduit: Pipe: lift x >> f" forall m f. lift m >> f = PipeM (liftM (\_ -> f) m) #-}
Data/Conduit/List.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE TupleSections #-}+{-# LANGUAGE CPP #-} -- | Higher-level functions to interact with the elements of a stream. Most of -- these are based on list functions. --@@ -80,34 +80,44 @@ import Data.Monoid (Monoid, mempty, mappend) import qualified Data.Foldable as F import Data.Conduit-import qualified Data.Conduit.Internal as CI import Data.Conduit.Internal.Fusion+import Data.Conduit.Internal.List.Stream+import qualified Data.Conduit.Internal as CI import Control.Monad (when, (<=<), liftM, void) import Control.Monad.Trans.Class (lift) +-- Defines INLINE_RULE0, INLINE_RULE, STREAMING0, and STREAMING.+#include "fusion-macros.h"+ -- | Generate a source from a seed value. --+-- Subject to fusion+-- -- Since 0.4.2-unfold :: Monad m-       => (b -> Maybe (a, b))-       -> b-       -> Producer m a-unfold f =+unfold, unfoldC :: Monad m+                => (b -> Maybe (a, b))+                -> b+                -> Producer m a+unfoldC f =     go   where     go seed =         case f seed of             Just (a, seed') -> yield a >> go seed'             Nothing -> return ()+{-# INLINE unfoldC #-}+STREAMING(unfold, f x)  -- | A monadic unfold. --+-- Subject to fusion+-- -- Since 1.1.2-unfoldM :: Monad m-        => (b -> m (Maybe (a, b)))-        -> b-        -> Producer m a-unfoldM f =+unfoldM, unfoldMC :: Monad m+                  => (b -> m (Maybe (a, b)))+                  -> b+                  -> Producer m a+unfoldMC f =     go   where     go seed = do@@ -115,9 +125,15 @@         case mres of             Just (a, seed') -> yield a >> go seed'             Nothing -> return ()+STREAMING(unfoldM, f seed) -sourceList :: Monad m => [a] -> Producer m a-sourceList = Prelude.mapM_ yield+-- | Yield the values from the list.+--+-- Subject to fusion+sourceList, sourceListC :: Monad m => [a] -> Producer m a+sourceListC = Prelude.mapM_ yield+{-# INLINE sourceListC #-}+STREAMING(sourceList, xs)  -- | Enumerate from a value to a final value, inclusive, via 'succ'. --@@ -128,71 +144,37 @@ -- Subject to fusion -- -- Since 0.4.2-enumFromTo :: (Enum a, Prelude.Ord a, Monad m)-           => a-           -> a-           -> Producer m a-enumFromTo x y = unstream $ streamSource $ enumFromToS x y-{-# INLINE [0] enumFromTo #-}-{-# RULES "unstream enumFromTo" forall x y.-    enumFromTo x y = unstream (streamSourcePure $ enumFromToS x y)-  #-}--enumFromToC :: (Enum a, Prelude.Ord a, Monad m)-            => a-            -> a-            -> Producer m a+enumFromTo, enumFromToC :: (Enum a, Prelude.Ord a, Monad m)+                        => a+                        -> a+                        -> Producer m a enumFromToC x0 y =     loop x0   where     loop x         | x Prelude.> y = return ()         | otherwise = yield x >> loop (Prelude.succ x)-{-# INLINE [0] enumFromToC #-}--enumFromToS :: (Enum a, Prelude.Ord a, Monad m)-            => a-            -> a-            -> Stream m a ()-enumFromToS x0 y =-    Stream step (return x0)-  where-    step x = return $ if x Prelude.> y-        then Stop ()-        else Emit (Prelude.succ x) x-{-# INLINE [0] enumFromToS #-}--enumFromToS_int :: (Prelude.Integral a, Monad m) => a -> a -> Stream m a ()-enumFromToS_int x0 y = x0 `seq` y `seq` Stream step (return x0)-  where-    step x | x <= y    = return $ Emit (x Prelude.+ 1) x-           | otherwise = return $ Stop ()-{-# INLINE enumFromToS_int #-}--{-# RULES "enumFromTo<Int>"-      enumFromToS = enumFromToS_int :: Monad m => Int -> Int -> Stream m Int ()-  #-}+{-# INLINE enumFromToC #-}+STREAMING(enumFromTo, x0 y)  -- | Produces an infinite stream of repeated applications of f to x.-iterate :: Monad m => (a -> a) -> a -> Producer m a-iterate f =+--+-- Subject to fusion+--+iterate, iterateC :: Monad m => (a -> a) -> a -> Producer m a+iterateC f =     go   where     go a = yield a >> go (f a)+{-# INLINE iterateC #-}+STREAMING(iterate, f a)  -- | Replicate a single value the given number of times. -- -- Subject to fusion -- -- Since 1.2.0-replicate :: Monad m => Int -> a -> Producer m a-replicate = replicateC-{-# INLINE [0] replicate #-}-{-# RULES "unstream replicate" forall i a.-     replicate i a = unstream (streamConduit (replicateC i a) (\_ -> replicateS i a))-  #-}--replicateC :: Monad m => Int -> a -> Producer m a+replicate, replicateC :: Monad m => Int -> a -> Producer m a replicateC cnt0 a =     loop cnt0   where@@ -200,27 +182,14 @@         | i <= 0 = return ()         | otherwise = yield a >> loop (i - 1) {-# INLINE replicateC #-}--replicateS :: Monad m => Int -> a -> Stream m a ()-replicateS cnt0 a =-    Stream step (return cnt0)-  where-    step cnt-        | cnt <= 0  = return $ Stop ()-        | otherwise = return $ Emit (cnt - 1) a-{-# INLINE replicateS #-}+STREAMING(replicate, cnt0 a)  -- | Replicate a monadic value the given number of times. --+-- Subject to fusion+-- -- Since 1.2.0-replicateM :: Monad m => Int -> m a -> Producer m a-replicateM = replicateMC-{-# INLINE [0] replicateM #-}-{-# RULES "unstream replicateM" forall i a.-     replicateM i a = unstream (streamConduit (replicateMC i a) (\_ -> replicateMS i a))-  #-}--replicateMC :: Monad m => Int -> m a -> Producer m a+replicateM, replicateMC :: Monad m => Int -> m a -> Producer m a replicateMC cnt0 ma =     loop cnt0   where@@ -228,72 +197,33 @@         | i <= 0 = return ()         | otherwise = lift ma >>= yield >> loop (i - 1) {-# INLINE replicateMC #-}--replicateMS :: Monad m => Int -> m a -> Stream m a ()-replicateMS cnt0 ma =-    Stream step (return cnt0)-  where-    step cnt-        | cnt <= 0  = return $ Stop ()-        | otherwise = Emit (cnt - 1) `liftM` ma-{-# INLINE replicateMS #-}+STREAMING(replicateM, cnt0 ma)  -- | A strict left fold. -- -- Subject to fusion -- -- Since 0.3.0-fold :: Monad m-     => (b -> a -> b)-     -> b-     -> Consumer a m b-fold = foldC-{-# INLINE [0] fold #-}-{-# RULES "unstream fold" forall f b.-        fold f b = unstream (streamConduit (foldC f b) (foldS f b))-  #-}--foldC :: Monad m-      => (b -> a -> b)-      -> b-      -> Consumer a m b+fold, foldC :: Monad m+            => (b -> a -> b)+            -> b+            -> Consumer a m b foldC f =     loop   where     loop !accum = await >>= maybe (return accum) (loop . f accum) {-# INLINE foldC #-}--foldS :: Monad m => (b -> a -> b) -> b -> Stream m a () -> Stream m o b-foldS f b0 (Stream step ms0) =-    Stream step' (liftM (b0, ) ms0)-  where-    step' (!b, s) = do-        res <- step s-        return $ case res of-            Stop () -> Stop b-            Skip s' -> Skip (b, s')-            Emit s' a -> Skip (f b a, s')-{-# INLINE foldS #-}+STREAMING(fold, f accum)  -- | A monadic strict left fold. -- -- Subject to fusion -- -- Since 0.3.0-foldM :: Monad m-      => (b -> a -> m b)-      -> b-      -> Consumer a m b-foldM = foldMC-{-# INLINE [0] foldM #-}-{-# RULES "unstream foldM" forall f b.-        foldM f b = unstream (streamConduit (foldMC f b) (foldMS f b))-  #-}--foldMC :: Monad m-       => (b -> a -> m b)-       -> b-       -> Consumer a m b+foldM, foldMC :: Monad m+              => (b -> a -> m b)+              -> b+              -> Consumer a m b foldMC f =     loop   where@@ -304,20 +234,7 @@             accum' <- lift $ f accum a             accum' `seq` loop accum' {-# INLINE foldMC #-}--foldMS :: Monad m => (b -> a -> m b) -> b -> Stream m a () -> Stream m o b-foldMS f b0 (Stream step ms0) =-    Stream step' (liftM (b0, ) ms0)-  where-    step' (!b, s) = do-        res <- step s-        case res of-            Stop () -> return $ Stop b-            Skip s' -> return $ Skip (b, s')-            Emit s' a -> do-                b' <- f b a-                return $ Skip (b', s')-{-# INLINE foldMS #-}+STREAMING(foldM, f accum)  ----------------------------------------------------------------- -- These are for cases where- for whatever reason- stream fusion cannot be@@ -334,7 +251,7 @@         src <- msrc         go src b {-# INLINE connectFold #-}-{-# RULES "$$ fold" forall src f b. src $$ fold f b = connectFold src f b #-}+{-# RULES "conduit: $$ fold" forall src f b. src $$ fold f b = connectFold src f b #-}  connectFoldM :: Monad m => Source m a -> (b -> a -> m b) -> b -> m b connectFoldM (CI.ConduitM src0) f =@@ -350,19 +267,18 @@         src <- msrc         go src b {-# INLINE connectFoldM #-}-{-# RULES "$$ foldM" forall src f b. src $$ foldM f b = connectFoldM src f b #-}+{-# RULES "conduit: $$ foldM" forall src f b. src $$ foldM f b = connectFoldM src f b #-} -----------------------------------------------------------------  -- | A monoidal strict left fold. --+-- Subject to fusion+-- -- Since 0.5.3 foldMap :: (Monad m, Monoid b)         => (a -> b)         -> Consumer a m b-foldMap f =-    fold combiner mempty-  where-    combiner accum = mappend accum . f+INLINE_RULE(foldMap, f, let combiner accum = mappend accum . f in fold combiner mempty)  -- | A monoidal strict left fold in a Monad. --@@ -370,19 +286,19 @@ foldMapM :: (Monad m, Monoid b)         => (a -> m b)         -> Consumer a m b-foldMapM f =-    foldM combiner mempty-  where-    combiner accum = liftM (mappend accum) . f+INLINE_RULE(foldMapM, f, let combiner accum = liftM (mappend accum) . f in foldM combiner mempty)  -- | Apply the action to all values in the stream. --+-- Subject to fusion+-- -- Since 0.3.0-mapM_ :: Monad m-      => (a -> m ())-      -> Consumer a m ()-mapM_ f = awaitForever $ lift . f-{-# INLINE [1] mapM_ #-}+mapM_, mapM_C :: Monad m+              => (a -> m ())+              -> Consumer a m ()+mapM_C f = awaitForever $ lift . f+{-# INLINE mapM_C #-}+STREAMING(mapM_, f)  srcMapM_ :: Monad m => Source m a -> (a -> m ()) -> m () srcMapM_ (CI.ConduitM src) f =@@ -394,7 +310,7 @@     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 #-}+{-# RULES "conduit: connect to mapM_" [2] forall f src. src $$ mapM_ f = srcMapM_ src f #-}  -- | Ignore a certain number of values in the stream. This function is -- semantically equivalent to:@@ -404,15 +320,19 @@ -- However, @drop@ is more efficient as it does not need to hold values in -- memory. --+-- Subject to fusion+-- -- Since 0.3.0-drop :: Monad m-     => Int-     -> Consumer a m ()-drop =+drop, dropC :: Monad m+            => Int+            -> Consumer a m ()+dropC =     loop   where     loop i | i <= 0 = return ()     loop count = await >>= maybe (return ()) (\_ -> loop (count - 1))+{-# INLINE dropC #-}+STREAMING(drop, i)  -- | Take some values from the stream and return as a list. If you want to -- instead create a conduit that pipes data to another sink, see 'isolate'.@@ -420,23 +340,31 @@ -- -- > take i = isolate i =$ consume --+-- Subject to fusion+-- -- Since 0.3.0-take :: Monad m-     => Int-     -> Consumer a m [a]-take =+take, takeC :: Monad m+            => Int+            -> Consumer a m [a]+takeC =     loop id   where     loop front count | count <= 0 = return $ front []     loop front count = await >>= maybe         (return $ front [])-        (\x -> loop (front .(x:)) (count - 1))+        (\x -> loop (front . (x:)) (count - 1))+{-# INLINE takeC #-}+STREAMING(take, i)  -- | Take a single value from the stream, if available. --+-- Subject to fusion+-- -- Since 0.3.0-head :: Monad m => Consumer a m (Maybe a)-head = await+head, headC :: Monad m => Consumer a m (Maybe a)+headC = await+{-# INLINE headC #-}+STREAMING0(head)  -- | Look at the next value in the stream, if available. This function will not -- change the state of the stream.@@ -450,32 +378,14 @@ -- Subject to fusion -- -- Since 0.3.0-map :: Monad m => (a -> b) -> Conduit a m b-map = mapC-{-# INLINE [0] map #-}-{-# RULES "unstream map" forall f.-    map f = unstream (streamConduit (mapC f) (mapS f))-  #-}--mapC :: Monad m => (a -> b) -> Conduit a m b+map, mapC :: Monad m => (a -> b) -> Conduit a m b mapC f = awaitForever $ yield . f {-# INLINE mapC #-}--mapS :: Monad m => (a -> b) -> Stream m a r -> Stream m b r-mapS f (Stream step ms0) =-    Stream step' ms0-  where-    step' s = do-        res <- step s-        return $ case res of-            Stop r -> Stop r-            Emit s' a -> Emit s' (f a)-            Skip s' -> Skip s'-{-# INLINE mapS #-}+STREAMING(map, f)  -- 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 "conduit: source/map fusion =$=" forall f src. src =$= map f = mapFuseRight src f #-}  mapFuseRight :: Monad m => Source m a -> (a -> b) -> Source m b mapFuseRight src f = CIC.mapOutput f src@@ -487,18 +397,18 @@ It might be nice to include these rewrite rules, but they may have subtle differences based on leftovers. -{-# RULES "map-to-mapOutput pipeL" forall f src. pipeL src (map f) = mapOutput f src #-}-{-# RULES "map-to-mapOutput $=" forall f src. src $= (map f) = mapOutput f src #-}-{-# RULES "map-to-mapOutput pipe" forall f src. pipe src (map f) = mapOutput f src #-}-{-# RULES "map-to-mapOutput >+>" forall f src. src >+> (map f) = mapOutput f src #-}+{-# RULES "conduit: map-to-mapOutput pipeL" forall f src. pipeL src (map f) = mapOutput f src #-}+{-# RULES "conduit: map-to-mapOutput $=" forall f src. src $= (map f) = mapOutput f src #-}+{-# RULES "conduit: map-to-mapOutput pipe" forall f src. pipe src (map f) = mapOutput f src #-}+{-# RULES "conduit: map-to-mapOutput >+>" forall f src. src >+> (map f) = mapOutput f src #-} -{-# RULES "map-to-mapInput pipeL" forall f sink. pipeL (map f) sink = mapInput f (Prelude.const Prelude.Nothing) sink #-}-{-# RULES "map-to-mapInput =$" forall f sink. map f =$ sink = mapInput f (Prelude.const Prelude.Nothing) sink #-}-{-# RULES "map-to-mapInput pipe" forall f sink. pipe (map f) sink = mapInput f (Prelude.const Prelude.Nothing) sink #-}-{-# RULES "map-to-mapInput >+>" forall f sink. map f >+> sink = mapInput f (Prelude.const Prelude.Nothing) sink #-}+{-# RULES "conduit: map-to-mapInput pipeL" forall f sink. pipeL (map f) sink = mapInput f (Prelude.const Prelude.Nothing) sink #-}+{-# RULES "conduit: map-to-mapInput =$" forall f sink. map f =$ sink = mapInput f (Prelude.const Prelude.Nothing) sink #-}+{-# RULES "conduit: map-to-mapInput pipe" forall f sink. pipe (map f) sink = mapInput f (Prelude.const Prelude.Nothing) sink #-}+{-# RULES "conduit: map-to-mapInput >+>" forall f sink. map f >+> sink = mapInput f (Prelude.const Prelude.Nothing) sink #-} -{-# RULES "map-to-mapOutput =$=" forall f con. con =$= map f = mapOutput f con #-}-{-# RULES "map-to-mapInput =$=" forall f con. map f =$= con = mapInput f (Prelude.const Prelude.Nothing) con #-}+{-# RULES "conduit: map-to-mapOutput =$=" forall f con. con =$= map f = mapOutput f con #-}+{-# RULES "conduit: map-to-mapInput =$=" forall f con. map f =$= con = mapInput f (Prelude.const Prelude.Nothing) con #-}  {-# INLINE [1] map #-} @@ -512,28 +422,10 @@ -- Subject to fusion -- -- Since 0.3.0-mapM :: Monad m => (a -> m b) -> Conduit a m b-mapM = mapMC-{-# INLINE [0] mapM #-}-{-# RULES "unstream mapM" forall f.-    mapM f = unstream (streamConduit (mapMC f) (mapMS f))-  #-}--mapMC :: Monad m => (a -> m b) -> Conduit a m b+mapM, mapMC :: Monad m => (a -> m b) -> Conduit a m b mapMC f = awaitForever $ \a -> lift (f a) >>= yield {-# INLINE mapMC #-}--mapMS :: Monad m => (a -> m b) -> Stream m a r -> Stream m b r-mapMS f (Stream step ms0) =-    Stream step' ms0-  where-    step' s = do-        res <- step s-        case res of-            Stop r -> return $ Stop r-            Emit s' a -> Emit s' `liftM` f a-            Skip s' -> return $ Skip s'-{-# INLINE mapMS #-}+STREAMING(mapM, f)  -- | Apply a monadic action on all values in a stream. --@@ -542,56 +434,88 @@ -- -- > iterM f = mapM (\a -> f a >>= \() -> return a) --+-- Subject to fusion+-- -- Since 0.5.6-iterM :: Monad m => (a -> m ()) -> Conduit a m a-iterM f = awaitForever $ \a -> lift (f a) >> yield a+iterM, iterMC :: Monad m => (a -> m ()) -> Conduit a m a+iterMC f = awaitForever $ \a -> lift (f a) >> yield a+{-# INLINE iterMC #-}+STREAMING(iterM, f)  -- | Apply a transformation that may fail to all values in a stream, discarding -- the failures. --+-- Subject to fusion+-- -- Since 0.5.1-mapMaybe :: Monad m => (a -> Maybe b) -> Conduit a m b-mapMaybe f = awaitForever $ maybe (return ()) yield . f+mapMaybe, mapMaybeC :: Monad m => (a -> Maybe b) -> Conduit a m b+mapMaybeC f = awaitForever $ maybe (return ()) yield . f+{-# INLINE mapMaybeC #-}+STREAMING(mapMaybe, f)  -- | Apply a monadic transformation that may fail to all values in a stream, -- discarding the failures. --+-- Subject to fusion+-- -- Since 0.5.1-mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Conduit a m b-mapMaybeM f = awaitForever $ maybe (return ()) yield <=< lift . f+mapMaybeM, mapMaybeMC :: Monad m => (a -> m (Maybe b)) -> Conduit a m b+mapMaybeMC f = awaitForever $ maybe (return ()) yield <=< lift . f+{-# INLINE mapMaybeMC #-}+STREAMING(mapMaybeM, f)  -- | Filter the @Just@ values from a stream, discarding the @Nothing@  values. --+-- Subject to fusion+-- -- Since 0.5.1-catMaybes :: Monad m => Conduit (Maybe a) m a-catMaybes = awaitForever $ maybe (return ()) yield+catMaybes, catMaybesC :: Monad m => Conduit (Maybe a) m a+catMaybesC = awaitForever $ maybe (return ()) yield+{-# INLINE catMaybesC #-}+STREAMING0(catMaybes)  -- | Generalization of 'catMaybes'. It puts all values from --   'F.Foldable' into stream. --+-- Subject to fusion+-- -- Since 1.0.6-concat :: (Monad m, F.Foldable f) => Conduit (f a) m a-concat = awaitForever $ F.mapM_ yield+concat, concatC :: (Monad m, F.Foldable f) => Conduit (f a) m a+concatC = awaitForever $ F.mapM_ yield+{-# INLINE concatC #-}+STREAMING0(concat)  -- | Apply a transformation to all values in a stream, concatenating the output -- values. --+-- Subject to fusion+-- -- Since 0.3.0-concatMap :: Monad m => (a -> [b]) -> Conduit a m b-concatMap f = awaitForever $ sourceList . f+concatMap, concatMapC :: Monad m => (a -> [b]) -> Conduit a m b+concatMapC f = awaitForever $ sourceList . f+{-# INLINE concatMapC #-}+STREAMING(concatMap, f)  -- | Apply a monadic transformation to all values in a stream, concatenating -- the output values. --+-- Subject to fusion+-- -- Since 0.3.0-concatMapM :: Monad m => (a -> m [b]) -> Conduit a m b-concatMapM f = awaitForever $ sourceList <=< lift . f+concatMapM, concatMapMC :: Monad m => (a -> m [b]) -> Conduit a m b+concatMapMC f = awaitForever $ sourceList <=< lift . f+{-# INLINE concatMapMC #-}+STREAMING(concatMapM, f)  -- | 'concatMap' with an accumulator. --+-- Subject to fusion+-- -- Since 0.3.0-concatMapAccum :: Monad m => (a -> accum -> (accum, [b])) -> accum -> Conduit a m b-concatMapAccum f x0 = void (mapAccum f x0) =$= concat+concatMapAccum, concatMapAccumC :: Monad m => (a -> accum -> (accum, [b])) -> accum -> Conduit a m b+concatMapAccumC f x0 = void (mapAccum f x0) =$= concat+{-# INLINE concatMapAccumC #-}+STREAMING(concatMapAccum, f x0)  -- | Deprecated synonym for @mapAccum@ --@@ -609,21 +533,26 @@  -- | Analog of @mapAccumL@ for lists. --+-- Subject to fusion+-- -- Since 1.1.1-mapAccum :: Monad m => (a -> s -> (s, b)) -> s -> ConduitM a b m s-mapAccum f =+mapAccum, mapAccumC :: Monad m => (a -> s -> (s, b)) -> s -> ConduitM a b m s+mapAccumC f =     loop   where     loop s = await >>= maybe (return s) go       where         go a = case f a s of                  (s', b) -> yield b >> loop s'+STREAMING(mapAccum, f s)  -- | Monadic `mapAccum`. --+-- Subject to fusion+-- -- Since 1.1.1-mapAccumM :: Monad m => (a -> s -> m (s, b)) -> s -> ConduitM a b m s-mapAccumM f =+mapAccumM, mapAccumMC :: Monad m => (a -> s -> m (s, b)) -> s -> ConduitM a b m s+mapAccumMC f =     loop   where     loop s = await >>= maybe (return s) go@@ -631,43 +560,56 @@         go a = do (s', b) <- lift $ f a s                   yield b                   loop s'+{-# INLINE mapAccumMC #-}+STREAMING(mapAccumM, f s)  -- | Analog of 'Prelude.scanl' for lists. --+-- Subject to fusion+-- -- Since 1.1.1 scan :: Monad m => (a -> b -> b) -> b -> ConduitM a b m b-scan f =-    mapAccum $ \a b -> let b' = f a b in (b', b')+INLINE_RULE(scan, f, mapAccum (\a b -> let r = f a b in (r, r)))  -- | Monadic @scanl@. --+-- Subject to fusion+-- -- Since 1.1.1 scanM :: Monad m => (a -> b -> m b) -> b -> ConduitM a b m b-scanM f =-    mapAccumM $ \a b -> do b' <- f a b-                           return (b', b')+INLINE_RULE(scanM, f, mapAccumM (\a b -> f a b >>= \r -> return (r, r)))  -- | 'concatMapM' with an accumulator. --+-- Subject to fusion+-- -- Since 0.3.0-concatMapAccumM :: Monad m => (a -> accum -> m (accum, [b])) -> accum -> Conduit a m b-concatMapAccumM f x0 = void (mapAccumM f x0) =$= concat-+concatMapAccumM, concatMapAccumMC :: Monad m => (a -> accum -> m (accum, [b])) -> accum -> Conduit a m b+concatMapAccumMC f x0 = void (mapAccumM f x0) =$= concat+{-# INLINE concatMapAccumMC #-}+STREAMING(concatMapAccumM, f x0)  -- | Generalization of 'mapMaybe' and 'concatMap'. It applies function -- to all values in a stream and send values inside resulting -- 'Foldable' downstream. --+-- Subject to fusion+-- -- Since 1.0.6-mapFoldable :: (Monad m, F.Foldable f) => (a -> f b) -> Conduit a m b-mapFoldable f = awaitForever $ F.mapM_ yield . f+mapFoldable, mapFoldableC :: (Monad m, F.Foldable f) => (a -> f b) -> Conduit a m b+mapFoldableC f = awaitForever $ F.mapM_ yield . f+{-# INLINE mapFoldableC #-}+STREAMING(mapFoldable, f)  -- | Monadic variant of 'mapFoldable'. --+-- Subject to fusion+-- -- Since 1.0.6-mapFoldableM :: (Monad m, F.Foldable f) => (a -> m (f b)) -> Conduit a m b-mapFoldableM f = awaitForever $ F.mapM_ yield <=< lift . f-+mapFoldableM, mapFoldableMC :: (Monad m, F.Foldable f) => (a -> m (f b)) -> Conduit a m b+mapFoldableMC f = awaitForever $ F.mapM_ yield <=< lift . f+{-# INLINE mapFoldableMC #-}+STREAMING(mapFoldableM, f)  -- | Consume all values from the stream and return as a list. Note that this -- will pull all values into memory. For a lazy variant, see@@ -676,35 +618,21 @@ -- Subject to fusion -- -- Since 0.3.0-consume :: Monad m => Consumer a m [a]-consume = consumeC-{-# INLINE [0] consume #-}-{-# RULES "unstream consume" consume = unstream (streamConduit consumeC consumeS) #-}--consumeC :: Monad m => Consumer a m [a]+consume, consumeC :: Monad m => Consumer a m [a] consumeC =     loop id   where     loop front = await >>= maybe (return $ front []) (\x -> loop $ front . (x:)) {-# INLINE consumeC #-}--consumeS :: Monad m => Stream m a () -> Stream m o [a]-consumeS (Stream step ms0) =-    Stream step' (liftM (id,) ms0)-  where-    step' (front, s) = do-        res <- step s-        return $ case res of-            Stop () -> Stop (front [])-            Skip s' -> Skip (front, s')-            Emit s' a -> Skip (front . (a:), s')-{-# INLINE consumeS #-}+STREAMING0(consume)  -- | Grouping input according to an equality function. --+-- Subject to fusion+-- -- Since 0.3.0-groupBy :: Monad m => (a -> a -> Bool) -> Conduit a m [a]-groupBy f =+groupBy, groupByC :: Monad m => (a -> a -> Bool) -> Conduit a m [a]+groupByC f =     start   where     start = await >>= maybe (return ()) (loop id)@@ -715,7 +643,7 @@         go y             | f x y     = loop (rest . (y:)) x             | otherwise = yield (x : rest []) >> loop id y-+STREAMING(groupBy, f)  -- | 'groupOn1' is similar to @groupBy id@ --@@ -728,11 +656,13 @@ -- > groupOn1 :: (Monad m, Eq b) => (a -> b) -> Conduit a m (NonEmpty a) -- > groupOn1 f = CL.groupOn1 f =$= CL.map (uncurry (:|)) --+-- Subject to fusion+-- -- Since 1.1.7-groupOn1 :: (Monad m, Eq b)-         => (a -> b)-         -> Conduit a m (a, [a])-groupOn1 f =+groupOn1, groupOn1C :: (Monad m, Eq b)+                     => (a -> b)+                     -> Conduit a m (a, [a])+groupOn1C f =     start   where     start = await >>= maybe (return ()) (loop id)@@ -743,7 +673,7 @@         go y             | f x == f y = loop (rest . (y:)) x             | otherwise  = yield (x, rest []) >> loop id y-+STREAMING(groupOn1, f)  -- | Ensure that the inner sink consumes no more than the given number of -- values. Note this this does /not/ ensure that the sink consumes all of those@@ -757,19 +687,25 @@ -- >     someOtherSink -- >     ... --+-- Subject to fusion+-- -- Since 0.3.0-isolate :: Monad m => Int -> Conduit a m a-isolate =+isolate, isolateC :: Monad m => Int -> Conduit a m a+isolateC =     loop   where     loop count | count <= 0 = return ()     loop count = await >>= maybe (return ()) (\x -> yield x >> loop (count - 1))+STREAMING(isolate, count)  -- | Keep only values in the stream passing a given predicate. --+-- Subject to fusion+-- -- Since 0.3.0-filter :: Monad m => (a -> Bool) -> Conduit a m a-filter f = awaitForever $ \i -> when (f i) (yield i)+filter, filterC :: Monad m => (a -> Bool) -> Conduit a m a+filterC f = awaitForever $ \i -> when (f i) (yield i)+STREAMING(filter, f)  filterFuseRight :: Monad m => Source m a -> (a -> Bool) -> Source m a filterFuseRight (CI.ConduitM src) f = CI.ConduitM $ \rest -> let@@ -784,16 +720,19 @@ -- 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 "conduit: 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'. --+-- Subject to fusion+-- -- Since 0.3.0-sinkNull :: Monad m => Consumer a m ()-sinkNull = awaitForever $ \_ -> return ()-{-# RULES "connect to sinkNull" forall src. src $$ sinkNull = srcSinkNull src #-}+sinkNull, sinkNullC :: Monad m => Consumer a m ()+sinkNullC = awaitForever $ \_ -> return ()+{-# INLINE sinkNullC #-}+STREAMING0(sinkNull)  srcSinkNull :: Monad m => Source m a -> m () srcSinkNull (CI.ConduitM src) =@@ -805,13 +744,18 @@     go (CI.HaveOutput p _ _) = go p     go (CI.NeedInput _ c) = go (c ()) {-# INLINE srcSinkNull #-}+{-# RULES "conduit: connect to sinkNull" forall src. src $$ sinkNull = srcSinkNull src #-}  -- | A source that outputs no values. Note that this is just a type-restricted -- synonym for 'mempty'. --+-- Subject to fusion+-- -- Since 0.3.0-sourceNull :: Monad m => Producer m a-sourceNull = return ()+sourceNull, sourceNullC :: Monad m => Producer m a+sourceNullC = return ()+{-# INLINE sourceNullC #-}+STREAMING0(sourceNull)  -- | Run a @Pipe@ repeatedly, and output its result value downstream. Stops -- when no more input is available from upstream.
conduit.cabal view
@@ -1,5 +1,5 @@ Name:                conduit-Version:             1.2.1+Version:             1.2.2 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>.@@ -13,15 +13,17 @@ Homepage:            http://github.com/snoyberg/conduit extra-source-files:  test/main.hs                    , changelog.md+                   , fusion-macros.h  Library   Exposed-modules:     Data.Conduit                        Data.Conduit.List                        Data.Conduit.Internal                        Data.Conduit.Lift+                       Data.Conduit.Internal.Fusion+                       Data.Conduit.Internal.List.Stream   other-modules:       Data.Conduit.Internal.Pipe                        Data.Conduit.Internal.Conduit-                       Data.Conduit.Internal.Fusion   Build-depends:       base                     >= 4.3          && < 5                      , resourcet                >= 1.1          && < 1.2                      , exceptions               >= 0.6@@ -33,12 +35,14 @@                      , mtl                      , void                     >= 0.5.5                      , mmorph-  ghc-options:     -Wall+  ghc-options:         -Wall+  include-dirs:        .  test-suite test     hs-source-dirs: test     main-is: main.hs     other-modules: Data.Conduit.Extra.ZipConduitSpec+                 , Data.Conduit.StreamSpec     type: exitcode-stdio-1.0     cpp-options:   -DTEST     build-depends:   conduit@@ -51,6 +55,7 @@                    , void                    , containers                    , exceptions >= 0.6+                   , safe     ghc-options:     -Wall  --test-suite doctests
+ fusion-macros.h view
@@ -0,0 +1,23 @@+#define INLINE_RULE0(new,old)             ;\+    new = old                            ;\+    {-# INLINE [0] new #-}               ;\+    {-# RULES "inline new" new = old #-}++#define INLINE_RULE(new,vars,body)                           ;\+    new vars = body                                         ;\+    {-# INLINE [0] new #-}                                  ;\+    {-# RULES "inline new" forall vars. new vars = body #-}++#define STREAMING0(name)                                 ;\+    name = name/**/C                                     ;\+    {-# INLINE [0] name #-}                              ;\+    {-# RULES "unstream name"                             \+      name = unstream (streamConduit name/**/C name/**/S) \+      #-}++#define STREAMING(name,vars)                                                ;\+    name = name/**/C                                                        ;\+    {-# INLINE [0] name #-}                                                 ;\+    {-# RULES "unstream name" forall vars.                                   \+      name vars = unstream (streamConduit (name/**/C vars) (name/**/S vars)) \+      #-}
+ test/Data/Conduit/StreamSpec.hs view
@@ -0,0 +1,596 @@+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+module Data.Conduit.StreamSpec where++import           Control.Applicative+import qualified Control.Monad+import           Control.Monad (MonadPlus(..), liftM)+import           Control.Monad.Identity (Identity, runIdentity)+import           Control.Monad.State (StateT(..), get, put)+import           Data.Conduit+import           Data.Conduit.Internal.Fusion+import           Data.Conduit.Internal.List.Stream+import           Data.Conduit.List+import qualified Data.Foldable as F+import qualified Data.Foldable+import           Data.Function (on)+import qualified Data.List+import qualified Data.Maybe+import           Data.Monoid (Monoid(..))+import           Prelude+    ((.), ($), (>>=), (=<<), return, (==), Int, id, Maybe(..), Monad, Bool(..),+     Eq, Show, String, Functor, fst, snd)+import qualified Prelude+import qualified Safe+import           Test.Hspec+import           Test.QuickCheck++spec :: Spec+spec = describe "Comparing list function to" $ do+    qit "unfold" $+        \(getBlind -> f, initial :: Int) ->+            unfold f initial `checkInfiniteProducer`+            (Data.List.unfoldr f initial :: [Int])+    qit "unfoldS" $+        \(getBlind -> f, initial :: Int) ->+            unfoldS f initial `checkInfiniteStreamProducer`+            (Data.List.unfoldr f initial :: [Int])+    qit "unfoldM" $+        \(getBlind -> f, initial :: Int) ->+            unfoldM f initial `checkInfiniteProducerM`+            (unfoldrM f initial :: M [Int])+    qit "unfoldMS" $+        \(getBlind -> f, initial :: Int) ->+            unfoldMS f initial `checkInfiniteStreamProducerM`+            (unfoldrM f initial :: M [Int])+    qit "sourceList" $+        \(xs :: [Int]) ->+            sourceList xs `checkProducer` xs+    qit "sourceListS" $+        \(xs :: [Int]) ->+            sourceListS xs `checkStreamProducer` xs+    qit "enumFromTo" $+        \(fr :: Small Int, to :: Small Int) ->+            enumFromTo fr to `checkProducer`+            Prelude.enumFromTo fr to+    qit "enumFromToS" $+        \(fr :: Small Int, to :: Small Int) ->+            enumFromToS fr to `checkStreamProducer`+            Prelude.enumFromTo fr to+    qit "enumFromToS_int" $+        \(getSmall -> fr :: Int, getSmall -> to :: Int) ->+            enumFromToS_int fr to `checkStreamProducer`+            Prelude.enumFromTo fr to+    qit "iterate" $+        \(getBlind -> f, initial :: Int) ->+            iterate f initial `checkInfiniteProducer`+            Prelude.iterate f initial+    qit "iterateS" $+        \(getBlind -> f, initial :: Int) ->+            iterateS f initial `checkInfiniteStreamProducer`+            Prelude.iterate f initial+    qit "replicate" $+        \(getSmall -> n, getSmall -> x) ->+            replicate n x `checkProducer`+            (Prelude.replicate n x :: [Int])+    qit "replicateS" $+        \(getSmall -> n, getSmall -> x) ->+            replicateS n x `checkStreamProducer`+            (Prelude.replicate n x :: [Int])+    qit "replicateM" $+        \(getSmall -> n, getBlind -> f) ->+            replicateM n f `checkProducerM`+            (Control.Monad.replicateM n f :: M [Int])+    qit "replicateMS" $+        \(getSmall -> n, getBlind -> f) ->+            replicateMS n f `checkStreamProducerM`+            (Control.Monad.replicateM n f :: M [Int])+    qit "fold" $+        \(getBlind -> f, initial :: Int) ->+            fold f initial `checkConsumer`+            Data.List.foldl' f initial+    qit "foldS" $+        \(getBlind -> f, initial :: Int) ->+            foldS f initial `checkStreamConsumer`+            Data.List.foldl' f initial+    qit "foldM" $+        \(getBlind -> f, initial :: Int) ->+            foldM f initial `checkConsumerM`+            (Control.Monad.foldM f initial :: [Int] -> M Int)+    qit "foldMS" $+        \(getBlind -> f, initial :: Int) ->+            foldMS f initial `checkStreamConsumerM`+            (Control.Monad.foldM f initial :: [Int] -> M Int)+    qit "foldMap" $+        \(getBlind -> (f :: Int -> Sum Int)) ->+            foldMap f `checkConsumer`+            Data.Foldable.foldMap f+    qit "mapM_" $+        \(getBlind -> (f :: Int -> M ())) ->+            mapM_ f `checkConsumerM`+            Prelude.mapM_ f+    qit "mapM_S" $+        \(getBlind -> (f :: Int -> M ())) ->+            mapM_S f `checkStreamConsumerM`+            Prelude.mapM_ f+    qit "take" $+        \(getSmall -> n) ->+            take n `checkConsumer`+            Prelude.take n+    qit "takeS" $+        \(getSmall -> n) ->+            takeS n `checkStreamConsumer`+            Prelude.take n+    qit "head" $+        \() ->+            head `checkConsumer`+            Safe.headMay+    qit "headS" $+        \() ->+            headS `checkStreamConsumer`+            Safe.headMay+    qit "peek" $+        \() ->+            peek `checkConsumer`+            Safe.headMay+    qit "map" $+        \(getBlind -> (f :: Int -> Int)) ->+            map f `checkConduit`+            Prelude.map f+    qit "mapS" $+        \(getBlind -> (f :: Int -> Int)) ->+            mapS f `checkStreamConduit`+            Prelude.map f+    qit "mapM" $+        \(getBlind -> (f :: Int -> M Int)) ->+            mapM f `checkConduitM`+            Prelude.mapM f+    qit "mapMS" $+        \(getBlind -> (f :: Int -> M Int)) ->+            mapMS f `checkStreamConduitM`+            Prelude.mapM f+    qit "iterM" $+        \(getBlind -> (f :: Int -> M ())) ->+            iterM f `checkConduitM`+            iterML f+    qit "iterMS" $+        \(getBlind -> (f :: Int -> M ())) ->+            iterMS f `checkStreamConduitM`+            iterML f+    qit "mapMaybe" $+        \(getBlind -> (f :: Int -> Maybe Int)) ->+            mapMaybe f `checkConduit`+            Data.Maybe.mapMaybe f+    qit "mapMaybeS" $+        \(getBlind -> (f :: Int -> Maybe Int)) ->+            mapMaybeS f `checkStreamConduit`+            Data.Maybe.mapMaybe f+    qit "mapMaybeM" $+        \(getBlind -> (f :: Int -> M (Maybe Int))) ->+            mapMaybeM f `checkConduitM`+            mapMaybeML f+    qit "mapMaybeMS" $+        \(getBlind -> (f :: Int -> M (Maybe Int))) ->+            mapMaybeMS f `checkStreamConduitM`+            mapMaybeML f+    qit "catMaybes" $+        \() ->+            catMaybes `checkConduit`+            (Data.Maybe.catMaybes :: [Maybe Int] -> [Int])+    qit "catMaybesS" $+        \() ->+            catMaybesS `checkStreamConduit`+            (Data.Maybe.catMaybes :: [Maybe Int] -> [Int])+    qit "concat" $+        \() ->+            concat `checkConduit`+            (Prelude.concat :: [[Int]] -> [Int])+    qit "concatS" $+        \() ->+            concatS `checkStreamConduit`+            (Prelude.concat :: [[Int]] -> [Int])+    qit "concatMap" $+        \(getBlind -> f) ->+            concatMap f `checkConduit`+            (Prelude.concatMap f :: [Int] -> [Int])+    qit "concatMapS" $+        \(getBlind -> f) ->+            concatMapS f `checkStreamConduit`+            (Prelude.concatMap f :: [Int] -> [Int])+    qit "concatMapM" $+        \(getBlind -> (f :: Int -> M [Int])) ->+            concatMapM f `checkConduitM`+            concatMapML f+    qit "concatMapMS" $+        \(getBlind -> (f :: Int -> M [Int])) ->+            concatMapMS f `checkStreamConduitM`+            concatMapML f+    qit "concatMapAccum" $+        \(getBlind -> (f :: Int -> Int -> (Int, [Int])), initial :: Int) ->+            concatMapAccum f initial `checkConduit`+            concatMapAccumL f initial+    qit "concatMapAccumS" $+        \(getBlind -> (f :: Int -> Int -> (Int, [Int])), initial :: Int) ->+            concatMapAccumS f initial `checkStreamConduit`+            concatMapAccumL f initial+    {-qit "mapAccum" $+        \(getBlind -> (f :: Int -> Int -> (Int, [Int])), initial :: Int) ->+            mapAccum f initial `checkConduitResult`+            mapAccumL f initial-}+    qit "mapAccumS" $+        \(getBlind -> (f :: Int -> Int -> (Int, [Int])), initial :: Int) ->+            mapAccumS f initial `checkStreamConduitResult`+            mapAccumL f initial+    {-qit "mapAccumM" $+        \(getBlind -> (f :: Int -> Int -> M (Int, [Int])), initial :: Int) ->+            mapAccumM f initial `checkConduitResultM`+            mapAccumML f initial-}+    qit "mapAccumMS" $+        \(getBlind -> (f :: Int -> Int -> M (Int, [Int])), initial :: Int) ->+            mapAccumMS f initial `checkStreamConduitResultM`+            mapAccumML f initial+    {-qit "scan" $+        \(getBlind -> (f :: Int -> Int -> Int), initial :: Int) ->+            scan f initial `checkConduitResult`+            scanL f initial-}+    {-qit "scanM" $+        \(getBlind -> (f :: Int -> Int -> M Int), initial :: Int) ->+            scanM f initial `checkConduitResultM`+            scanML f initial-}+    qit "mapFoldable" $+        \(getBlind -> (f :: Int -> [Int])) ->+            mapFoldable f `checkConduit`+            mapFoldableL f+    qit "mapFoldableS" $+        \(getBlind -> (f :: Int -> [Int])) ->+            mapFoldableS f `checkStreamConduit`+            mapFoldableL f+    qit "mapFoldableM" $+        \(getBlind -> (f :: Int -> M [Int])) ->+            mapFoldableM f `checkConduitM`+            mapFoldableML f+    qit "mapFoldableMS" $+        \(getBlind -> (f :: Int -> M [Int])) ->+            mapFoldableMS f `checkStreamConduitM`+            mapFoldableML f+    qit "consume" $+        \() ->+            consume `checkConsumer`+            id+    qit "consumeS" $+        \() ->+            consumeS `checkStreamConsumer`+            id+    qit "groupBy" $+        \(getBlind -> f) ->+            groupBy f `checkConduit`+            (Data.List.groupBy f :: [Int] -> [[Int]])+    qit "groupByS" $+        \(getBlind -> f) ->+            groupByS f `checkStreamConduit`+            (Data.List.groupBy f :: [Int] -> [[Int]])+    qit "groupOn1" $+        \(getBlind -> (f :: Int -> Int)) ->+            groupOn1 f `checkConduit`+            groupOn1L f+    qit "groupOn1S" $+        \(getBlind -> (f :: Int -> Int)) ->+            groupOn1S f `checkStreamConduit`+            groupOn1L f+    qit "isolate" $+        \n ->+            isolate n `checkConduit`+            (Data.List.take n :: [Int] -> [Int])+    qit "isolateS" $+        \n ->+            isolateS n `checkStreamConduit`+            (Data.List.take n :: [Int] -> [Int])+    qit "filter" $+        \(getBlind -> f) ->+            filter f `checkConduit`+            (Data.List.filter f :: [Int] -> [Int])+    qit "filterS" $+        \(getBlind -> f) ->+            filterS f `checkStreamConduit`+            (Data.List.filter f :: [Int] -> [Int])+    qit "sourceNull" $+        \() ->+            sourceNull `checkProducer`+            ([] :: [Int])+    qit "sourceNullS" $+        \() ->+            sourceNullS `checkStreamProducer`+            ([] :: [Int])++qit :: (Arbitrary a, Testable prop, Show a)+    => String -> (a -> prop) -> Spec+qit n f = it n $ property $ forAll arbitrary f++--------------------------------------------------------------------------------+-- Quickcheck utilities for pure conduits / streams++checkProducer :: (Show a, Eq a) => Source Identity a -> [a] -> Property+checkProducer c l  = checkProducerM' runIdentity c (return l)++checkStreamProducer :: (Show a, Eq a) => StreamSource Identity a -> [a] -> Property+checkStreamProducer s l = checkStreamProducerM' runIdentity s (return l)++checkInfiniteProducer :: (Show a, Eq a) => Source Identity a -> [a] -> Property+checkInfiniteProducer c l = checkInfiniteProducerM' runIdentity c (return l)++checkInfiniteStreamProducer :: (Show a, Eq a) => StreamSource Identity a -> [a] -> Property+checkInfiniteStreamProducer s l = checkInfiniteStreamProducerM' runIdentity s (return l)++checkConsumer :: (Show b, Eq b) => Consumer Int Identity b -> ([Int] -> b) -> Property+checkConsumer c l = checkConsumerM' runIdentity c (return . l)++checkStreamConsumer :: (Show b, Eq b) => StreamConsumer Int Identity b -> ([Int] -> b) -> Property+checkStreamConsumer c l = checkStreamConsumerM' runIdentity c (return . l)++checkConduit :: (Show a, Arbitrary a, Show b, Eq b) => Conduit a Identity b -> ([a] -> [b]) -> Property+checkConduit c l = checkConduitM' runIdentity c (return . l)++checkStreamConduit :: (Show a, Arbitrary a, Show b, Eq b) => StreamConduit a Identity b -> ([a] -> [b]) -> Property+checkStreamConduit c l = checkStreamConduitM' runIdentity c (return . l)++-- checkConduitResult :: (Show a, Arbitrary a, Show b, Eq b, Show r, Eq r) => ConduitM a b Identity r -> ([a] -> ([b], r)) -> Property+-- checkConduitResult c l = checkConduitResultM' runIdentity c (return . l)++checkStreamConduitResult :: (Show a, Arbitrary a, Show b, Eq b, Show r, Eq r) => StreamConduitM a b Identity r -> ([a] -> ([b], r)) -> Property+checkStreamConduitResult c l = checkStreamConduitResultM' runIdentity c (return . l)++--------------------------------------------------------------------------------+-- Quickcheck utilities for conduits / streams in the M monad.++checkProducerM :: (Show a, Eq a) => Source M a -> M [a] -> Property+checkProducerM = checkProducerM' runM++checkStreamProducerM :: (Show a, Eq a) => StreamSource M a -> M [a] -> Property+checkStreamProducerM = checkStreamProducerM' runM++checkInfiniteProducerM :: (Show a, Eq a) => Source M a -> M [a] -> Property+checkInfiniteProducerM = checkInfiniteProducerM' (fst . runM)++checkInfiniteStreamProducerM :: (Show a, Eq a) => StreamSource M a -> M [a] -> Property+checkInfiniteStreamProducerM = checkInfiniteStreamProducerM' (fst . runM)++checkConsumerM :: (Show b, Eq b) => Consumer Int M b -> ([Int] -> M b) -> Property+checkConsumerM  = checkConsumerM' runM++checkStreamConsumerM :: (Show b, Eq b) => StreamConsumer Int M b -> ([Int] -> M b) -> Property+checkStreamConsumerM  = checkStreamConsumerM' runM++checkConduitM :: (Show a, Arbitrary a, Show b, Eq b) => Conduit a M b -> ([a] -> M [b]) -> Property+checkConduitM = checkConduitM' runM++checkStreamConduitM :: (Show a, Arbitrary a, Show b, Eq b) => StreamConduit a M b -> ([a] -> M [b]) -> Property+checkStreamConduitM = checkStreamConduitM' runM++-- checkConduitResultM :: (Show a, Arbitrary a, Show b, Eq b, Show r, Eq r) => ConduitM a b M r -> ([a] -> M ([b], r)) -> Property+-- checkConduitResultM = checkConduitResultM' runM++checkStreamConduitResultM :: (Show a, Arbitrary a, Show b, Eq b, Show r, Eq r) => StreamConduitM a b M r -> ([a] -> M ([b], r)) -> Property+checkStreamConduitResultM = checkStreamConduitResultM' runM++--------------------------------------------------------------------------------+-- Quickcheck utilities for monadic streams / conduits+-- These are polymorphic in which Monad is used.++checkProducerM' :: (Show a, Monad m, Show b, Eq b)+                => (m [a] -> b)+                -> Source m a+                -> m [a]+                -> Property+checkProducerM' f c l =+    f (preventFusion c $$ consume)+    ===+    f l++checkStreamProducerM' :: (Show a, Monad m, Show b, Eq b)+                      => (m [a] -> b)+                      -> StreamSource m a+                      -> m [a]+                      -> Property+checkStreamProducerM' f s l =+    f (liftM fst $ evalStream $ s emptyStream)+    ===+    f l++checkInfiniteProducerM' :: (Show a, Monad m, Show b, Eq b)+                        => (m [a] -> b)+                        -> Source m a+                        -> m [a]+                        -> Property+checkInfiniteProducerM' f s l =+    checkProducerM' f+        (preventFusion s $= isolate 10)+        (liftM (Prelude.take 10) l)++checkInfiniteStreamProducerM' :: (Show a, Monad m, Show b, Eq b)+                              => (m [a] -> b)+                              -> StreamSource m a+                              -> m [a]+                              -> Property+checkInfiniteStreamProducerM' f s l =+    f (liftM snd $ evalStream $ takeS 10 $ s emptyStream)+    ===+    f (liftM (Prelude.take 10) l)++checkConsumerM' :: (Show a, Monad m, Show b, Eq b)+                => (m a -> b)+                -> Consumer Int m a+                -> ([Int] -> m a)+                -> Property+checkConsumerM' f c l = forAll arbitrary $ \xs ->+    f (sourceList xs $$ preventFusion c)+    ===+    f (l xs)++checkStreamConsumerM' :: (Show a, Monad m, Show b, Eq b)+                      => (m a -> b)+                      -> StreamConsumer Int m a+                      -> ([Int] -> m a)+                      -> Property+checkStreamConsumerM' f s l = forAll arbitrary $ \xs ->+    f (liftM snd $ evalStream $ s $ sourceListS xs emptyStream)+    ===+    f (l xs)++checkConduitM' :: (Show a, Arbitrary a, Monad m, Show c, Eq c)+               => (m [b] -> c)+               -> Conduit a m b+               -> ([a] -> m [b])+               -> Property+checkConduitM' f c l = forAll arbitrary $ \xs ->+    f (sourceList xs $= preventFusion c $$ consume)+    ===+    f (l xs)++checkStreamConduitM' :: (Show a, Arbitrary a, Monad m, Show c, Eq c)+                     =>  (m [b] -> c)+                     -> StreamConduit a m b+                     -> ([a] -> m [b])+                     -> Property+checkStreamConduitM' f s l = forAll arbitrary $ \xs ->+    f (liftM fst $ evalStream $ s $ sourceListS xs emptyStream)+    ===+    f (l xs)++-- TODO: Fixing this would allow comparing conduit consumers against+-- their list versions.+--+-- checkConduitResultM' :: (Show a, Arbitrary a, Monad m, Show c, Eq c)+--                      => (m ([b], r) -> c)+--                      -> ConduitM a b m r+--                      -> ([a] -> m ([b], r))+--                      -> Property+-- checkConduitResultM' f c l = FIXME forAll arbitrary $ \xs ->+--     f (sourceList xs $= preventFusion c $$ consume)+--     ===+--     f (l xs)++checkStreamConduitResultM' :: (Show a, Arbitrary a, Monad m, Show c, Eq c)+                           =>  (m ([b], r) -> c)+                           -> StreamConduitM a b m r+                           -> ([a] -> m ([b], r))+                           -> Property+checkStreamConduitResultM' f s l = forAll arbitrary $ \xs ->+    f (evalStream $ s $ sourceListS xs emptyStream)+    ===+    f (l xs)++emptyStream :: Monad m => Stream m () ()+emptyStream = Stream (\_ -> return $ Stop ()) (return ())++evalStream :: Monad m => Stream m o r -> m ([o], r)+evalStream (Stream step s0) = go =<< s0+  where+    go s = do+        res <- step s+        case res of+            Stop r -> return ([], r)+            Skip s' -> go s'+            Emit s' x -> liftM (\(l, r) -> (x:l, r)) (go s')++--------------------------------------------------------------------------------+-- Misc utilities++-- Prefer this to creating an orphan instance for Data.Monoid.Sum:++newtype Sum a = Sum a+  deriving (Eq, Show, Arbitrary)++instance Prelude.Num a => Monoid (Sum a) where+  mempty = Sum 0+  mappend (Sum x) (Sum y) = Sum $ x Prelude.+ y++preventFusion :: a -> a+preventFusion = id+{-# INLINE [0] preventFusion #-}++newtype M a = M (StateT Int Identity a)+  deriving (Functor, Applicative, Monad)++instance Arbitrary a => Arbitrary (M a) where+    arbitrary = do+        f <- arbitrary+        return $ do+            s <- M get+            let (x, s') = f s+            M (put s')+            return x++runM :: M a -> (a, Int)+runM (M m) = runIdentity $ runStateT m 0++--------------------------------------------------------------------------------+-- List versions of some functions++iterML :: Monad m => (a -> m ()) -> [a] -> m [a]+iterML f = Prelude.mapM (\a -> f a >>= \() -> return a)++mapMaybeML :: Monad m => (a -> m (Maybe b)) -> [a] -> m [b]+mapMaybeML f = liftM Data.Maybe.catMaybes . Prelude.mapM f++concatMapML :: Monad m => (a -> m [b]) -> [a] -> m [b]+concatMapML f = liftM Prelude.concat . Prelude.mapM f++concatMapAccumL :: (a -> s -> (s, [b])) -> s -> [a] -> [b]+concatMapAccumL f acc0 =+    runIdentity . concatMapAccumML (\a acc -> return $ f a acc) acc0++mapAccumL :: (a -> s -> (s, b)) -> s -> [a] -> ([b], s)+mapAccumL f acc0 =+    runIdentity . mapAccumML (\a acc -> return $ f a acc) acc0++concatMapAccumML :: Monad m => (a -> s -> m (s, [b])) -> s -> [a] -> m [b]+concatMapAccumML f acc0 =+    liftM (Prelude.concat . fst) . mapAccumML f acc0++scanL :: (a -> b -> b) -> b -> [a] -> ([b], b)+scanL f = mapAccumL (\a b -> let r = f a b in (r, r))++scanML :: Monad m => (a -> b -> m b) -> b -> [a] -> m ([b], b)+scanML f = mapAccumML (\a b -> f a b >>= \r -> return (r, r))++mapFoldableL :: F.Foldable f => (a -> f b) -> [a] -> [b]+mapFoldableL f = runIdentity . mapFoldableML (return . f)++mapFoldableML :: (Monad m, F.Foldable f) => (a -> m (f b)) -> [a] -> m [b]+mapFoldableML f = concatMapML (liftM F.toList . f)++groupOn1L :: Eq b => (a -> b) -> [a] -> [(a, [a])]+groupOn1L f =+    Data.List.map (\(x:xs) -> (x, xs)) . Data.List.groupBy ((==) `on` f)++mapAccumML :: Monad m => (a -> s -> m (s, b)) -> s -> [a] -> m ([b], s)+mapAccumML f s0 = go s0+  where+    go s [] = return ([], s)+    go s (x:xs) = do+        (s', r) <- f x s+        liftM (\(l, o) -> (r:l, o)) $ go s' xs++--------------------------------------------------------------------------------+-- Utilities taken from monad-loops package++-- http://hackage.haskell.org/package/monad-loops++-- |See 'Data.List.unfoldr'.  This is a monad-friendly version of that.+unfoldrM :: (Monad m) => (a -> m (Maybe (b,a))) -> a -> m [b]+unfoldrM = unfoldrM'++-- |See 'Data.List.unfoldr'.  This is a monad-friendly version of that, with a+-- twist.  Rather than returning a list, it returns any MonadPlus type of your+-- choice.+unfoldrM' :: (Monad m, MonadPlus f) => (a -> m (Maybe (b,a))) -> a -> m (f b)+unfoldrM' f = go+    where go z = do+            x <- f z+            case x of+                Nothing         -> return mzero+                Just (x', z')   -> do+                        xs <- go z'+                        return (return x' `mplus` xs)
test/main.hs view
@@ -32,6 +32,7 @@ import Control.Monad.Error (catchError, throwError, Error) import qualified Data.Map as Map import qualified Data.Conduit.Extra.ZipConduitSpec as ZipConduit+import qualified Data.Conduit.StreamSpec as Stream  (@=?) :: (Eq a, Show a) => a -> a -> IO () (@=?) = flip shouldBe@@ -943,6 +944,7 @@             res `shouldBe` [1, 3]      ZipConduit.spec+    Stream.spec  it' :: String -> IO () -> Spec it' = it