diff --git a/Data/Conduit/Combinators.hs b/Data/Conduit/Combinators.hs
--- a/Data/Conduit/Combinators.hs
+++ b/Data/Conduit/Combinators.hs
@@ -39,6 +39,12 @@
     , sourceIOHandle
     , stdin
 
+      -- ** Random numbers
+    , sourceRandom
+    , sourceRandomN
+    , sourceRandomGen
+    , sourceRandomNGen
+
       -- * Consumers
       -- ** Pure
     , drop
@@ -78,6 +84,8 @@
     , lastE
     , length
     , lengthE
+    , lengthIf
+    , lengthIfE
     , maximum
     , maximumE
     , minimum
@@ -160,7 +168,7 @@
 import           Control.Monad               (unless, when, (>=>), liftM, forever)
 import           Control.Monad.Base          (MonadBase (liftBase))
 import           Control.Monad.IO.Class      (MonadIO (..))
-import           Control.Monad.Primitive     (PrimMonad)
+import           Control.Monad.Primitive     (PrimMonad, PrimState)
 import           Control.Monad.Trans.Class   (lift)
 import           Data.Conduit
 import qualified Data.Conduit.List           as CL
@@ -185,6 +193,8 @@
 import qualified Data.Conduit.Text as CT
 import Data.ByteString (ByteString)
 import Data.Text (Text)
+import qualified System.Random.MWC as MWC
+import Data.Conduit.Combinators.Internal
 
 -- END IMPORTS
 
@@ -340,6 +350,45 @@
 stdin :: (MonadIO m, IOData a) => Producer m a
 stdin = sourceHandle SIO.stdin
 
