packages feed

drinkery 0.2 → 0.2.1

raw patch · 6 files changed

+85/−44 lines, 6 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.Drinkery.Still: mapMaybe :: (Monad m) => (a -> Maybe b) -> Pipe a b m
+ Data.Drinkery.Combinators: lastFrom :: (Alternative t, Foldable t, Monad m) => m (t a) -> m (Maybe a)
+ Data.Drinkery.Still: concatMap :: (Foldable f, Monad m) => (a -> f b) -> Pipe a b m
+ Data.Drinkery.Still: drop :: Monad m => Int -> Pipe a a m
+ Data.Drinkery.Still: dropWhile :: Monad m => (a -> Bool) -> Pipe a a m
+ Data.Drinkery.Still: map' :: (Functor t, Monad m) => (a -> b) -> Distiller (Tap r (t a)) r (t b) m
+ Data.Drinkery.Still: take :: Monad m => Int -> Pipe a a m
+ Data.Drinkery.Still: takeWhile :: Monad m => (a -> Bool) -> Pipe a a m
+ Data.Drinkery.Still: traverse :: (Monad m) => (a -> m b) -> Pipe a b m
+ Data.Drinkery.Tap: Joint :: Tap r s m -> Joint r m s
+ Data.Drinkery.Tap: [unJoint] :: Joint r m s -> Tap r s m
+ Data.Drinkery.Tap: instance GHC.Base.Applicative m => GHC.Base.Applicative (Data.Drinkery.Tap.Joint r m)
+ Data.Drinkery.Tap: instance GHC.Base.Functor m => GHC.Base.Functor (Data.Drinkery.Tap.Joint r m)
+ Data.Drinkery.Tap: newtype Joint r m s

Files

benchmarks/benchmark.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS -ddump-simpl -dsuppress-all #-}
 import Control.Arrow
 import Control.Monad
 import Data.Functor.Identity
