packages feed

machines 0.6.3 → 0.6.4

raw patch · 10 files changed

+426/−113 lines, 10 filesdep +streamingdep −conduit-combinatorsdep ~basedep ~conduitdep ~containers

Dependencies added: streaming

Dependencies removed: conduit-combinators

Dependency ranges changed: base, conduit, containers

Files

.gitignore view
@@ -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.*
.travis.yml view
@@ -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
CHANGELOG.markdown view
@@ -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`
benchmarks/Benchmarks.hs view
@@ -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+          ]       ]   ]
examples/Examples.hs view
@@ -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
examples/machines-examples.cabal view
@@ -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
machines.cabal view
@@ -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
src/Data/Machine/Mealy.hs view
@@ -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
src/Data/Machine/MealyT.hs view
@@ -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')
src/Data/Machine/Type.hs view
@@ -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 []