+-- | Create an infinite stream of random values, seeding from the system random
+-- number.
+--
+-- Since 1.0.0
+sourceRandom :: (MWC.Variate a, MonadIO m) => Producer m a
+sourceRandom = initRepeat (liftIO MWC.createSystemRandom) (liftIO . MWC.uniform)
+{-# INLINE sourceRandom #-}
+
+-- | Create a stream of random values of length n, seeding from the system
+-- random number.
+--
+-- Since 1.0.0
+sourceRandomN :: (MWC.Variate a, MonadIO m)
+              => Int -- ^ count
+              -> Producer m a
+sourceRandomN = initReplicate (liftIO MWC.createSystemRandom) (liftIO . MWC.uniform)
+{-# INLINE [0] sourceRandomN #-}
+
+-- | Create an infinite stream of random values, using the given random number
+-- generator.
+--
+-- Since 1.0.0
+sourceRandomGen :: (MWC.Variate a, MonadBase base m, PrimMonad base)
+                => MWC.Gen (PrimState base)
+                -> Producer m a
+sourceRandomGen gen = initRepeat (return gen) (liftBase . MWC.uniform)
+{-# INLINE sourceRandomGen #-}
+
+-- | Create a stream of random values of length n, seeding from the system
+-- random number.
+--
+-- Since 1.0.0
+sourceRandomNGen :: (MWC.Variate a, MonadBase base m, PrimMonad base)
+                 => MWC.Gen (PrimState base)
+                 -> Int -- ^ count
+                 -> Producer m a
+sourceRandomNGen gen = initReplicate (return gen) (liftBase . MWC.uniform)
+{-# INLINE sourceRandomNGen #-}
+
 -- | Ignore a certain number of values in the stream.
 --
 -- Since 1.0.0
@@ -774,6 +823,21 @@
 lengthE :: (Monad m, Num len, MonoFoldable mono) => Consumer mono m len
 lengthE = foldl (\x y -> x + fromIntegral (olength y)) 0
 {-# INLINE lengthE #-}
+
+-- | Count how many values in the stream pass the given predicate.
+--
+-- Since 1.0.0
+lengthIf :: (Monad m, Num len) => (a -> Bool) -> Consumer a m len
+lengthIf f = foldl (\cnt a -> if f a then (cnt + 1) else cnt) 0
+{-# INLINE lengthIf #-}
+
+-- | Count how many elements in the chunked stream pass the given predicate.
+--
+-- Since 1.0.0
+lengthIfE :: (Monad m, Num len, MonoFoldable mono)
+          => (Element mono -> Bool) -> Consumer mono m len
+lengthIfE f = foldlE (\cnt a -> if f a then (cnt + 1) else cnt) 0
+{-# INLINE lengthIfE #-}
 
 -- | Get the largest value in the stream, if present.
 --
diff --git a/Data/Conduit/Combinators/Internal.hs b/Data/Conduit/Combinators/Internal.hs
new file mode 100644
--- /dev/null
+++ b/Data/Conduit/Combinators/Internal.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE RankNTypes #-}
+-- | Internal helper functions, usually used for rewrite rules.
+module Data.Conduit.Combinators.Internal
+    ( initReplicate
+    , initReplicateConnect
+    , initRepeat
+    , initRepeatConnect
+    ) where
+
+import Data.Conduit
+import Data.Conduit.Internal (ConduitM (..), Pipe (..), injectLeftovers)
+import Data.Void (absurd)
+import Control.Monad.Trans.Class (lift)
+import Control.Monad (replicateM_, forever)
+
+-- | Acquire the seed value and perform the given action with it n times,
+-- yielding each result.
+--
+-- Since 0.2.1
+initReplicate :: Monad m => m seed -> (seed -> m a) -> Int -> Producer m a
+initReplicate mseed f cnt = do
+    seed <- lift mseed
+    replicateM_ cnt (lift (f seed) >>= yield)
+{-# INLINE [1] initReplicate #-}
+
+-- | Optimized version of initReplicate for the special case of connecting with
+-- a @Sink@.
+--
+-- Since 0.2.1
+initReplicateConnect :: Monad m
+                     => m seed
+                     -> (seed -> m a)
+                     -> Int
+                     -> Sink a m b
+                     -> m b
+initReplicateConnect mseed f cnt0 (ConduitM sink0) = do
+    seed <- mseed
+    let loop cnt sink | cnt <= 0 = finish sink
+        loop _ (Done r) = return r
+        loop cnt (NeedInput p _) = f seed >>= loop (pred cnt) . p
+        loop _ (HaveOutput _ _ o) = absurd o
+        loop cnt (PipeM mp) = mp >>= loop cnt
+        loop _ (Leftover _ i) = absurd i
+
+    loop cnt0 (injectLeftovers sink0)
+  where
+    finish (Done r) = return r
+    finish (HaveOutput _ _ o) = absurd o
+    finish (NeedInput _ p) = finish (p ())
+    finish (PipeM mp) = mp >>= finish
+    finish (Leftover _ i) = absurd i
+{-# RULES "initReplicateConnect" forall mseed f cnt sink.
+    initReplicate mseed f cnt $$ sink
+    = initReplicateConnect mseed f cnt sink
+  #-}
+
+-- | Acquire the seed value and perform the given action with it forever,
+-- yielding each result.
+--
+-- Since 0.2.1
+initRepeat :: Monad m => m seed -> (seed -> m a) -> Producer m a
+initRepeat mseed f = do
+    seed <- lift mseed
+    forever $ lift (f seed) >>= yield
+
+-- | Optimized version of initRepeat for the special case of connecting with
+-- a @Sink@.
+--
+-- Since 0.2.1
+initRepeatConnect :: Monad m
+                  => m seed
+                  -> (seed -> m a)
+                  -> Sink a m b
+                  -> m b
+initRepeatConnect mseed f (ConduitM sink0) = do
+    seed <- mseed
+    let loop (Done r) = return r
+        loop (NeedInput p _) = f seed >>= loop . p
+        loop (HaveOutput _ _ o) = absurd o
+        loop (PipeM mp) = mp >>= loop
+        loop (Leftover _ i) = absurd i
+
+    loop (injectLeftovers sink0)
+{-# RULES "initRepeatConnect" forall mseed f sink.
+    initRepeat mseed f $$ sink
+    = initRepeatConnect mseed f sink
+  #-}
diff --git a/Data/Conduit/Combinators/Unqualified.hs b/Data/Conduit/Combinators/Unqualified.hs
--- a/Data/Conduit/Combinators/Unqualified.hs
+++ b/Data/Conduit/Combinators/Unqualified.hs
@@ -28,6 +28,12 @@
     , sourceIOHandle
     , stdinC
 
+      -- *** Random numbers
+    , sourceRandom
+    , sourceRandomN
+    , sourceRandomGen
+    , sourceRandomNGen
+
       -- ** Consumers
       -- *** Pure
     , dropC
@@ -67,6 +73,8 @@
     , lastCE
     , lengthC
     , lengthCE
+    , lengthIfC
+    , lengthIfCE
     , maximumC
     , maximumCE
     , minimumC
@@ -152,7 +160,7 @@
 import           Control.Monad               (unless, when, (>=>), liftM, forever)
 import           Control.Monad.Base          (MonadBase (liftBase))
 import           Control.Monad.IO.Class      (MonadIO (..))
-import           Control.Monad.Primitive     (PrimMonad)
+import           Control.Monad.Primitive     (PrimMonad, PrimState)
 import           Control.Monad.Trans.Class   (lift)
 import           Data.Conduit
 import qualified Data.Conduit.List           as CL
@@ -177,6 +185,8 @@
 import qualified Data.Conduit.Text as CT
 import Data.ByteString (ByteString)
 import Data.Text (Text)
+import qualified System.Random.MWC as MWC
+import Data.Conduit.Combinators.Internal
 
 
 -- END IMPORTS
@@ -314,6 +324,45 @@
 stdinC = CC.stdin
 {-# INLINE stdinC #-}
 
+-- | Create an infinite stream of random values, seeding from the system random
+-- number.
+--
+-- Since 1.0.0
+sourceRandom :: (MWC.Variate a, MonadIO m) => Producer m a
+sourceRandom = CC.sourceRandom
+{-# INLINE sourceRandom #-}
+
+-- | Create a stream of random values of length n, seeding from the system
+-- random number.
+--
+-- Since 1.0.0
+sourceRandomN :: (MWC.Variate a, MonadIO m)
+              => Int -- ^ count
+              -> Producer m a
+sourceRandomN = CC.sourceRandomN
+{-# INLINE sourceRandomN #-}
+
+-- | Create an infinite stream of random values, using the given random number
+-- generator.
+--
+-- Since 1.0.0
+sourceRandomGen :: (MWC.Variate a, MonadBase base m, PrimMonad base)
+                => MWC.Gen (PrimState base)
+                -> Producer m a
+sourceRandomGen = CC.sourceRandomGen
+{-# INLINE sourceRandomGen #-}
+
+-- | Create a stream of random values of length n, seeding from the system
+-- random number.
+--
+-- Since 1.0.0
+sourceRandomNGen :: (MWC.Variate a, MonadBase base m, PrimMonad base)
+                 => MWC.Gen (PrimState base)
+                 -> Int -- ^ count
+                 -> Producer m a
+sourceRandomNGen = CC.sourceRandomNGen
+{-# INLINE sourceRandomNGen #-}
+
 -- | Ignore a certain number of values in the stream.
 --
 -- Since 1.0.0
@@ -662,6 +711,21 @@
 lengthCE :: (Monad m, Num len, MonoFoldable mono) => Consumer mono m len
 lengthCE = CC.lengthE
 {-# INLINE lengthCE #-}
+
+-- | Count how many values in the stream pass the given predicate.
+--
+-- Since 1.0.0
+lengthIfC :: (Monad m, Num len) => (a -> Bool) -> Consumer a m len
+lengthIfC = CC.lengthIf
+{-# INLINE lengthIfC #-}
+
+-- | Count how many elements in the chunked stream pass the given predicate.
+--
+-- Since 1.0.0
+lengthIfCE :: (Monad m, Num len, MonoFoldable mono)
+          => (Element mono -> Bool) -> Consumer mono m len
+lengthIfCE = CC.lengthIfE
+{-# INLINE lengthIfCE #-}
 
 -- | Get the largest value in the stream, if present.
 --
diff --git a/conduit-combinators.cabal b/conduit-combinators.cabal
--- a/conduit-combinators.cabal
+++ b/conduit-combinators.cabal
@@ -1,5 +1,5 @@
 name:                conduit-combinators
-version:             0.2.0.1
+version:             0.2.1
 synopsis:            Commonly used conduit functions, for both chunked and unchunked data
 description:         Provides a replacement for Data.Conduit.List, as well as a convenient Conduit module.
 homepage:            https://github.com/fpco/conduit-combinators
@@ -14,6 +14,7 @@
 library
   exposed-modules:     Conduit
                        Data.Conduit.Combinators
+                       Data.Conduit.Combinators.Internal
   other-modules:       Data.Conduit.Combinators.Unqualified
   build-depends:       base >= 4 && < 5
                      , chunked-data
@@ -27,6 +28,8 @@
                      , system-filepath
                      , text
                      , bytestring
+                     , void
+                     , mwc-random
 
 test-suite test
   hs-source-dirs: test
@@ -44,6 +47,7 @@
                 , mono-traversable
                 , silently
                 , bytestring
+                , mwc-random
   ghc-options:    -Wall
 
 source-repository head
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -3,6 +3,7 @@
 {-# LANGUAGE ViewPatterns #-}
 {-# OPTIONS_GHC -fno-warn-type-defaults #-}
 import Conduit
+import Data.Conduit.Combinators.Internal
 import Test.Hspec
 import Test.Hspec.QuickCheck
 import BasicPrelude hiding (encodeUtf8)
@@ -23,6 +24,7 @@
 import GHC.IO.Handle (hDuplicateTo)
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Char8 as S8
+import System.Random.MWC (createSystemRandom)
 
 main :: IO ()
 main = hspec $ do
@@ -107,6 +109,20 @@
             hDuplicateTo h IO.stdin
             x <- stdinC $$ foldC
             x `shouldBe` content
+    it "sourceRandom" $ do
+        x <- sourceRandom $$ takeC 100 =$ sumC :: IO Double
+        x `shouldSatisfy` (\y -> y > 10 && y < 90)
+    it "sourceRandomN" $ do
+        x <- sourceRandomN 100 $$ sumC :: IO Double
+        x `shouldSatisfy` (\y -> y > 10 && y < 90)
+    it "sourceRandomGen" $ do
+        gen <- createSystemRandom
+        x <- sourceRandomGen gen $$ takeC 100 =$ sumC :: IO Double
+        x `shouldSatisfy` (\y -> y > 10 && y < 90)
+    it "sourceRandomNGen" $ do
+        gen <- createSystemRandom
+        x <- sourceRandomNGen gen 100 $$ sumC :: IO Double
+        x `shouldSatisfy` (\y -> y > 10 && y < 90)
     prop "drop" $ \(T.pack -> input) count ->
         runIdentity (yieldMany input $$ (dropC count >>= \() -> sinkList))
         `shouldBe` T.unpack (T.drop count input)
@@ -215,6 +231,12 @@
     prop "lengthE" $ \xs ->
         runIdentity (yieldMany xs $$ lengthCE)
         `shouldBe` length (concat xs :: [Int])
+    prop "lengthIf" $ \x xs ->
+        runIdentity (yieldMany xs $$ lengthIfC (< x))
+        `shouldBe` length (filter (< x) xs :: [Int])
+    prop "lengthIfE" $ \x xs ->
+        runIdentity (yieldMany xs $$ lengthIfCE (< x))
+        `shouldBe` length (filter (< x) (concat xs) :: [Int])
     prop "maximum" $ \xs ->
         runIdentity (yieldMany xs $$ maximumC)
         `shouldBe` (if null (xs :: [Int]) then Nothing else Just (maximum xs))
@@ -491,6 +513,18 @@
     prop "linesUnboundedAscii" $ \(map S.pack -> input) ->
         runIdentity (yieldMany input $$ (linesUnboundedAsciiC >>= \() -> mempty) =$ sinkList)
         `shouldBe` S8.lines (S.concat input)
+    prop "initReplicate" $ \seed delta (min 50 . abs -> cnt) -> do
+        let sink = sumC
+        res1 <- initReplicate (return seed) (return . (+ delta)) cnt $$ sink
+        res1 `shouldBe` cnt * (seed + delta)
+        res2 <- initReplicateConnect (return seed) (return . (+ delta)) cnt sink
+        res2 `shouldBe` res1
+    prop "initReplicate" $ \seed delta (min 50 . abs -> cnt) -> do
+        let sink = takeC cnt =$ sumC
+        res1 <- initRepeat (return seed) (return . (+ delta)) $$ sink
+        res1 `shouldBe` cnt * (seed + delta)
+        res2 <- initRepeatConnect (return seed) (return . (+ delta)) sink
+        res2 `shouldBe` res1
 
 evenInt :: Int -> Bool
 evenInt = even
