packages feed

drinkery 0.2.1 → 0.2.2

raw patch · 5 files changed

+78/−60 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.Drinkery.Class: [runDrinker] :: Drinker t m a -> t m -> m (a, t m)
- Data.Drinkery.Class: instance (GHC.Base.Functor m, GHC.Base.Monad m) => GHC.Base.Applicative (Data.Drinkery.Class.Drinker s m)
- Data.Drinkery.Class: instance GHC.Base.Functor m => GHC.Base.Functor (Data.Drinkery.Class.Drinker s m)
- Data.Drinkery.Class: instance GHC.Base.Monad m => GHC.Base.Monad (Data.Drinkery.Class.Drinker s m)
+ Data.Drinkery.Class: [unDrinker] :: Drinker t m a -> forall r. t m -> (a -> t m -> m r) -> m r
+ Data.Drinkery.Class: instance GHC.Base.Applicative (Data.Drinkery.Class.Drinker s m)
+ Data.Drinkery.Class: instance GHC.Base.Functor (Data.Drinkery.Class.Drinker s m)
+ Data.Drinkery.Class: instance GHC.Base.Monad (Data.Drinkery.Class.Drinker s m)
+ Data.Drinkery.Class: runDrinker :: Applicative m => Drinker t m a -> t m -> m (a, t m)
- Data.Drinkery.Class: Drinker :: (t m -> m (a, t m)) -> Drinker t m a
+ Data.Drinkery.Class: Drinker :: (forall r. t m -> (a -> t m -> m r) -> m r) -> Drinker t m a
- Data.Drinkery.Distiller: (++$) :: (Functor m) => tap m -> Distiller tap r s m -> Tap r s m
+ Data.Drinkery.Distiller: (++$) :: (Applicative m) => tap m -> Distiller tap r s m -> Tap r s m
- Data.Drinkery.Distiller: (++&) :: (Functor m) => tap m -> Drinker tap m a -> m (tap m, a)
+ Data.Drinkery.Distiller: (++&) :: (Applicative m) => tap m -> Drinker tap m a -> m (tap m, a)
- Data.Drinkery.Distiller: reservingTap :: MonadDrunk (Tap r a) m => (a -> m (s, Tap r s m)) -> Tap r s m
+ Data.Drinkery.Distiller: reservingTap :: Monad m => (a -> Drinker (Tap r a) m (b, Distiller (Tap r a) r b m)) -> Distiller (Tap r a) r b m

Files

benchmarks/benchmark.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS -ddump-simpl -dsuppress-all #-}
 import Control.Arrow
 import Control.Monad
 import Data.Functor.Identity
