diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -12,10 +12,21 @@
 *.hi
 *~
 *#
-.cabal-sandbox
+.stack-work/
+cabal-dev
+*.chi
+*.chs.h
+*.dyn_o
+*.dyn_hi
+.hpc
+.hsenv
+.cabal-sandbox/
 cabal.sandbox.config
 *.prof
 *.aux
 *.hp
 *.eventlog
-.stack-work/
+cabal.project.local
+cabal.project.local~
+.HTF/
+.ghc.environment.*
diff --git a/.travis.yml b/.travis.yml
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,115 +1,162 @@
-# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
+# This Travis job script has been generated by a script via
+#
+#   runghc make_travis_yml_2.hs '-o' '.travis.yml' '--ghc-head' '--irc-channel=irc.freenode.org#haskell-lens' '--no-no-tests-no-bench' '--no-unconstrained' 'cabal.project'
+#
+# For more information, see https://github.com/hvr/multi-ghc-travis
+#
 language: c
 sudo: false
 
+git:
+  submodules: false  # whether to recursively clone submodules
+
+notifications:
+  irc:
+    channels:
+      - "irc.freenode.org#haskell-lens"
+    skip_join: true
+    template:
+      - "\x0313machines\x03/\x0306%{branch}\x03 \x0314%{commit}\x03 %{build_url} %{message}"
+
 cache:
   directories:
-    - $HOME/.cabsnap
     - $HOME/.cabal/packages
+    - $HOME/.cabal/store
 
 before_cache:
   - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
+  # remove files that are regenerated by 'cabal update'
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.*
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.cache
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar
+  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx
 
+  - rm -rfv $HOME/.cabal/packages/head.hackage
+
 matrix:
   include:
-    - env: CABALVER=1.24 GHCVER=7.4.2
-      compiler: ": #GHC 7.4.2"
-      addons: {apt: {packages: [cabal-install-1.24,ghc-7.4.2], sources: [hvr-ghc]}}
-    - env: CABALVER=1.24 GHCVER=7.6.3
-      compiler: ": #GHC 7.6.3"
-      addons: {apt: {packages: [cabal-install-1.24,ghc-7.6.3], sources: [hvr-ghc]}}
-    - env: CABALVER=1.24 GHCVER=7.8.4
-      compiler: ": #GHC 7.8.4"
-      addons: {apt: {packages: [cabal-install-1.24,ghc-7.8.4], sources: [hvr-ghc]}}
-    - env: CABALVER=1.24 GHCVER=7.10.3
-      compiler: ": #GHC 7.10.3"
-      addons: {apt: {packages: [cabal-install-1.24,ghc-7.10.3], sources: [hvr-ghc]}}
-    - env: CABALVER=1.24 GHCVER=8.0.2
-      compiler: ": #GHC 8.0.2"
-      addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2], sources: [hvr-ghc]}}
-    - env: CABALVER=2.0 GHCVER=8.2.1
-      compiler: ": #GHC 8.2.1"
-      addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.1], sources: [hvr-ghc]}}
-    - env: CABALVER=head GHCVER=head
-      compiler: ": #GHC head"
-      addons: {apt: {packages: [cabal-install-head,ghc-head], sources: [hvr-ghc]}}
+    - compiler: "ghc-8.6.1"
+      env: GHCHEAD=true
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.6.1], sources: [hvr-ghc]}}
+    - compiler: "ghc-8.4.3"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-8.4.3], sources: [hvr-ghc]}}
+    - compiler: "ghc-8.2.2"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-8.2.2], sources: [hvr-ghc]}}
+    - compiler: "ghc-8.0.2"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-8.0.2], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.10.3"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-7.10.3], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.8.4"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-7.8.4], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.6.3"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-7.6.3], sources: [hvr-ghc]}}
+    - compiler: "ghc-7.4.2"
+    # env: TEST=--disable-tests BENCH=--disable-benchmarks
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-7.4.2], sources: [hvr-ghc]}}
+    - compiler: "ghc-head"
+      env: GHCHEAD=true
+      addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-head], sources: [hvr-ghc]}}
 
   allow_failures:
-    - env: CABALVER=head GHCVER=head
+    - compiler: "ghc-head"
+    - compiler: "ghc-8.6.1"
 
 before_install:
- - unset CC
- - export PATH=$HOME/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
+  - HC=${CC}
+  - HCVER=${HC/ghc-/}
+  - HCPKG=${HC/ghc/ghc-pkg}
+  - unset CC
+  - ROOTDIR=$(pwd)
+  - mkdir -p $HOME/.local/bin
+  - "PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$HOME/local/bin:$PATH"
+  - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))
+  - echo $HCNUMVER
 
 install:
- - cabal --version
- - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
- - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
-   then
-     zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
-          $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
-   fi
- - travis_retry cabal update -v
- - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
- - cabal install --only-dependencies --enable-tests --dry -v > installplan.txt
- - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
-
-# check whether current requested install-plan matches cached package-db snapshot
- - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;
-   then
-     echo "cabal build-cache HIT";
-     rm -rfv .ghc;
-     cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
-     cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
-   else
-     echo "cabal build-cache MISS";
-     rm -rf $HOME/.cabsnap;
-     mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
-     cabal install -j --only-dependencies --enable-tests;
-   fi
+  - cabal --version
+  - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
+  - |
+    if dpkg --compare-versions "${HCVER}" ge "8.0"; then
+      BENCH=${BENCH---enable-benchmarks}
+    else
+      BENCH=${BENCH---disable-benchmarks}
+    fi
+  - TEST=${TEST---enable-tests}
+  - HADDOCK=${HADDOCK-true}
+  - UNCONSTRAINED=${UNCONSTRAINED-true}
+  - NOINSTALLEDCONSTRAINTS=${NOINSTALLEDCONSTRAINTS-false}
+  - GHCHEAD=${GHCHEAD-false}
+  - travis_retry cabal update -v
+  - "sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config"
+  - rm -fv cabal.project cabal.project.local
+  # Overlay Hackage Package Index for GHC HEAD: https://github.com/hvr/head.hackage
+  - |
+    if $GHCHEAD; then
+      sed -i 's/-- allow-newer: .*/allow-newer: *:base/' ${HOME}/.cabal/config
+      for pkg in $($HCPKG list --simple-output); do pkg=$(echo $pkg | sed 's/-[^-]*$//'); sed -i "s/allow-newer: /allow-newer: *:$pkg, /" ${HOME}/.cabal/config; done
 
-# snapshot package-db on cache miss
- - if [ ! -d $HOME/.cabsnap ];
-   then
-      echo "snapshotting package-db to build-cache";
-      mkdir $HOME/.cabsnap;
-      cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
-      cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
-   fi
+      echo 'repository head.hackage'                                                        >> ${HOME}/.cabal/config
+      echo '   url: http://head.hackage.haskell.org/'                                       >> ${HOME}/.cabal/config
+      echo '   secure: True'                                                                >> ${HOME}/.cabal/config
+      echo '   root-keys: 07c59cb65787dedfaef5bd5f987ceb5f7e5ebf88b904bbd4c5cbdeb2ff71b740' >> ${HOME}/.cabal/config
+      echo '              2e8555dde16ebd8df076f1a8ef13b8f14c66bad8eafefd7d9e37d0ed711821fb' >> ${HOME}/.cabal/config
+      echo '              8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e' >> ${HOME}/.cabal/config
+      echo '   key-threshold: 3'                                                            >> ${HOME}/.cabal.config
 
-# Here starts the actual work to be performed for the package under
-# test; any command which exits with a non-zero exit code causes the
-# build to fail.
-script:
- # -v2 provides useful information for debugging
- - cabal configure --enable-tests -v2
+      grep -Ev -- '^\s*--' ${HOME}/.cabal/config | grep -Ev '^\s*$'
 
- # this builds all libraries and executables
- # (including tests/benchmarks)
- - cabal build
+      cabal new-update head.hackage -v
+    fi
+  - grep -Ev -- '^\s*--' ${HOME}/.cabal/config | grep -Ev '^\s*$'
+  - "printf 'packages: \".\" \"./examples\"\\n' > cabal.project"
+  - touch cabal.project.local
+  - "if ! $NOINSTALLEDCONSTRAINTS; then for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/^/constraints: /' | sed 's/-[^-]*$/ installed/' >> cabal.project.local; done; fi"
+  - cat cabal.project || true
+  - cat cabal.project.local || true
+  - if [ -f "./configure.ac" ]; then
+      (cd "." && autoreconf -i);
+    fi
+  - if [ -f "./examples/configure.ac" ]; then
+      (cd "./examples" && autoreconf -i);
+    fi
+  - rm -f cabal.project.freeze
+  - cabal new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project" --dep -j2 all
+  - rm -rf .ghc.environment.* "."/dist "./examples"/dist
+  - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
 
