pipes-extra 0.0.1 → 0.1.0
raw patch · 7 files changed
+107/−62 lines, 7 filesdep +transformersdep −mtldep ~pipes-corePVP ok
version bump matches the API change (PVP)
Dependencies added: transformers
Dependencies removed: mtl
Dependency ranges changed: pipes-core
API changes (from Hackage documentation)
- Control.Pipe.ChunkPipe: ChunkPipe :: Pipe a b m (a, r) -> ChunkPipe a b m r
- Control.Pipe.ChunkPipe: instance (Monoid a, Monad m) => Monad (ChunkPipe a b m)
- Control.Pipe.ChunkPipe: newtype ChunkPipe a b m r
- Control.Pipe.ChunkPipe: nonchunked :: (Monoid a, Monad m) => Pipe a b m r -> ChunkPipe a b m r
- Control.Pipe.ChunkPipe: unChunkPipe :: ChunkPipe a b m r -> Pipe a b m (a, r)
- Control.Pipe.Coroutine: suspendE :: Coroutine a b m r -> SomeException -> Pipe a b m r
+ Control.Pipe.PutbackPipe: PutbackPipe :: Pipe (Either a a) (Either b a) m r -> PutbackPipe a b m r
+ Control.Pipe.PutbackPipe: await :: Monad m => PutbackPipe a b m a
+ Control.Pipe.PutbackPipe: fromPipe :: Monad m => Pipe a b m r -> PutbackPipe a b m r
+ Control.Pipe.PutbackPipe: instance Monad m => Applicative (PutbackPipe a b m)
+ Control.Pipe.PutbackPipe: instance Monad m => Functor (PutbackPipe a b m)
+ Control.Pipe.PutbackPipe: instance Monad m => Monad (PutbackPipe a b m)
+ Control.Pipe.PutbackPipe: instance MonadIO m => MonadIO (PutbackPipe a b m)
+ Control.Pipe.PutbackPipe: instance MonadTrans (PutbackPipe a b)
+ Control.Pipe.PutbackPipe: newtype PutbackPipe a b m r
+ Control.Pipe.PutbackPipe: putback :: Monad m => a -> PutbackPipe a b m ()
+ Control.Pipe.PutbackPipe: runPutback :: Monad m => PutbackPipe a b m r -> Pipe a b m r
+ Control.Pipe.PutbackPipe: tryAwait :: Monad m => PutbackPipe a b m (Maybe a)
+ Control.Pipe.PutbackPipe: unPutback :: PutbackPipe a b m r -> Pipe (Either a a) (Either b a) m r
+ Control.Pipe.PutbackPipe: yield :: Monad m => b -> PutbackPipe a b m ()
- Control.Pipe.Coroutine: resume :: Monad m => Pipe a b m r -> Pipe a x m (Either r (b, Coroutine a b m r))
+ Control.Pipe.Coroutine: resume :: Coroutine a b m r -> Pipe a b m r
- Control.Pipe.Coroutine: suspend :: Coroutine a b m r -> Pipe a b m r
+ Control.Pipe.Coroutine: suspend :: Monad m => Pipe a b m r -> Pipe a x m (Either r (b, Coroutine a b m r))
- Control.Pipe.Coroutine: terminate :: Monad m => Coroutine a b m r -> Pipe a x m ()
+ Control.Pipe.Coroutine: terminate :: Monad m => Coroutine a b m r -> Pipe a b m ()
Files
- Control/Pipe/Binary.hs +3/−1
- Control/Pipe/ChunkPipe.hs +0/−29
- Control/Pipe/Coroutine.hs +21/−22
- Control/Pipe/PutbackPipe.hs +73/−0
- Control/Pipe/Tee.hs +3/−3
- Control/Pipe/Zip.hs +3/−3
- pipes-extra.cabal +4/−4
Control/Pipe/Binary.hs view
@@ -15,7 +15,8 @@ ) where import Control.Monad-import Control.Monad.Trans (MonadIO, liftIO, lift)+import Control.Monad.IO.Class+import Control.Monad.Trans.Class import Control.Pipe import Control.Pipe.Exception import Control.Pipe.Combinators (tryAwait, feed)@@ -105,6 +106,7 @@ go leftover = do mchunk <- tryAwait case mchunk of+ Nothing | B.null leftover -> idP Nothing -> yield leftover >> idP Just chunk -> split chunk leftover split chunk leftover
− Control/Pipe/ChunkPipe.hs
@@ -1,29 +0,0 @@--- | This module contains utilities to create and combine pipes that accept--- "chunked" input and return unconsumed portions of their internal buffer.------ The main interface is an alternative monad instance for Pipe, which passes--- leftover data along automatically.-module Control.Pipe.ChunkPipe (- ChunkPipe(..),- nonchunked,- ) where--import Control.Pipe-import Data.Monoid---- | Newtype wrapper for Pipe proving a monad instance that takes care of--- passing leftover data automatically.------ An individual 'ChunkPipe' is just a regular pipe, but returns unconsumed--- input in a pair alongside the actual return value.-newtype ChunkPipe a b m r = ChunkPipe { unChunkPipe :: Pipe a b m (a, r) }--instance (Monoid a, Monad m) => Monad (ChunkPipe a b m) where- return = nonchunked . return- (ChunkPipe p) >>= f = ChunkPipe $ p >>= \(leftover, result) ->- (yield leftover >> idP) >+> unChunkPipe (f result)---- | Create a 'ChunkPipe' out of a regular pipe that is able to consume all its--- input.-nonchunked :: (Monoid a, Monad m) => Pipe a b m r -> ChunkPipe a b m r-nonchunked p = ChunkPipe $ p >>= \r -> return (mempty, r)
Control/Pipe/Coroutine.hs view
@@ -1,46 +1,45 @@+{-# LANGUAGE DeriveDataTypeable #-} module Control.Pipe.Coroutine ( Coroutine,- coroutine,- suspend,- suspendE, resume,+ suspend,+ coroutine, step, terminate ) where import Control.Monad import Control.Pipe+import Control.Pipe.Exception import qualified Control.Exception as E+import Data.Typeable+import Prelude hiding (catch) data Coroutine a b m r = Coroutine- { suspend :: Pipe a b m r- , suspendE :: E.SomeException -> Pipe a b m r }+ { resume :: Pipe a b m r+ , finalizer :: [m ()]+ } -resume :: Monad m- => Pipe a b m r- -> Pipe a x m (Either r (b, Coroutine a b m r))-resume (Pure r) = return $ Left r-resume (Throw e) = throwP e-resume (Free c h) = go c >>= \x -> case x of- Left p -> resume p- Right (b, p) -> return $ Right (b, Coroutine p h)- where- go (Await k) = liftM (Left . k) await- go (Yield b p) = return $ Right (b, p)- go (M m s) = liftM Left $ liftP s m+suspend :: Monad m+ => Pipe a b m r+ -> Pipe a x m (Either r (b, Coroutine a b m r))+suspend (Pure r w) = Pure (Left r) w+suspend (Throw e w) = Throw e w+suspend (Yield x p w) = return (Right (x, Coroutine p w))+suspend (M s m h) = M s (liftM suspend m) (suspend . h)+suspend (Await k h) = Await (suspend . k) (suspend . h) coroutine :: Monad m => Pipe a b m r -> Coroutine a b m r-coroutine p = Coroutine p throwP+coroutine p = Coroutine p [] step :: Monad m => Coroutine a b m r -> Pipe a x m (Either r (b, Coroutine a b m r))-step = resume . suspend+step = suspend . resume terminate :: Monad m => Coroutine a b m r- -> Pipe a x m ()-terminate (Coroutine _ h) =- void (catchP discard h) >+> return ()+ -> Pipe a b m ()+terminate p = mapM_ masked (finalizer p)
+ Control/Pipe/PutbackPipe.hs view
@@ -0,0 +1,73 @@+-- | This module contains an alternative pipe implementation, 'PutbackPipe',+-- providing an additional primitive 'putback', which allows data to be+-- inserted into the input stream of the current pipe.+--+-- PutbackPipes can be used to implement pipes with left-over data, and can be+-- composed vertically (using the Monad instance), but not horizontally.+--+-- To make use of a PutbackPipe within a 'Pipeline', you need to convert it to+-- a regular 'Pipe' using 'runPutback'.+module Control.Pipe.PutbackPipe (+ PutbackPipe(..),+ fromPipe,+ putback,+ yield,+ await,+ tryAwait,+ runPutback+ ) where++import Control.Applicative+import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Trans.Class+import qualified Control.Pipe as P+import Control.Pipe ((>+>), Pipe)+import qualified Control.Pipe.Combinators as PC+import Control.Pipe.Monoidal++-- | The 'PutbackPipe' data type.+newtype PutbackPipe a b m r = PutbackPipe {+ unPutback :: Pipe (Either a a) (Either b a) m r+ }++instance Monad m => Monad (PutbackPipe a b m) where+ return = PutbackPipe . return+ (PutbackPipe p) >>= f = PutbackPipe (p >>= unPutback . f)++instance MonadTrans (PutbackPipe a b) where+ lift = PutbackPipe . lift++instance Monad m => Functor (PutbackPipe a b m) where+ fmap f (PutbackPipe p) = PutbackPipe (liftM f p)++instance Monad m => Applicative (PutbackPipe a b m) where+ pure = return+ (<*>) = ap++instance MonadIO m => MonadIO (PutbackPipe a b m) where+ liftIO a = PutbackPipe (liftIO a)++-- | Create a 'PutbackPipe' from a regular pipe.+fromPipe :: Monad m => Pipe a b m r -> PutbackPipe a b m r+fromPipe p = PutbackPipe (joinP >+> p >+> P.pipe Left)++-- | Put back an element into the input stream.+putback :: Monad m => a -> PutbackPipe a b m ()+putback = PutbackPipe . P.yield . Right++-- | Same as 'P.yield' for regular pipes.+yield :: Monad m => b -> PutbackPipe a b m ()+yield = PutbackPipe . P.yield . Left++-- | Same as 'P.await' for regular pipes.+await :: Monad m => PutbackPipe a b m a+await = PutbackPipe $ liftM (either id id) P.await++-- | Same as 'PC.tryAwait' for regular pipes.+tryAwait :: Monad m => PutbackPipe a b m (Maybe a)+tryAwait = PutbackPipe $ liftM (fmap (either id id)) PC.tryAwait++-- | Convert a 'PutbackPipe' to a regular pipe.+runPutback :: Monad m => PutbackPipe a b m r -> Pipe a b m r+runPutback = loopP . unPutback
Control/Pipe/Tee.hs view
@@ -17,10 +17,10 @@ teeFileBS ) where -import Control.Monad.Trans (MonadIO(..))+import Control.Monad.IO.Class import Control.Pipe-import Control.Pipe.Binary (fileWriter)-import Data.ByteString (ByteString)+import Control.Pipe.Binary+import Data.ByteString -- | Acts like 'idP', but also passes a copy to the supplied consumer. tee :: (Monad m)
Control/Pipe/Zip.hs view
@@ -22,15 +22,15 @@ => Producer a m r -> Pipe (Either () (ProducerControl r)) a m r controllable p = do- x <- pipe (const ()) >+> resume p+ x <- pipe (const ()) >+> suspend p case x of Left r -> return r Right (b, p') -> join $ onException (await >>= \c -> case c of- Left () -> yield b >> return (controllable (suspend p'))+ Left () -> yield b >> return (controllable (resume p')) Right (Done r) -> return $ (pipe (const ()) >+> terminate p') >> return r- Right (Error e) -> return $ controllable (suspendE p' e))+ Right (Error e) -> return $ (pipe (const ()) >+> terminate p') >> throw e) (pipe (const ()) >+> terminate p') controllable_ :: Monad m
pipes-extra.cabal view
@@ -1,5 +1,5 @@ Name: pipes-extra-Version: 0.0.1+Version: 0.1.0 License: BSD3 License-file: LICENSE Author: Paolo Capriotti@@ -19,12 +19,12 @@ Library Build-Depends: base (== 4.*),- mtl,- pipes-core (== 0.0.*),+ transformers (>= 0.2 && < 0.4),+ pipes-core (== 0.1.*), bytestring (== 0.9.*) Exposed-Modules: Control.Pipe.Binary, Control.Pipe.Coroutine,- Control.Pipe.ChunkPipe,+ Control.Pipe.PutbackPipe, Control.Pipe.Tee, Control.Pipe.Zip