@@ -46,14 +45,44 @@ {-# INLINE sourceM #-}
 
 main = defaultMain
-  [ bgroup "map-filter"
-      [ bench "drinkery/$&" $ whnfIO $ apply (\h -> sourceD D.++$ h D.+& drainD)
-          (mapFilter D.++$ mapFilter D.++$ mapFilter D.++$ mapFilter)
+  [ 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
+      ]
   ]
-
-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: 8721a9c033d203203693686a359a7d6d4f5026ebbaaedd5de20c604fcbee478b+-- hash: a02d5f24aaf654476fe20d6324eebcaa59bf282ddc4946c5b15c83fbdb019481  name:           drinkery-version:        0.2.1+version:        0.2.2 synopsis:       Boozy streaming library description:    Please see the README on Github at <https://github.com/fumieval/drinkery#readme> category:       Control
src/Data/Drinkery/Class.hs view
@@ -13,12 +13,14 @@ module Data.Drinkery.Class   ( Drinker(..)   , mapDrinker+  , runDrinker   , MonadDrunk(..)   , CloseRequest(..)   , Closable(..)) where +import Control.Monad import Control.Monad.Trans.Class-import Control.Monad.Trans.Cont+import Control.Monad.Trans.Cont hiding (cont) import Control.Monad.Trans.Maybe import qualified Control.Monad.Trans.Reader as Reader import qualified Control.Monad.Trans.State.Lazy as Lazy@@ -33,40 +35,31 @@ import Control.Monad.State.Class  -- | A 'Drinker' is a stream consumer monad.-newtype Drinker t m a = Drinker { runDrinker :: t m -> m (a, t m) }+newtype Drinker t m a = Drinker+  { unDrinker :: forall r. t m -> (a -> t m -> m r) -> m r }  mapDrinker :: (forall x. m x -> m x) -> Drinker t m a -> Drinker t m a-mapDrinker t = Drinker . fmap t . runDrinker-{-# INLINE mapDrinker #-}+mapDrinker t (Drinker d) = Drinker $ \tap k -> t (d tap k) -instance (Functor m) => Functor (Drinker s m) where-  fmap f m = Drinker $ \s -> fmap (\(a, s') -> (f a, s')) $ runDrinker m s-  {-# INLINE fmap #-}+runDrinker :: Applicative m => Drinker t m a -> t m -> m (a, t m)+runDrinker (Drinker d) t = d t (\a t' -> pure (a, t')) -instance (Functor m, Monad m) => Applicative (Drinker s m) where-  pure a = Drinker $ \s -> return (a, s)-  {-# INLINE pure #-}-  Drinker mf <*> Drinker mx = Drinker $ \ s -> do-    (f, s') <- mf s-    (x, s'') <- mx s'-    return (f x, s'')-  {-# INLINE (<*>) #-}+instance Functor (Drinker s m) where+  fmap f m = Drinker $ \s k -> unDrinker m s (k . f)++instance Applicative (Drinker s m) where+  pure a = Drinker $ \s k -> k a s+  Drinker mf <*> Drinker mx = Drinker+    $ \s k -> mf s $ \f s' -> mx s' $ k . f   m *> k = m >>= \_ -> k-  {-# INLINE (*>) #-} -instance (Monad m) => Monad (Drinker s m) where-  return a = Drinker $ \s -> return (a, s)+instance Monad (Drinker s m) where+  return = pure   {-# INLINE return #-}-  m >>= k  = Drinker $ \s -> do-    (a, s') <- runDrinker m s-    runDrinker (k a) s'-  {-# INLINE (>>=) #-}-  fail str = Drinker $ \_ -> fail str-  {-# INLINE fail #-}+  m >>= k = Drinker $ \s cont -> unDrinker m s $ \a s' -> unDrinker (k a) s' cont  instance MonadTrans (Drinker t) where-  lift m = Drinker $ \t -> m >>= \a -> return (a, t)-  {-# INLINE lift #-}+  lift m = Drinker $ \t k -> m >>= \a -> k a t  instance MonadIO m => MonadIO (Drinker t m) where   liftIO = lift . liftIO@@ -83,19 +76,20 @@ instance MonadWriter s m => MonadWriter s (Drinker t m) where   writer = lift . writer   tell   = lift . tell-  listen m = Drinker $ \s -> do+  listen m = Drinker $ \s k -> do     ((a, s'), w) <- listen (runDrinker m s)-    return ((a, w), s')-  pass m = Drinker $ \s -> pass $ do+    k (a, w) s'+  pass m = Drinker $ \s k -> join $ pass $ do     ((a, f), s') <- runDrinker m s-    return ((a, s'), f)+    return (k a s', f)  -- | Monads that drink class Monad m => MonadDrunk t m | m -> t where   drinking :: (forall n. Monad n => t n -> n (a, t n)) -> m a  instance Monad m => MonadDrunk t (Drinker t m) where-  drinking = Drinker+  drinking f = Drinker $ \t k -> f t >>= uncurry k+  {-# INLINE drinking #-}  instance MonadDrunk t m => MonadDrunk t (Reader.ReaderT x m) where   drinking f = lift (drinking f)
src/Data/Drinkery/Distiller.hs view
@@ -32,7 +32,6 @@ import Data.Drinkery.Tap import Data.Drinkery.Class import Data.Semigroup-import Data.Tuple  -- | @Distiller tap m r s@ is a stream transducer which has four parameters: --@@ -57,8 +56,8 @@ -- * @+@ Left operand is a tap. -- * @+@ Returns a tap (along with the result). -- * @&@ Right operand is a Drinker.-(++&) :: (Functor m) => tap m -> Drinker tap m a -> m (tap m, a)-d ++& b = swap <$> runDrinker b d+(++&) :: (Applicative m) => tap m -> Drinker tap m a -> m (tap m, a)+d ++& b = unDrinker b d $ \a t -> pure (t, a) {-# INLINE (++&) #-}  -- | Attach a distiller to a tap.@@ -69,10 +68,10 @@ -- * @+@ Returns a tap. -- * @$@ Right operand is a distiller. ---(++$) :: (Functor m) => tap m -> Distiller tap r s m -> Tap r s m+(++$) :: (Applicative m) => tap m -> Distiller tap r s m -> Tap r s m (++$) = go where -- looks strange, but seems to perform better (GHC 8.2.2)-  go t d = Tap $ \r -> (\((s, d'), t') -> (s, go t' d'))-    <$> runDrinker (unTap d r) t+  go t d = Tap $ \r -> unDrinker (unTap d r) t+    $ \(s, d') t' -> pure (s, go t' d') {-# INLINE (++$) #-}  -- | Feed a tap to a drinker and close the used tap.@@ -101,10 +100,10 @@ {-# INLINE mapping #-}  -- | Get one element preserving a request-reservingTap :: MonadDrunk (Tap r a) m => (a -> m (s, Tap r s m)) -> Tap r s m-reservingTap k = Tap $ \r -> do-  a <- drinking $ \t -> unTap t r-  k a+reservingTap :: Monad m => (a -> Drinker (Tap r a) m (b, Distiller (Tap r a) r b m)) -> Distiller (Tap r a) r b m+reservingTap k = Tap $ \r -> Drinker $ \t cont -> do+  (a, t') <- unTap t r+  unDrinker (k a) t' cont {-# INLINE reservingTap #-}  traversing :: (Monad m) => (a -> m b) -> Distiller (Tap r a) r b m
src/Data/Drinkery/Still.hs view
@@ -17,11 +17,9 @@  scan :: Monad m => (b -> a -> b) -> b -> Pipe a b m scan f b0 = consTap (Just b0) $ go b0 where-  go b = Tap $ \r -> Drinker $ \tap -> do-    (m, t') <- unTap tap r-    case m of-      Just a -> let !b' = f b a in return ((Just b', go b'), t')-      Nothing -> return ((Nothing, go b), t')+  go b = reservingTap $ \case+    Just a -> let !b' = f b a in return (Just b', go b')+    Nothing -> return (Nothing, go b) {-# INLINE scan #-}  reserve :: (Monoid r, MonadDrunk (Cask r s) m)@@ -51,11 +49,9 @@  mapAccum :: Monad m => (s -> a -> (s, b)) -> s -> Pipe a b m mapAccum f = go where-  go s = Tap $ \r -> Drinker $ \tap -> do-    (m, t') <- unTap tap r-    case m of-      Just a -> let (s', b) = f s a in return ((Just b, go s'), t')-      Nothing -> return ((Nothing, go s), t')+  go s = reservingTap $ \case+    Just a -> let (s', b) = f s a in return (Just b, go s')+    Nothing -> return (Nothing, go s) {-# INLINE mapAccum #-}  traverse :: (Monad m) => (a -> m b) -> Pipe a b m