- - cabal test
+# Here starts the actual work to be performed for the package under test;
+# any command which exits with a non-zero exit code causes the build to fail.
+script:
+  # test that source-distributions can be generated
+  - (cd "." && cabal sdist)
+  - (cd "./examples" && cabal sdist)
+  - mv "."/dist/machines-*.tar.gz "./examples"/dist/machines-examples-*.tar.gz ${DISTDIR}/
+  - cd ${DISTDIR} || false
+  - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;
+  - "printf 'packages: machines-*/*.cabal machines-examples-*/*.cabal\\n' > cabal.project"
+  - touch cabal.project.local
+  - "if ! $NOINSTALLEDCONSTRAINTS; then for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/^/constraints: /' | sed 's/-[^-]*$/ installed/' >> cabal.project.local; done; fi"
+  - cat cabal.project || true
+  - cat cabal.project.local || true
 
- # tests that a source-distribution can be generated
- - cabal sdist
+  # build & run tests, build benchmarks
+  - cabal new-build -w ${HC} ${TEST} ${BENCH} all
+  - if [ "x$TEST" = "x--enable-tests" ]; then cabal new-test -w ${HC} ${TEST} ${BENCH} all; fi
 
- # check that the generated source-distribution can be built & installed
- - export SRC_TGZ=$(cabal info . | awk '{print $2 ".tar.gz";exit}') ;
-   cd dist/;
-   if [ -f "$SRC_TGZ" ]; then
-      cabal install --force-reinstalls "$SRC_TGZ";
-   else
-      echo "expected '$SRC_TGZ' not found";
-      exit 1;
-   fi
+  # cabal check
+  - (cd machines-* && cabal check)
+  - (cd machines-examples-* && cabal check)
 
-notifications:
-  irc:
-    channels:
-      - "irc.freenode.org#haskell-lens"
-    skip_join: true
-    template:
-      - "\x0313machines\x03/\x0306%{branch}\x03 \x0314%{commit}\x03 %{build_url} %{message}"
+  # haddock
+  - rm -rf ./dist-newstyle
+  - if $HADDOCK; then cabal new-haddock -w ${HC} ${TEST} ${BENCH} all; else echo "Skipping haddock generation";fi
 
+# REGENDATA ["-o",".travis.yml","--ghc-head","--irc-channel=irc.freenode.org#haskell-lens","--no-no-tests-no-bench","--no-unconstrained","cabal.project"]
 # EOF
diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,11 @@
+0.6.4 [2018.07.03]
+------------------
+* Add `Semigroup` and `Monoid` instances for `Mealy` and `MealyT`.
+* Mark `runT` and `runT_` as `INLINEABLE`.
+* Increase the scope of the benchmarks. Also include the `streaming` library
+  among the things that are benchmarked.
+* Allow building with `containers-0.6`.
+
 0.6.3
 -----
 * Add `Semigroup` instance for `Is`
diff --git a/benchmarks/Benchmarks.hs b/benchmarks/Benchmarks.hs
--- a/benchmarks/Benchmarks.hs
+++ b/benchmarks/Benchmarks.hs
@@ -1,15 +1,18 @@
 module Main (main) where
 
 import Control.Applicative
+import Data.Function ((&))
 import Control.Monad (void)
 import Control.Monad.Identity
 import Criterion.Main
+import Data.Void
 import qualified Data.Conduit      as C
 import qualified Data.Conduit.Combinators as CC
 import qualified Data.Conduit.List as C
 import qualified Data.Machine      as M
 import qualified Pipes             as P
 import qualified Pipes.Prelude     as P
+import qualified Streaming.Prelude as S
 import Prelude
 
 value :: Int
@@ -18,85 +21,285 @@
 drainM :: M.ProcessT Identity Int o -> ()
 drainM m = runIdentity $ M.runT_ (sourceM M.~> m)
 
+drainMIO :: M.ProcessT IO Int o -> IO ()
+drainMIO m = M.runT_ (sourceM M.~> m)
+
 drainP :: P.Proxy () Int () a Identity () -> ()
 drainP p = runIdentity $ P.runEffect $ P.for (sourceP P.>-> p) P.discard
 
-drainC :: C.Conduit Int Identity a -> ()
-drainC c = runIdentity $ (sourceC C.$= c) C.$$ C.sinkNull
+drainPIO :: P.Proxy () Int () a IO () -> IO ()
+drainPIO p = P.runEffect $ sourceP P.>-> p P.>-> P.mapM_ (\_ -> return ())
 
