diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Revision history for Churros
 
+## 0.1.4.0 -- 2020-10-18
+
+* Generalising list type to Foldable/Traversible where possible (`sources`).
+* Additional documentation
+* Underscore variants of prelude function that specialise Async action to `()`.
+
 ## 0.1.3.0 -- 2020-10-17
 
 * Generalised functions to have Monoid for Async action result.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@
 * Type for the async action restricted to Monoid for most operations.
 * Limited ability to perform lock-step computation (although this is by design)
 
-See [Hackage](https://hackage.haskell.org/package/churros-0.1.0.0/candidate) for more info!
+See [Hackage](https://hackage.haskell.org/package/churros) for more info!
 
 ## Examples
 
@@ -50,8 +50,8 @@
 import Control.Churro
 
 main = do
-   runWaitChan        $ sourceList [1..10] >>> processDebug "after source" >>> delay 1 {- seconds -} >>> arr succ >>> sinkPrint
-   wait =<< run @Chan $ sourceIO (\cb -> cb 1 >> print "Doing whatever!" >> cb 5) >>> filterC (> 3) >>> sinkIO print
+   runWaitChan             $ sourceList [1..10] >>> processDebug "after source" >>> delay 1 {- seconds -} >>> arr succ >>> sinkPrint
+   (wait =<<)  $ run @Chan $ sourceIO (\cb -> cb 1 >> print "Doing whatever!" >> cb 5) >>> filterC (> 3) >>> sinkIO print
 ```
 
 ## Testing
diff --git a/churros.cabal b/churros.cabal
--- a/churros.cabal
+++ b/churros.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.2
 name:                churros
-version:             0.1.3.0
+version:             0.1.4.0
 license-file:        LICENSE
 author:              Lyndon Maydwell
 maintainer:          lyndon@sordina.net
diff --git a/src/Control/Churro/Prelude.hs b/src/Control/Churro/Prelude.hs
--- a/src/Control/Churro/Prelude.hs
+++ b/src/Control/Churro/Prelude.hs
@@ -5,6 +5,13 @@
 
 -- | Common transport-agnostic functions for using Churro.
 -- 
+-- Variants with a trailing underscore - E.g. `runWait_` specialised the Async action to
+-- be () if you don't care about accumulating results and only processing items as they
+-- pass through the pipeline.
+-- 
+-- Variants with a trailing prime - E.g. `processRetry'`. also change the generality of the
+-- types involved in some way.
+-- 
 module Control.Churro.Prelude where
 
 import Control.Churro.Types
@@ -14,10 +21,10 @@
 import           Control.Arrow            (arr)
 import           Control.Category         (id, (.), (>>>))
 import           Control.Concurrent       (threadDelay)
-import           Control.Concurrent.Async (waitAny, Async, wait)
+import           Control.Concurrent.Async (cancel, Async, wait)
 import           Control.Exception        (Exception, SomeException, try)
 import           Control.Monad            (replicateM_, when)
-import           Data.Foldable            (for_)
+import           Data.Foldable            (toList, for_)
 import           Data.Maybe               (isJust)
 import           Data.Time                (NominalDiffTime)
 import           Data.Void                (Void)
@@ -40,6 +47,11 @@
 runWait :: Transport t => Churro a t Void Void -> IO a
 runWait x = wait =<< run x
 
+-- | Version of `runWait` specialised to `()`.
+-- 
+runWait_ :: Transport t => Churro () t Void Void -> IO ()
+runWait_ = runWait
+
 -- | Read the output of a Churro into a list.
 -- 
 -- Warning: This will block until the Churro terminates,
@@ -53,11 +65,21 @@
 runWaitList :: (Transport t, Monoid a) => Churro a t Void b -> IO [b]
 runWaitList c = runWait $ (c >>> arr' (:[])) >>>> sink 
 
+-- | Version of `runWaitList` specialised to `()`.
+-- 
+runWaitList_ :: Transport t => Churro () t Void b -> IO [b]
+runWaitList_ = runWaitList
+
 -- | Run a sourced and sinked (double-dipped) churro and return an async action representing the in-flight processes.
 --
 run :: Transport t => Churro a t Void Void -> IO (Async a)
 run = run'
 
+-- | Version of `run` with async return type specialised to `()`.
+--
+run_ :: Transport t => Churro () t Void Void -> IO (Async ())
+run_ = run'
+
 -- | Run any churro, there is no check that this was spawned with a source, or terminated with a sink.
 --   This is unsafe, since the pipeline may not generate or consume in a predictable way.
 --   Use `run` instead unless you are confident you know what you're doing.
@@ -103,6 +125,11 @@
         yeet o Nothing
         return r
 
+-- | Variant of `sourceIO` with Async action specialised to `()`.
+-- 
+sourceIO_ :: Transport t => ((o -> IO ()) -> IO ()) -> Churro () t Void o
+sourceIO_ = sourceIO
+
 -- | Combine a list of sources into a single source.
 -- 
 -- Sends individual items downstream without attempting to combine them.
@@ -114,18 +141,29 @@
 -- >>> runWaitChan $ sources_ [pure 1, pure 1] >>> sinkPrint
 -- 1
 -- 1
-sources :: (Transport t, Monoid a) => [Source a t o] -> Source () t o
+sources :: (Transport t, Foldable f, Traversable f) => f (Churro a t Void i) -> Churro () t Void i
 sources ss = sourceIO \cb -> do
     asyncs <- mapM (\s -> run $ s >>>> sinkIO cb) ss
-    (_, r) <- waitAny asyncs
-    return r
+    let as = toList asyncs
+    finally' (mapM_ cancel as) do
+        mapM_ wait as
 
--- | This is `sources` specialised to `()`.
+-- | Variant of `sources` with Async action of sources in argument specialised to `()`.
+-- 
 sources_ :: Transport t => [Source () t o] -> Source () t o
 sources_ = sources
 
 -- ** Sinks
 
+-- | Consume all items and combines them into a result via their monoid.
+-- 
+-- >>> :set -XFlexibleContexts
+-- >>> r <- runWaitChan $ pure' [1 :: Int] >>> sink
+-- >>> print r
+-- [1]
+sink :: (Transport t, Monoid a) => Churro a t a Void
+sink = sinkIO return
+
 -- | Consume all items with no additional effects.
 -- 
 -- TODO: Decide if we should use some kind of `nf` evaluation here to force items.
@@ -136,15 +174,6 @@
 sink_ :: Transport t => Churro () t i Void
 sink_ = sinkIO (const (return ()))
 
--- | Consume all items and combines them into a result via their monoid.
--- 
--- >>> :set -XFlexibleContexts
--- >>> r <- runWaitChan $ pure' [1 :: Int] >>> sink
--- >>> print r
--- [1]
-sink :: (Transport t, Monoid a) => Churro a t a Void
-sink = sinkIO return
-
 -- | Consume a churro with an IO process.
 -- 
 -- >>> runWaitChan $ pure 1 >>> sinkIO (\x -> print "hello" >> print (succ x))
@@ -152,6 +181,11 @@
 -- 2
 sinkIO :: (Transport t, Monoid a) => (o -> IO a) -> Churro a t o Void
 sinkIO cb = buildChurro \i _o -> yankAll i cb
+
+-- | Variant of `sinkIO` with Async action specialised to `()`.
+-- 
+sinkIO_ :: Transport t => (o -> IO ()) -> Churro () t o Void
+sinkIO_ cb = buildChurro \i _o -> yankAll i cb
 
 -- | Create a "sink" with more flexibility about when items are demanded using a higher-order "HO" callback.
 -- 
diff --git a/src/Control/Churro/Types.hs b/src/Control/Churro/Types.hs
--- a/src/Control/Churro/Types.hs
+++ b/src/Control/Churro/Types.hs
@@ -40,10 +40,10 @@
 -- Convenience types of `Source`, `Sink`, and `DoubleDipped` are also defined,
 -- although use is not required.
 -- 
-data Churro a t i o   = Churro { runChurro :: IO (In t (Maybe i), Out t (Maybe o), Async a) }
-type Source a t   o   = Churro a t Void o
-type Sink   a t i     = Churro a t i Void
-type DoubleDipped a t = Churro a t Void Void
+newtype Churro a t i o   = Churro { runChurro :: IO (In t (Maybe i), Out t (Maybe o), Async a) }
+type    Source a t   o   = Churro a t Void o
+type    Sink   a t i     = Churro a t i Void
+type    DoubleDipped a t = Churro a t Void Void
 
 -- | The transport method is abstracted via the Transport class
 -- 
@@ -128,9 +128,9 @@
 -- 
 --  The `pure` method allows for the creation of a Churro yielding a single item.
 -- 
--- TODO: Generalise () to a Monoid constraint.
+-- TODO: Write test to check Monoid return type.
 -- 
-instance Transport t => Applicative (Churro () t Void) where
+instance (Transport t, Monoid a) => Applicative (Churro a t Void) where
     pure = pure'
 
     f <*> g = buildChurro \_i o -> do
@@ -188,7 +188,10 @@
 -- 
 -- >>> runWaitChan $ pure 1 >>> (arr show &&& arr succ) >>> sinkPrint
 -- ("1",2)
-instance Transport t => Arrow (Churro () t) where
+-- 
+-- TODO: Write tests to check if the monoid return type is implemented correctly.
+-- 
+instance (Transport t, Monoid a) => Arrow (Churro a t) where
     arr = arr'
 
     first c = Churro do
@@ -240,7 +243,9 @@
     a       <- async do cb ai ao bi
     return (ai,bo,a)
 
--- | Yeet all items from a list into a transport.
+-- | Yeet all items from a list into a raw transport.
+-- 
+-- WARNING: If you are using this to build a churro by hand make sure you yeet Nothing once you're finished.
 -- 
 yeetList :: (Foldable f, Transport t) => In t a -> f a -> IO ()
 yeetList t = mapM_ (yeet t)
diff --git a/test/Churro/Test/Examples.hs b/test/Churro/Test/Examples.hs
--- a/test/Churro/Test/Examples.hs
+++ b/test/Churro/Test/Examples.hs
@@ -15,6 +15,8 @@
 import Prelude hiding (id, (.))
 
 import Control.Churro
+import Control.Concurrent.Async (wait)
+import Control.Concurrent (Chan)
 
 -- $setup
 -- 
@@ -23,6 +25,14 @@
 -- >>> import Control.Concurrent (threadDelay)
 
 -- ** Tests
+
+-- | Example from readme:
+-- 
+-- No need to run it, just typecheck it.
+readme :: IO ()
+readme = do
+    runWaitChan             $ sourceList [1::Int ..10] >>> processDebug "after source" >>> delay 1 {- seconds -} >>> arr succ >>> sinkPrint
+    (wait =<<)  $ run @Chan $ sourceIO (\cb -> cb (1::Int) >> print "Doing whatever!" >> cb 5) >>> filterC (> 3) >>> sinkIO print
 
 -- | Checks that the IO nature of the churros doesn't duplicate operations.
 --   Actions within a pipeline should only occur once no matter how the