@@ -45,44 +46,14 @@ {-# INLINE sourceM #-}
 
 main = defaultMain
-  [ bgroup "drain"
-      [ bench "drinkery/Barman" $ whnfIO
-          $ apply (D.+& drainD)
-          $ D.runBarman (sourceSeq D.yield)
-      , bench "drinkery/Sommelier" $ whnfIO
-          $ apply (D.+& drainD) sourceD
-      , bench "pipes/Producer" $ whnfIO
-          $ apply (\s -> P.runEffect $ s P.>-> P.drain) sourceP
-      , bench "pipes/ListT" $ whnfIO
-          $ apply (\s -> P.runEffect $ s P.>-> P.drain)
-          $ P.enumerate (sourceAlt (P.Select . P.each))
-      , bench "list-t" $ whnfIO
-          $ apply (L.traverse_ $ const $ pure ())
-          $ sourceAlt L.fromFoldable
-      ]
-  , bgroup "scan"
-      [ bench "drinkery" $ whnfIO $ apply (\h -> sourceD D.+& h D.$& drainD)
-          $ D.scan (+) 0
-      , bench "pipes" $ whnfIO $ apply (\p -> P.runEffect $ P.for (sourceP P.>-> p) P.discard)
-          $ P.scan (+) 0 id
-      , bench "conduit" $ whnfIO $ C.runConduit $ apply (\(h, s) -> sourceC C..| h C..| s)
-          (CC.scanl (+) 0, CC.sinkNull)
-      , bench "machines" $ whnfIO $ apply (M.runT_ . (sourceM M.~>))
-          $ M.scan (+) 0
-      ]
-   , bgroup "scan-chain"
-      [ bench "drinkery/++$" $ whnfIO $ apply (\h -> D.runBarman (sourceSeq D.yield) D.+& h D.$& drainD)
-          $ D.scan (+) 0 D.++$ D.scan (+) 0
-      , bench "drinkery/$&" $ whnfIO $ apply (\(h, h') -> D.runBarman (sourceSeq D.yield) D.+& h D.$& h' D.$& drainD)
-          (D.scan (+) 0, D.scan (+) 0)
-      , bench "pipes" $ whnfIO $ apply (\p -> P.runEffect $ P.for (sourceP P.>-> p) P.discard)
-          $ P.scan (+) 0 id P.>-> P.scan (+) 0 id
-      , bench "conduit" $ whnfIO $ apply (\(h, s) -> C.runConduit $ sourceC C..| h C..| s)
-          (CC.scanl (+) 0 C..| CC.scanl (+) 0, CC.sinkNull)
-      , bench "machines" $ whnfIO $ apply (M.runT_ . (sourceM M.~>))
-          $ M.scan (+) 0 M.~> M.scan (+) 0
+  [ bgroup "map-filter"
+      [ bench "drinkery/$&" $ whnfIO $ apply (\h -> sourceD D.++$ h D.+& drainD)
+          (mapFilter D.++$ mapFilter D.++$ mapFilter D.++$ mapFilter)
       ]
   ]
+
+mapFilter :: Monad m => D.Pipe Int Int m
+mapFilter = D.map' (+1) D.++$ D.filter (>0)
 
 apply :: (a -> b) -> a -> b
 apply f x = f x
drinkery.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: c680196ca0c264db17dcb6cca154fa3a64e957e2d4859e8dd024c4b302e0f731+-- hash: 8721a9c033d203203693686a359a7d6d4f5026ebbaaedd5de20c604fcbee478b  name:           drinkery-version:        0.2+version:        0.2.1 synopsis:       Boozy streaming library description:    Please see the README on Github at <https://github.com/fumieval/drinkery#readme> category:       Control
src/Data/Drinkery/Combinators.hs view
@@ -13,9 +13,11 @@   , foldMFrom   , traverseFrom_   , drainFrom+  , lastFrom   ) where +import Control.Applicative import Control.Monad hiding (foldM) import qualified Data.Foldable as F @@ -48,3 +50,10 @@ drainFrom m = go where   go = m >>= \t -> unless (null t) go {-# INLINE drainFrom #-}++lastFrom :: (Alternative t, Foldable t, Monad m) => m (t a) -> m (Maybe a)+lastFrom m = go empty where+  go l = m >>= \t -> if null t+    then return $! foldr (\x r _ -> r (Just x)) id l Nothing+    else go t+{-# INLINE lastFrom #-}
src/Data/Drinkery/Distiller.hs view
@@ -93,10 +93,11 @@  echo :: Monad m => Distiller (Tap r s) r s m echo = mapping id+{-# INLINE echo #-}  mapping :: (Monad m) => (a -> b) -> Distiller (Tap r a) r b m mapping f = go where-  go = Tap $ \r -> drinking $ \t -> fmap (\(s, t') -> ((f s, go), t')) $ unTap t r+  go = reservingTap $ \a -> pure (f a, go) {-# INLINE mapping #-}  -- | Get one element preserving a request
src/Data/Drinkery/Still.hs view
@@ -2,6 +2,7 @@ module Data.Drinkery.Still where  import Control.Applicative+import Control.Monad (replicateM_) import Data.Drinkery.Class import Data.Drinkery.Distiller import Data.Drinkery.Tap@@ -33,10 +34,17 @@ map = mapping . fmap {-# INLINE map #-} -mapMaybe :: (Monad m) => (a -> Maybe b) -> Pipe a b m-mapMaybe f = inexhaustible $ reserve $ mapM_ yield . f-{-# INLINE mapMaybe #-}+map' :: (Functor t, Monad m) => (a -> b) -> Distiller (Tap r (t a)) r (t b) m+map' f = traversing $ (pure$!) . fmap f+{-# INLINE map' #-} +concatMap :: (Foldable f, Monad m) => (a -> f b) -> Pipe a b m+concatMap f = go where+  go = reservingTap $ \case+    Just a -> unTap (foldr (consTap . Just) go (f a)) mempty+    Nothing -> return (Nothing, go)+{-# INLINE concatMap #-}+ filter :: Monad m => (a -> Bool) -> Pipe a a m filter = filtering . maybe True {-# INLINE filter #-}@@ -50,9 +58,41 @@       Nothing -> return ((Nothing, go s), t') {-# INLINE mapAccum #-} +traverse :: (Monad m) => (a -> m b) -> Pipe a b m+traverse = traversing . Prelude.traverse+{-# INLINE traverse #-}++take :: Monad m => Int -> Pipe a a m+take = go where+  go 0 = repeatTap Nothing+  go n = reservingTap $ \a -> return (a, go (n - 1))+{-# INLINE take #-}++drop :: Monad m => Int -> Pipe a a m+drop n = makeTap $ do+  replicateM_ n drink+  return echo+{-# INLINE drop #-}++takeWhile :: Monad m => (a -> Bool) -> Pipe a a m+takeWhile p = go where+  go = reservingTap $ \case+    Just s | p s -> return (Just s, go)+    _ -> return (Nothing, go)+{-# INLINE takeWhile #-}++dropWhile :: Monad m => (a -> Bool) -> Pipe a a m+dropWhile p = go where+  go = reservingTap $ \case+    Just s | p s -> unTap go mempty+    x -> return (x, go)+{-# INLINE dropWhile #-}+ -- | Consume all the content of a 'Tap' and return the elements as a list. drinkUp :: (Monoid r, Semigroup r, MonadDrunk (Tap r (Maybe s)) m) => m [s]-drinkUp = drink >>= maybe (pure []) (\x -> (x:) <$> drinkUp)+drinkUp = go id where+  go f = drink >>= maybe (pure $ f []) (\x -> go $ f . (x:))+{-# INLINE drinkUp #-}  sip :: (Monoid r, Alternative m, MonadDrunk (Tap r (Maybe s)) m) => m s sip = drink >>= maybe empty pure
src/Data/Drinkery/Tap.hs view
@@ -18,6 +18,7 @@   , repeatTap   , repeatTapM   , repeatTapM'+  , Joint(..)   -- * Barman   , Barman(..)   , yield@@ -105,6 +106,23 @@   return s {-# INLINE smell #-} +-- | ('<*>') zips two taps.+newtype Joint r m s = Joint { unJoint :: Tap r s m }++instance Functor m => Functor (Joint r m) where+  fmap f (Joint tap0) = Joint (go tap0) where+    go tap = Tap $ \r -> fmap (\(s, t) -> (f s, go t)) $ unTap tap r+  {-# INLINE fmap #-}++instance Applicative m => Applicative (Joint r m) where+  pure = Joint . repeatTap+  {-# INLINE pure #-}+  Joint tapF <*> Joint tapA = Joint (go tapF tapA) where+    go s t = Tap $ \r -> (\(f, s') (x, t') -> (f x, go s' t'))+      <$> unTap s r+      <*> unTap t r+  {-# INLINE (<*>) #-}+ -- | Monadic producer newtype Barman r s m a = Barman { unBarman :: (a -> Tap r s m) -> Tap r s m } @@ -141,7 +159,9 @@ -- @inexhaustible :: 'Barman' r s ('Drinker' tap m) x -> 'Distiller' tap m r s@ -- inexhaustible :: Barman r s m x -> Tap r s m-inexhaustible t = unBarman t $ const $ inexhaustible t+inexhaustible t = go where+  go = unBarman t $ const go+{-# INLINE inexhaustible #-}  -- | Backtracking producer a.k.a. "ListT done right". newtype Sommelier r m s = Sommelier