-drainSC :: C.Sink Int Identity b -> ()
-drainSC c = runIdentity $ void $! sourceC C.$$ c
+drainC :: C.ConduitT Int a Identity () -> ()
+drainC c = runIdentity $ C.runConduit $ (sourceC C..| c) C..| C.sinkNull
 
+drainCIO :: C.ConduitT Int a IO () -> IO ()
+drainCIO c = C.runConduit $ (sourceC C..| c) C..| C.mapM_ (\_ -> return ())
+
+drainSC :: C.ConduitT Int Void Identity b -> ()
+drainSC c = runIdentity $ void $! C.runConduit $ sourceC C..| c
+
+drainS :: (S.Stream (S.Of Int) Identity () -> S.Stream (S.Of Int) Identity ())
+    -> ()
+drainS s = runIdentity $ S.effects $ sourceS & s
+
+drainSIO :: (S.Stream (S.Of Int) IO () -> S.Stream (S.Of Int) IO ()) -> IO ()
+drainSIO s = sourceS & s & S.mapM_ (\_ -> return ())
+
+sourceM :: M.Source Int
 sourceM = M.enumerateFromTo 1 value
+
+sourceC :: Monad m => C.ConduitT i Int m ()
 sourceC = C.enumFromTo 1 value
+
+sourceP :: Monad m => P.Producer' Int m ()
 sourceP = P.each [1..value]
 
+sourceS :: Monad m => S.Stream (S.Of Int) m ()
+sourceS = S.each [1..value]
+
 main :: IO ()
 main =
   defaultMain
   [ bgroup "map"
       [ bench "machines" $ whnf drainM (M.mapping (+1))
+      , bench "streaming" $ whnf drainS (S.map (+1))
       , bench "pipes" $ whnf drainP (P.map (+1))
       , bench "conduit" $ whnf drainC (C.map (+1))
       ]
   , bgroup "drop"
       [ bench "machines" $ whnf drainM (M.dropping value)
+      , bench "streaming" $ whnf drainS (S.drop value)
       , bench "pipes" $ whnf drainP (P.drop value)
       , bench "conduit" $ whnf drainC (C.drop value)
       ]
   , bgroup "dropWhile"
       [ bench "machines" $ whnf drainM (M.droppingWhile (<= value))
+      , bench "streaming" $ whnf drainS (S.dropWhile (<= value))
       , bench "pipes" $ whnf drainP (P.dropWhile (<= value))
       , bench "conduit" $ whnf drainC (CC.dropWhile (<= value))
       ]
   , bgroup "scan"
       [ bench "machines" $ whnf drainM (M.scan (+) 0)
+      , bench "streaming" $ whnf drainS (S.scan (+) 0 id)
       , bench "pipes" $ whnf drainP (P.scan (+) 0 id)
       , bench "conduit" $ whnf drainC (CC.scanl (+) 0)
       ]
   , bgroup "take"
       [ bench "machines" $ whnf drainM (M.taking value)
+      , bench "streaming" $ whnf drainS (S.take value)
       , bench "pipes" $ whnf drainP (P.take value)
       , bench "conduit" $ whnf drainC (C.isolate value)
       ]
   , bgroup "takeWhile"
       [ bench "machines" $ whnf drainM (M.takingWhile (<= value))
+      , bench "streaming" $ whnf drainS (S.takeWhile (<= value))
       , bench "pipes" $ whnf drainP (P.takeWhile (<= value))
       , bench "conduit" $ whnf drainC (CC.takeWhile (<= value))
       ]
   , bgroup "fold"
       [ bench "machines" $ whnf drainM (M.fold (+) 0)
-      , bench "pipes" $ whnf (P.fold (+) 0 id) sourceP
+      , bench "streaming" $ whnf runIdentity $ (S.fold (+) 0 id) sourceS
+      , bench "pipes" $ whnf runIdentity $ (P.fold (+) 0 id) sourceP
       , bench "conduit" $ whnf drainSC (C.fold (+) 0)
       ]
   , bgroup "filter"
       [ bench "machines" $ whnf drainM (M.filtered even)
+      , bench "streaming" $ whnf drainS (S.filter even)
       , bench "pipes" $ whnf drainP (P.filter even)
       , bench "conduit" $ whnf drainC (C.filter even)
       ]
   , bgroup "mapM"
       [ bench "machines" $ whnf drainM (M.autoM Identity)
+      , bench "streaming" $ whnf drainS (S.mapM Identity)
       , bench "pipes" $ whnf drainP (P.mapM Identity)
       , bench "conduit" $ whnf drainC (C.mapM Identity)
       ]
   , bgroup "zip"
       [ bench "machines" $ whnf (\x -> runIdentity $ M.runT_ x)
           (M.capT sourceM sourceM M.zipping)
+      , bench "streaming" $ whnf (\x -> runIdentity $ S.effects $ x)
+          (S.zip sourceS sourceS)
       , bench "pipes" $ whnf (\x -> runIdentity $ P.runEffect $ P.for x P.discard)
           (P.zip sourceP sourceP)
-      , bench "conduit" $ whnf (\x -> runIdentity $ x C.$$ C.sinkNull)
+      , bench "conduit" $ whnf (\x -> runIdentity $ C.runConduit $ x C..| C.sinkNull)
           (C.getZipSource $ (,) <$> C.ZipSource sourceC <*> C.ZipSource sourceC)
       ]
+  , bgroup "concat"
+      [ bench "machines" $ whnf drainM (M.mapping (replicate 10) M.~> M.asParts)
+      , bench "streaming" $ whnf drainS (S.concat . S.map (replicate 10))
+      , bench "pipes" $ whnf drainP (P.map (replicate 10) P.>-> P.concat)
+      , bench "conduit" $ whnf drainC (C.map (replicate 10) C..| C.concat)
+      ]
   , bgroup "last"
       [ bench "machines" $ whnf drainM (M.final)
-      , bench "pipes" $ whnf P.last sourceP
+      , bench "streaming" $ whnf runIdentity $ S.last sourceS
+      , bench "pipes" $ whnf runIdentity $ P.last sourceP
       ]
   , bgroup "buffered"
       [ bench "machines" $ whnf drainM (M.buffered 1000)
       ]
-  , bgroup "concat"
-      [ bench "machines" $ whnf drainM (M.mapping (replicate 10) M.~> M.asParts)
-      , bench "pipes" $ whnf drainP (P.map (replicate 10) P.>-> P.concat)
-      , bench "conduit" $ whnf drainC (C.map (replicate 10) C.$= C.concat)
+  , bgroup "toList"
+      [ bench "machines"  $ whnf (length . runIdentity) $ M.runT sourceM
+      , bench "streaming" $ whnf (length . runIdentity)
+                          $ S.toList sourceS >>= (\(xs S.:> _) -> return xs)
+      , bench "pipes"     $ whnf (length . runIdentity) $ P.toListM sourceP
+      , bench "conduit"   $ whnf (length . runIdentity)
+                          $ C.runConduit $ sourceC C..| CC.sinkList
+      ]
+  , bgroup "toListIO"
+      [ bench "machines"  $ whnfIO $ M.runT sourceM
+      , bench "streaming" $ whnfIO $ S.toList sourceS
+      , bench "pipes"     $ whnfIO $ P.toListM sourceP
+      , bench "conduit"   $ whnfIO $ C.runConduit $ sourceC C..| CC.sinkList
+      ]
+
+  , bgroup "compose"
+      [
+      -- Compose multiple ops, all stages letting everything through
+        let m = M.filtered (<= value)
+            s = S.filter (<= value)
+            p = P.filter (<= value)
+            c = C.filter (<= value)
+        in bgroup "summary"
+          [ bench "machines"  $ whnf drainM $ m M.~> m M.~> m M.~> m
+          , bench "streaming" $ whnf drainS $ \x -> s x & s & s & s
+          , bench "pipes"     $ whnf drainP $ p P.>-> p P.>-> p P.>-> p
+          , bench "conduit"   $ whnf drainC $ c C..| c C..| c C..| c
+          ]
+
+      -- IO monad makes a big difference especially for machines
+      , let m = M.filtered (<= value)
+            s = S.filter (<= value)
+            p = P.filter (<= value)
+            c = C.filter (<= value)
+        in bgroup "summary-io"
+          [ bench "machines"  $ whnfIO $ drainMIO $ m M.~> m M.~> m M.~> m
+          , bench "streaming" $ whnfIO $ drainSIO $ \x -> s x & s & s & s
+          , bench "pipes"     $ whnfIO $ drainPIO $ p P.>-> p P.>-> p P.>-> p
+          , bench "conduit"   $ whnfIO $ drainCIO $ c C..| c C..| c C..| c
+          ]
+
+      -- Scaling with same operation in sequence
+      , let f = M.filtered (<= value)
+        in bgroup "machines"
+          [ bench "1-filter" $ whnf drainM f
+          , bench "2-filters" $ whnf drainM $ f M.~> f
+          , bench "3-filters" $ whnf drainM $ f M.~> f M.~> f
+          , bench "4-filters" $ whnf drainM $ f M.~> f M.~> f M.~> f
+          ]
+      , let f = S.filter (<= value)
+        in bgroup "streaming"
+          [ bench "1-filter" $ whnf drainS (\x -> f x)
+          , bench "2-filters" $ whnf drainS $ \x -> f x & f
+          , bench "3-filters" $ whnf drainS $ \x -> f x & f & f
+          , bench "4-filters" $ whnf drainS $ \x -> f x & f & f & f
+          ]
+      , let f = P.filter (<= value)
+        in bgroup "pipes"
+          [ bench "1-filter" $ whnf drainP f
+          , bench "2-filters" $ whnf drainP $ f P.>-> f
+          , bench "3-filters" $ whnf drainP $ f P.>-> f P.>-> f
+          , bench "4-filters" $ whnf drainP $ f P.>-> f P.>-> f P.>-> f
+          ]
+      , let f = C.filter (<= value)
+        in bgroup "conduit"
+          [ bench "1-filter" $ whnf drainC f
+          , bench "2-filters" $ whnf drainC $ f C..| f
+          , bench "3-filters" $ whnf drainC $ f C..| f C..| f
+          , bench "4-filters" $ whnf drainC $ f C..| f C..| f C..| f
+          ]
+
+      , let m = M.mapping (subtract 1) M.~> M.filtered (<= value)
+            s = S.filter (<= value) . S.map (subtract 1)
+            p = P.map (subtract 1)  P.>-> P.filter (<= value)
+            c = C.map (subtract 1)  C..| C.filter (<= value)
+        in bgroup "summary-alternate"
+          [ bench "machines"  $ whnf drainM $ m M.~> m M.~> m M.~> m
+          , bench "streaming" $ whnf drainS $ \x -> s x & s & s & s
+          , bench "pipes"     $ whnf drainP $ p P.>-> p P.>-> p P.>-> p
+          , bench "conduit"   $ whnf drainC $ c C..| c C..| c C..| c
+          ]
+
+      , let f = M.mapping (subtract 1) M.~> M.filtered (<= value)
+        in bgroup "machines-alternate"
+          [ bench "1-map-filter" $ whnf drainM f
+          , bench "2-map-filters" $ whnf drainM $ f M.~> f
+          , bench "3-map-filters" $ whnf drainM $ f M.~> f M.~> f
+          , bench "4-map-filters" $ whnf drainM $ f M.~> f M.~> f M.~> f
+          ]
+      , let f = S.filter (<= value) . S.map (subtract 1)
+        in bgroup "streaming-alternate"
+          [ bench "1-map-filter" $ whnf drainS (\x -> f x)
+          , bench "2-map-filters" $ whnf drainS $ \x -> f x & f
+          , bench "3-map-filters" $ whnf drainS $ \x -> f x & f & f
+          , bench "4-map-filters" $ whnf drainS $ \x -> f x & f & f & f
+          ]
+      , let f = P.map (subtract 1)  P.>-> P.filter (<= value)
+        in bgroup "pipes-alternate"
+          [ bench "1-map-filter" $ whnf drainP f
+          , bench "2-map-filters" $ whnf drainP $ f P.>-> f
+          , bench "3-map-filters" $ whnf drainP $ f P.>-> f P.>-> f
+          , bench "4-map-filters" $ whnf drainP $ f P.>-> f P.>-> f P.>-> f
+          ]
+      , let f = C.map (subtract 1)  C..| C.filter (<= value)
+        in bgroup "conduit-alternate"
+          [ bench "1-map-filter" $ whnf drainC f
+          , bench "2-map-filters" $ whnf drainC $ f C..| f
+          , bench "3-map-filters" $ whnf drainC $ f C..| f C..| f
+          , bench "4-map-filters" $ whnf drainC $ f C..| f C..| f C..| f
+          ]
+
+        -- how filtering affects the subsequent composition
+      , let m = M.filtered (> value)
+            s = S.filter   (> value)
+            p = P.filter   (> value)
+            c = C.filter   (> value)
+        in bgroup "summary-filter-effect"
+          [ bench "machines"  $ whnf drainM $ m M.~> m M.~> m M.~> m
+          , bench "streaming" $ whnf drainS $ \x -> s x & s & s & s
+          , bench "pipes"     $ whnf drainP $ p P.>-> p P.>-> p P.>-> p
+          , bench "conduit"   $ whnf drainC $ c C..| c C..| c C..| c
+          ]
+
+      , let m = M.filtered (> value)
+            s = S.filter   (> value)
+            p = P.filter   (> value)
+            c = C.filter   (> value)
+        in bgroup "summary-filter-effect-io"
+          [ bench "machines"  $ whnfIO $ drainMIO $ m M.~> m M.~> m M.~> m
+          , bench "streaming" $ whnfIO $ drainSIO $ \x -> s x & s & s & s
+          , bench "pipes"     $ whnfIO $ drainPIO $ p P.>-> p P.>-> p P.>-> p
+          , bench "conduit"   $ whnfIO $ drainCIO $ c C..| c C..| c C..| c
+          ]
+
+      , let f = M.filtered (> value)
+        in bgroup "machines-filter-effect"
+          [ bench "filter1" $ whnf drainM f
+          , bench "filter2" $ whnf drainM $ f M.~> f
+          , bench "filter3" $ whnf drainM $ f M.~> f M.~> f
+          , bench "filter4" $ whnf drainM $ f M.~> f M.~> f M.~> f
+          ]
+      , let f = S.filter (> value)
+        in bgroup "streaming-filter-effect"
+          [ bench "filter1" $ whnf drainS (\x -> f x)
+          , bench "filter2" $ whnf drainS $ \x -> f x & f
+          , bench "filter3" $ whnf drainS $ \x -> f x & f & f
+          , bench "filter4" $ whnf drainS $ \x -> f x & f & f & f
+          ]
+      , let f = P.filter (> value)
+        in bgroup "pipes-filter-effect"
+          [ bench "filter1" $ whnf drainP f
+          , bench "filter2" $ whnf drainP $ f P.>-> f
+          , bench "filter3" $ whnf drainP $ f P.>-> f P.>-> f
+          , bench "filter4" $ whnf drainP $ f P.>-> f P.>-> f P.>-> f
+          ]
+      , let f = C.filter (> value)
+        in bgroup "conduit-filter-effect"
+          [ bench "filter1" $ whnf drainC f
+          , bench "filter2" $ whnf drainC $ f C..| f
+          , bench "filter3" $ whnf drainC $ f C..| f C..| f
+          , bench "filter4" $ whnf drainC $ f C..| f C..| f C..| f
+          ]
       ]
   ]
diff --git a/examples/Examples.hs b/examples/Examples.hs
--- a/examples/Examples.hs
+++ b/examples/Examples.hs
@@ -1,8 +1,11 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE RankNTypes #-}
 
 module Examples where
 
+#if !(MIN_VERSION_base(4,8,0))
 import Control.Applicative
+#endif
 import Control.Exception
 import Control.Monad.Trans
 import Data.Machine
diff --git a/examples/machines-examples.cabal b/examples/machines-examples.cabal
--- a/examples/machines-examples.cabal
+++ b/examples/machines-examples.cabal
@@ -11,10 +11,19 @@
 bug-reports:   http://github.com/ekmett/machines/issues
 copyright:     Copyright (C) 2014 Edward A. Kmett
 synopsis:      Networked stream transducers
-description:   machines examples
+description:   Networked stream transducers
+               .
+               @machines@ examples
 
 build-type:    Simple
-tested-with:   GHC == 7.4.1
+tested-with:   GHC == 7.4.2
+             , GHC == 7.6.3
+             , GHC == 7.8.4
+             , GHC == 7.10.3
+             , GHC == 8.0.2
+             , GHC == 8.2.2
+             , GHC == 8.4.3
+             , GHC == 8.6.1
 
 source-repository head
   type: git
@@ -28,3 +37,6 @@
 
   exposed-modules:
     Examples
+
+  default-language: Haskell2010
+  ghc-options:      -Wall
diff --git a/machines.cabal b/machines.cabal
--- a/machines.cabal
+++ b/machines.cabal
@@ -1,6 +1,6 @@
 name:          machines
 category:      Control, Enumerator
-version:       0.6.3
+version:       0.6.4
 license:       BSD3
 cabal-version: >= 1.10
 license-file:  LICENSE
@@ -17,7 +17,14 @@
   Rúnar Bjarnason's talk on machines can be downloaded from:
   <https://dl.dropbox.com/u/4588997/Machines.pdf>
 build-type:    Custom
-tested-with:   GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.1
+tested-with:   GHC == 7.4.2
+             , GHC == 7.6.3
+             , GHC == 7.8.4
+             , GHC == 7.10.3
+             , GHC == 8.0.2
+             , GHC == 8.2.2
+             , GHC == 8.4.3
+             , GHC == 8.6.1
 extra-source-files:
   .travis.yml
   .gitignore
@@ -45,8 +52,8 @@
     adjunctions  >= 4.2   && < 5,
     base         >= 4.5   && < 5,
     comonad      >= 3     && < 6,
-    containers   >= 0.3   && < 0.6,
-    distributive             < 0.6,
+    containers   >= 0.3   && < 0.7,
+    distributive             < 0.7,
     pointed      >= 3     && < 6,
     profunctors  >= 3     && < 6,
     semigroupoids >= 5    && < 6,
@@ -100,7 +107,7 @@
   default-language: Haskell2010
   build-depends:
     base    == 4.*,
-    doctest >= 0.11.1 && < 0.13,
+    doctest >= 0.11.1 && < 0.17,
     machines
   ghc-options: -Wall -threaded
   hs-source-dirs: tests
@@ -113,10 +120,10 @@
   ghc-options:      -O2 -rtsopts -threaded
 
   build-depends:
-    base                == 4.*,
-    conduit             >= 1.0   && < 1.3,
-    conduit-combinators >= 0.2.5 && < 1.2,
-    criterion           >= 0.6   && < 1.3,
+    base                >= 4.9   && < 5,
+    conduit             >= 1.3   && < 1.4,
+    criterion           >= 0.6   && < 1.6,
     machines,
     mtl                 >= 2     && < 2.3,
-    pipes               >= 4     && < 4.4
+    pipes               >= 4     && < 4.4,
+    streaming           >= 0.1.4 && < 0.3
diff --git a/src/Data/Machine/Mealy.hs b/src/Data/Machine/Mealy.hs
--- a/src/Data/Machine/Mealy.hs
+++ b/src/Data/Machine/Mealy.hs
@@ -225,3 +225,10 @@
 
 instance Closed Mealy where
   closed m = cotabulate $ \fs x -> cosieve m (fmap ($x) fs)
+
+instance Semigroup b => Semigroup (Mealy a b) where
+  f <> g = Mealy $ \x -> runMealy f x <> runMealy g x
+
+instance Monoid b => Monoid (Mealy a b) where
+  mempty = Mealy mempty
+  mappend f g = Mealy $ \x -> runMealy f x `mappend` runMealy g x
diff --git a/src/Data/Machine/MealyT.hs b/src/Data/Machine/MealyT.hs
--- a/src/Data/Machine/MealyT.hs
+++ b/src/Data/Machine/MealyT.hs
@@ -28,6 +28,7 @@
 import Control.Monad.Trans
 import Control.Monad.Identity
 import Data.Profunctor
+import Data.Semigroup
 import qualified Control.Category as C
 import Prelude
 
@@ -132,3 +133,15 @@
 instance AutomatonM MealyT where
   autoT = autoMealyTImpl
 
+instance (Semigroup b, Monad m) => Semigroup (MealyT m a b) where
+  f <> g = MealyT $ \x -> do
+    (fx, f') <- runMealyT f x
+    (gx, g') <- runMealyT g x
+    return (fx <> gx, f' <> g')
+
+instance (Monoid b, Monad m) => Monoid (MealyT m a b) where
+  mempty = MealyT $ \_ -> return mempty
+  mappend f g = MealyT $ \x -> do
+    (fx, f') <- runMealyT f x
+    (gx, g') <- runMealyT g x
+    return (fx `mappend` gx, f' `mappend` g')
diff --git a/src/Data/Machine/Type.hs b/src/Data/Machine/Type.hs
--- a/src/Data/Machine/Type.hs
+++ b/src/Data/Machine/Type.hs
@@ -164,6 +164,7 @@
 -}
 
 -- | Stop feeding input into model, taking only the effects.
+{-# INLINABLE runT_ #-}
 runT_ :: Monad m => MachineT m k b -> m ()
 runT_ m = runMachineT m >>= \v -> case v of
   Stop        -> return ()
@@ -171,6 +172,7 @@
   Await _ _ e -> runT_ e
 
 -- | Stop feeding input into model and extract an answer
+{-# INLINABLE runT #-}
 runT :: Monad m => MachineT m k b -> m [b]
 runT (MachineT m) = m >>= \v -> case v of
   Stop        -> return []
