quiver 0.0.0.6 → 0.0.0.7
raw patch · 4 files changed
+184/−79 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Control.Quiver: emit' :: b -> Consumer a' a f b' -> P a' a b b' f b'
- Control.Quiver: fetch' :: a' -> Producer b b' f a -> P a' a b b' f a
- Control.Quiver: qconcat_ :: SP [a] a f [a]
- Control.Quiver: qpure_ :: (a -> b) -> SP a b f ()
- Control.Quiver: type SP a b f r = forall b'. P () a b b' f r
- Control.Quiver.Internal: instance Applicative f => Applicative (P a' a b b' f)
- Control.Quiver.Internal: instance Functor f => Functor (P a' a b b' f)
- Control.Quiver.Internal: instance Monad f => Monad (P a' a b b' f)
- Control.Quiver.Internal: type SP a b f r = forall b'. P () a b b' f r
+ Control.Quiver: (>&>) :: Functor f => P a a' b b' f r -> (r -> r') -> P a a' b b' f r'
+ Control.Quiver: fetch_ :: a -> P a a' b b' f ()
+ Control.Quiver: qcompose :: Functor f => (r1 -> r2 -> r) -> P a a' b b' f r1 -> P b' b c c' f r2 -> P a a' c c' f r
+ Control.Quiver.Internal: instance Applicative f => Applicative (P a a' b b' f)
+ Control.Quiver.Internal: instance Functor f => Functor (P a a' b b' f)
+ Control.Quiver.Internal: instance Monad f => Monad (P a a' b b' f)
+ Control.Quiver.SP: spconcat :: SP [a] a f [a]
+ Control.Quiver.SP: spfetch :: Functor f => SP a b f (Maybe a)
+ Control.Quiver.SP: spfold :: (Functor f, Monoid a) => SP a a f ()
+ Control.Quiver.SP: spfoldl :: (b -> a -> b) -> b -> SP a b f ()
+ Control.Quiver.SP: spfoldr :: (a -> b -> b) -> b -> SP a b f ()
+ Control.Quiver.SP: spid :: SP a a f ()
+ Control.Quiver.SP: sppure :: (a -> b) -> SP a b f ()
+ Control.Quiver.SP: type SP a b f r = forall b'. P () a b b' f r
+ Control.Quiver.SP: type SPResult e = Maybe (Maybe e)
- Control.Quiver: (>->>) :: Functor f => P a' a b b' f r1 -> P b' b c c' f r2 -> P a' a c c' f (r1, r2)
+ Control.Quiver: (>->>) :: Functor f => P a a' b b' f r1 -> P b' b c c' f r2 -> P a a' c c' f (r1, r2)
- Control.Quiver: (>>->) :: Functor f => P a' a b b' f r1 -> P b' b c c' f r2 -> P a' a c c' f (r1, r2)
+ Control.Quiver: (>>->) :: Functor f => P a a' b b' f r1 -> P b' b c c' f r2 -> P a a' c c' f (r1, r2)
- Control.Quiver: consume :: a' -> (a -> P a' a b b' f r) -> Producer b b' f r -> P a' a b b' f r
+ Control.Quiver: consume :: a -> (a' -> P a a' b b' f r) -> Producer b b' f r -> P a a' b b' f r
- Control.Quiver: data P a' a b b' f r
+ Control.Quiver: data P a a' b b' f r
- Control.Quiver: decouple :: Functor f => P a' a b b' f r -> Producer b b' f r
+ Control.Quiver: decouple :: Functor f => P a a' b b' f r -> Producer b b' f r
- Control.Quiver: deliver :: r -> P a' a b b' f r
+ Control.Quiver: deliver :: r -> P a a' b b' f r
- Control.Quiver: deplete :: Functor f => P a' a b b' f r -> Consumer a' a f r
+ Control.Quiver: deplete :: Functor f => P a a' b b' f r -> Consumer a a' f r
- Control.Quiver: emit :: b -> P a' a b b' f (Maybe b')
+ Control.Quiver: emit :: b -> P a a' b b' f (Maybe b')
- Control.Quiver: emit_ :: b -> P a' a b b' f ()
+ Control.Quiver: emit_ :: b -> P a a' b b' f ()
- Control.Quiver: enclose :: f (P a' a b b' f r) -> P a' a b b' f r
+ Control.Quiver: enclose :: f (P a a' b b' f r) -> P a a' b b' f r
- Control.Quiver: fetch :: a' -> P a' a b b' f (Maybe a)
+ Control.Quiver: fetch :: Functor f => a -> P a a' b b' f (Maybe a')
- Control.Quiver: produce :: b -> (b' -> P a' a b b' f r) -> Consumer a' a f r -> P a' a b b' f r
+ Control.Quiver: produce :: b -> (b' -> P a a' b b' f r) -> Consumer a a' f r -> P a a' b b' f r
- Control.Quiver: qlift :: Functor f => f r -> P a' a b b' f r
+ Control.Quiver: qlift :: Functor f => f r -> P a a' b b' f r
- Control.Quiver: qpure :: (b' -> a') -> (a -> b) -> b' -> P a' a b b' f ()
+ Control.Quiver: qpure :: (b' -> a) -> (a' -> b) -> b' -> P a a' b b' f (Either a b)
- Control.Quiver: type Consumer a' a f r = forall b b'. P a' a b b' f r
+ Control.Quiver: type Consumer a a' f r = forall b b'. P a a' b b' f r
- Control.Quiver: type Effect f r = forall a' a b b'. P a' a b b' f r
+ Control.Quiver: type Effect f r = forall a a' b b'. P a a' b b' f r
- Control.Quiver: type Producer b b' f r = forall a' a. P a' a b b' f r
+ Control.Quiver: type Producer b b' f r = forall a a'. P a a' b b' f r
- Control.Quiver.Internal: [Consume] :: a' -> (a -> P a' a b b' f r) -> (Producer b b' f r) -> P a' a b b' f r
+ Control.Quiver.Internal: [Consume] :: a -> (a' -> P a a' b b' f r) -> (Producer b b' f r) -> P a a' b b' f r
- Control.Quiver.Internal: [Deliver] :: r -> P a' a b b' f r
+ Control.Quiver.Internal: [Deliver] :: r -> P a a' b b' f r
- Control.Quiver.Internal: [Enclose] :: (f (P a' a b b' f r)) -> P a' a b b' f r
+ Control.Quiver.Internal: [Enclose] :: (f (P a a' b b' f r)) -> P a a' b b' f r
- Control.Quiver.Internal: [Produce] :: b -> (b' -> P a' a b b' f r) -> (Consumer a' a f r) -> P a' a b b' f r
+ Control.Quiver.Internal: [Produce] :: b -> (b' -> P a a' b b' f r) -> (Consumer a a' f r) -> P a a' b b' f r
- Control.Quiver.Internal: consume :: a' -> (a -> P a' a b b' f r) -> Producer b b' f r -> P a' a b b' f r
+ Control.Quiver.Internal: consume :: a -> (a' -> P a a' b b' f r) -> Producer b b' f r -> P a a' b b' f r
- Control.Quiver.Internal: data P a' a b b' f r
+ Control.Quiver.Internal: data P a a' b b' f r
- Control.Quiver.Internal: decouple :: Functor f => P a' a b b' f r -> Producer b b' f r
+ Control.Quiver.Internal: decouple :: Functor f => P a a' b b' f r -> Producer b b' f r
- Control.Quiver.Internal: deliver :: r -> P a' a b b' f r
+ Control.Quiver.Internal: deliver :: r -> P a a' b b' f r
- Control.Quiver.Internal: deplete :: Functor f => P a' a b b' f r -> Consumer a' a f r
+ Control.Quiver.Internal: deplete :: Functor f => P a a' b b' f r -> Consumer a a' f r
- Control.Quiver.Internal: enclose :: f (P a' a b b' f r) -> P a' a b b' f r
+ Control.Quiver.Internal: enclose :: f (P a a' b b' f r) -> P a a' b b' f r
- Control.Quiver.Internal: produce :: b -> (b' -> P a' a b b' f r) -> Consumer a' a f r -> P a' a b b' f r
+ Control.Quiver.Internal: produce :: b -> (b' -> P a a' b b' f r) -> Consumer a a' f r -> P a a' b b' f r
- Control.Quiver.Internal: type Consumer a' a f r = forall b b'. P a' a b b' f r
+ Control.Quiver.Internal: type Consumer a a' f r = forall b b'. P a a' b b' f r
- Control.Quiver.Internal: type Effect f r = forall a' a b b'. P a' a b b' f r
+ Control.Quiver.Internal: type Effect f r = forall a a' b b'. P a a' b b' f r
- Control.Quiver.Internal: type Producer b b' f r = forall a' a. P a' a b b' f r
+ Control.Quiver.Internal: type Producer b b' f r = forall a a'. P a a' b b' f r
Files
- quiver.cabal +3/−2
- src/Control/Quiver.lhs +51/−51
- src/Control/Quiver/Internal.lhs +25/−26
- src/Control/Quiver/SP.lhs +105/−0
quiver.cabal view
@@ -1,5 +1,5 @@ name: quiver-version: 0.0.0.6+version: 0.0.0.7 synopsis: Quiver finite stream processing library homepage: https://github.com/zadarnowski/quiver category: Control@@ -35,7 +35,7 @@ source-repository this type: git location: https://github.com/zadarnowski/quiver.git- tag: 0.0.0.6+ tag: 0.0.0.7 library hs-source-dirs: src@@ -45,6 +45,7 @@ exposed-modules: Control.Quiver Control.Quiver.Internal+ Control.Quiver.SP build-depends: base >= 4.8 && < 5
src/Control/Quiver.lhs view
@@ -13,66 +13,56 @@ > module Control.Quiver ( > -- Imported from @Control.Quiver.Internal@:-> P, SP, Consumer, Producer, Effect,+> P, Consumer, Producer, Effect, > consume, produce, enclose, deliver, > decouple, deplete, > -- Defined below:-> fetch, fetch',-> emit, emit', emit_,+> fetch, fetch_,+> emit, emit_, > qlift,-> qpure, qpure_, qid,-> qconcat, qconcat_,+> qpure, qid, qconcat, > runEffect,-> (>>->), (>->>),+> (>>->), (>->>), (>&>),+> qcompose, > ) where > import Control.Quiver.Internal -> infixl 0 >>->, >->>+> infixl 0 >>->, >->>, >&> > -- | @fetch x@ represents a singleton stream processor that > -- sends the request value @x@ upstream and delivers the > -- next input value received, or @Nothing@ if the upstream > -- processor has been depleted. -> fetch :: a' -> P a' a b b' f (Maybe a)+> fetch :: Functor f => a -> P a a' b b' f (Maybe a') > fetch x = consume x (deliver . Just) (deliver Nothing) -> -- | @fetch' x q@ represents a singleton stream processor that-> -- sends the request value @x@ upstream and delivers the next-> -- input value received, or, if the upstream processor has-> -- been depleted, continues with the decoupled processor @q@.+> -- | @fetch_ x@ represents a singleton stream processor that+> -- sends the request value @x@ upstream, discarding any+> -- input received, for symmetry with @emit_@. -> fetch' :: a' -> Producer b b' f a -> P a' a b b' f a-> fetch' x q = consume x deliver q+> fetch_ :: a -> P a a' b b' f ()+> fetch_ x = consume x (deliver . const ()) (deliver ()) > -- | @emit y@ represents a singleton stream processor that > -- produces a single output value @y@ and delivers the > -- response received from the downstream processor, or > -- @Nothing@ if the downstream processor has been decoupled. -> emit :: b -> P a' a b b' f (Maybe b')+> emit :: b -> P a a' b b' f (Maybe b') > emit y = produce y (deliver . Just) (deliver Nothing) -> -- | @emit' y q@ represents a singleton stream processor that-> -- produces a single output value @y@ and delivers the-> -- response received from the downstream processor, or,-> -- if the downstream processor has been decoupled, continues-> -- with the depleted processor @q@.--> emit' :: b -> Consumer a' a f b' -> P a' a b b' f b'-> emit' y q = produce y deliver q--> -- | @emit' y q@ represents a singleton stream processor that+> -- | @emit_ y@ represents a singleton stream processor that > -- produces a single output value @y@, ignoring any response > -- received from the downstream processor. -> emit_ :: b -> P a' a b b' f ()+> emit_ :: b -> P a a' b b' f () > emit_ y = produce y (deliver . const ()) (deliver ()) > -- | @qlift@ lifts the value of a base functor into a stream processor. -> qlift :: Functor f => f r -> P a' a b b' f r+> qlift :: Functor f => f r -> P a a' b b' f r > qlift = enclose . fmap deliver > -- | @qpure g f z@ produces an infinite consumer/producer that@@ -81,21 +71,11 @@ > -- into an upstream request; the initial request is obtained > -- by applying @g@ to the initial response value @z@. -> qpure :: (b' -> a') -> (a -> b) -> b' -> P a' a b b' f ()+> qpure :: (b' -> a) -> (a' -> b) -> b' -> P a a' b b' f (Either a b) > qpure g f = cloop > where-> cloop y = let y' = g y in consume y' ploop (deliver ())-> ploop x = let x' = f x in produce x' cloop (deliver ())--> -- | @qpure_ f@ produces an infinite consumer/producer that-> -- uses a pure function @f@ to convert every input value into-> -- an output; equivalent to @qpure id f (const ())@.--> qpure_ :: (a -> b) -> SP a b f ()-> qpure_ f = cloop-> where-> cloop = consume () ploop (deliver ())-> ploop x = produce (f x) (const cloop) (deliver ())+> cloop y = let y' = g y in consume y' ploop (deliver (Left y'))+> ploop x = let x' = f x in produce x' cloop (deliver (Right x')) > -- | A pull-based identity processor, equivalent to 'qpure id id'. @@ -116,15 +96,6 @@ > ploop ys (x:xs) = produce x (\y -> ploop (y:ys) xs) (deliver (xs, reverse ys)) > ploop ys [] = cloop (reverse ys) -> -- | A pull-based list flattening processor without requests.--> qconcat_ :: SP [a] a f [a]-> qconcat_ = cloop-> where-> cloop = consume () ploop (deliver [])-> ploop (x:xs) = produce x (const $ ploop xs) (deliver xs)-> ploop [] = cloop- > -- | Evaluates an /effect/, i.e., a processor that is both detached > -- and depleted and hence neither consumes nor produces any input, > -- returning its delivered value. The base functor must be a monad.@@ -144,7 +115,7 @@ > -- represents a non-commutative monad, any effects of @p2@ will be > -- observed before those of @p1@. -> (>>->) :: Functor f => P a' a b b' f r1 -> P b' b c c' f r2 -> P a' a c c' f (r1, r2)+> (>>->) :: Functor f => P a a' b b' f r1 -> P b' b c c' f r2 -> P a a' c c' f (r1, r2) > (Consume x1 k1 q1) >>-> p2 = consume x1 ((>>-> p2) . k1) (q1 >>-> p2) > (Produce y1 k1 q1) >>-> p2 = loop p2 > where@@ -166,7 +137,7 @@ > -- represents a non-commutative monad, any effects of @p1@ will be > -- observed before those of @p2@. -> (>->>) :: Functor f => P a' a b b' f r1 -> P b' b c c' f r2 -> P a' a c c' f (r1, r2)+> (>->>) :: Functor f => P a a' b b' f r1 -> P b' b c c' f r2 -> P a a' c c' f (r1, r2) > p1 >->> (Consume x2 k2 q2) = loop p1 > where > loop (Consume x1 k1 q1) = consume x1 (loop . k1) (loop' q1)@@ -180,3 +151,32 @@ > p1 >->> (Produce y2 k2 q2) = produce y2 ((p1 >->>) . k2) (p1 >->> q2) > p1 >->> (Enclose f2) = enclose (fmap (p1 >->>) f2) > p1 >->> (Deliver r2) = fmap (, r2) (deplete p1)++> -- | An infix version of @flip fmap@ with the same precedence and associativity+> -- as the stream processor composition operators '>->>' and '>>->', indended+> -- for idiomatic processing of composition deliverables using expressions+> -- such as @p >->> q >&> fst@.++> (>&>) :: Functor f => P a a' b b' f r -> (r -> r') -> P a a' b b' f r'+> (>&>) = flip fmap++> -- | The @qcompose f p q@ is precisely equivalent to @p >->> q >&> uncurry f@,+> -- but faster. A rewrite rule is included to replace applications of+> -- '>->>' followed by '>&>' into 'qcompose'.++> qcompose :: Functor f => (r1 -> r2 -> r) -> P a a' b b' f r1 -> P b' b c c' f r2 -> P a a' c c' f r+> qcompose ff p1 (Consume x2 k2 q2) = loop p1+> where+> loop (Consume x1 k1 q1) = consume x1 (loop . k1) (loop' q1)+> loop (Produce y1 k1 _) = qcompose ff (k1 x2) (k2 y1)+> loop (Enclose f1) = enclose (fmap loop f1)+> loop (Deliver r1) = fmap (ff r1) q2+> loop' (Consume _ _ q1) = loop' q1+> loop' (Produce y1 k1 _) = qcompose ff (k1 x2) (k2 y1)+> loop' (Enclose f1) = enclose (fmap loop' f1)+> loop' (Deliver r1) = fmap (ff r1) q2+> qcompose ff p1 (Produce y2 k2 q2) = produce y2 ((qcompose ff p1) . k2) (qcompose ff p1 q2)+> qcompose ff p1 (Enclose f2) = enclose (fmap (qcompose ff p1) f2)+> qcompose ff p1 (Deliver r2) = fmap (flip ff r2) (deplete p1)++> {-# RULES "qcompose/fmap" forall p q f . fmap f (p >->> q) = qcompose (curry f) p q #-}
src/Control/Quiver/Internal.lhs view
@@ -28,7 +28,7 @@ > {-# LANGUAGE RankNTypes, TupleSections #-} > module Control.Quiver.Internal (-> P (..), SP, Producer, Consumer, Effect,+> P (..), Producer, Consumer, Effect, > consume, produce, enclose, deliver, > decouple, deplete, > ) where@@ -37,24 +37,24 @@ Data Types ========== -> -- | The main Quiver /stream processor/ type @P a' a b b' f r@,+> -- | The main Quiver /stream processor/ type @P a a' b b' f r@, > -- representing a producer/consumer structure with /bidirectional/, > -- /bounded/ communication on both the upstream (consumer) and > -- downstream (producer) channel. The six type parameters have > -- the following intuitive meaning: > ---> -- * @a'@ is the type of a /request/ values sent by the stream+> -- * @a@ is the type of a /request/ values sent by the stream > -- processor to its upstream partner in order to receive the > -- next element of the input stream. > ---> -- * @a@ is the type of the actual information being consumed+> -- * @a'@ is the type of the actual information being consumed > -- by this stream processor (i.e., elements of its input stream.) > -- > -- * @b@ is the type of the actual information being produced > -- by this stream processor (i.e., elements of its output stream.) > -- > -- * @b'@ is the type of the /response/ values received from-> -- the downstream partner for each elemnet of the output+> -- the downstream partner for each element of the output > -- stream produced by this stream processor. > -- > -- * @f@ is the type of the stream processor's /base functor/;@@ -72,7 +72,7 @@ > -- only time will tell whether this generalisation has useful > -- applications in the real world. -> data P a' a b b' f r =+> data P a a' b b' f r = > -- | @Consume x k q@ represents a /consumer step/, in which > -- the request @x@ is sent upstream and the returned input@@ -81,7 +81,7 @@ > -- delivered its ultimate result, hence reaching the end > -- of processing), to the /decoupled continuation/ @q@. -> Consume a' (a -> P a' a b b' f r) (Producer b b' f r) |+> Consume a (a' -> P a a' b b' f r) (Producer b b' f r) | > -- | @Produce y k q@ represent a /producer step/, in which > -- the output value @y@ is sent downstream, and the returned@@ -90,56 +90,55 @@ > -- (i.e., delivered its ultimate result, hence reaching the end > -- of processing), to the /depleted continuation/ @q@. -> Produce b (b' -> P a' a b b' f r) (Consumer a' a f r) |+> Produce b (b' -> P a a' b b' f r) (Consumer a a' f r) | > -- | @Enclose@ allows for selective application of the base > -- functor @f@ the the remainder of the computation. -> Enclose (f (P a' a b b' f r)) |+> Enclose (f (P a a' b b' f r)) | > -- | @Deliver r@ completes processing of information, delivering > -- its ultimate result @r@. > Deliver r -> -- | A /simple processor/ with a unit request type and an unspecified-> -- response type:--> type SP a b f r = forall b' . P () a b b' f r- > -- | A Quiver /producer/, represented by a stream processor > -- with unspecified input types. -> type Producer b b' f r = forall a' a . P a' a b b' f r+> type Producer b b' f r = forall a a' . P a a' b b' f r > -- | A Quiver /consumer/, represented by a stream processor > -- with unspecified output types. -> type Consumer a' a f r = forall b b' . P a' a b b' f r+> type Consumer a a' f r = forall b b' . P a a' b b' f r > -- | A Quiver /effect/, represented by a stream processor > -- with unspecified input and output types. -> type Effect f r = forall a' a b b' . P a' a b b' f r+> type Effect f r = forall a a' b b' . P a a' b b' f r Instances ========= -> instance Functor f => Functor (P a' a b b' f) where+> instance Functor f => Functor (P a a' b b' f) where > fmap ff (Consume x k q) = Consume x (fmap ff . k) (fmap ff q) > fmap ff (Produce y k q) = Produce y (fmap ff . k) (fmap ff q) > fmap ff (Enclose f) = Enclose (fmap (fmap ff) f) > fmap ff (Deliver r) = Deliver (ff r)+> r <$ (Consume x k q) = Consume x ((r <$) . k) (r <$ q)+> r <$ (Produce y k q) = Produce y ((r <$) . k) (r <$ q)+> r <$ (Enclose f) = Enclose (fmap (r <$) f)+> r <$ (Deliver _) = Deliver r -> instance Applicative f => Applicative (P a' a b b' f) where+> instance Applicative f => Applicative (P a a' b b' f) where > pure = Deliver > (Consume x k q) <*> p = Consume x ((<*> p) . k) (q <*> decouple p) > (Produce y k q) <*> p = Produce y ((<*> p) . k) (q <*> deplete p) > (Enclose f) <*> p = Enclose (fmap (<*> p) f) > (Deliver r) <*> p = fmap r p -> instance Monad f => Monad (P a' a b b' f) where+> instance Monad f => Monad (P a a' b b' f) where > (Consume x k q) >>= kk = Consume x ((>>= kk) . k) (q >>= decouple . kk) > (Produce y k q) >>= kk = Produce y ((>>= kk) . k) (q >>= deplete . kk) > (Enclose f) >>= kk = Enclose (fmap (>>= kk) f)@@ -156,7 +155,7 @@ > -- delivered its ultimate result, hence reaching the end > -- of processing), to the /decoupled continuation/ @q@. -> consume :: a' -> (a -> P a' a b b' f r) -> Producer b b' f r -> P a' a b b' f r+> consume :: a -> (a' -> P a a' b b' f r) -> Producer b b' f r -> P a a' b b' f r > consume = Consume > -- | @produce y k q@ represent a /producer step/, in which@@ -166,19 +165,19 @@ > -- (i.e., delivered its ultimate result, hence reaching the end > -- of processing), to the /depleted continuation/ @q@. -> produce :: b -> (b' -> P a' a b b' f r) -> Consumer a' a f r -> P a' a b b' f r+> produce :: b -> (b' -> P a a' b b' f r) -> Consumer a a' f r -> P a a' b b' f r > produce = Produce > -- | @enclose@ allows for selective application of the base > -- functor @f@ the the remainder of the computation. -> enclose :: f (P a' a b b' f r) -> P a' a b b' f r+> enclose :: f (P a a' b b' f r) -> P a a' b b' f r > enclose = Enclose > -- | @deliver r@ completes processing of information, delivering > -- its ultimate result @r@. -> deliver :: r -> P a' a b b' f r+> deliver :: r -> P a a' b b' f r > deliver = Deliver @@ -190,7 +189,7 @@ > -- effectively converting @p@ into a producer processor that no longer > -- expects to receive any input. -> decouple :: Functor f => P a' a b b' f r -> Producer b b' f r+> decouple :: Functor f => P a a' b b' f r -> Producer b b' f r > decouple (Consume _ _ q) = q > decouple (Produce y k q) = Produce y (decouple . k) (decouple q) > decouple (Enclose f) = Enclose (fmap decouple f)@@ -201,7 +200,7 @@ > -- effectively converting @p@ into a consumer processor that will never > -- produce any more output. -> deplete :: Functor f => P a' a b b' f r -> Consumer a' a f r+> deplete :: Functor f => P a a' b b' f r -> Consumer a a' f r > deplete (Consume x k q) = Consume x (deplete . k) (deplete q) > deplete (Produce _ _ q) = q > deplete (Enclose f) = Enclose (fmap deplete f)
+ src/Control/Quiver/SP.lhs view
@@ -0,0 +1,105 @@+> -- | Module: Control.Quiver.SP+> -- Description: Simple stream processors+> -- Copyright: © 2015 Patryk Zadarnowski <pat@jantar.org>+> -- License: BSD3+> -- Maintainer: pat@jantar.org+> -- Stability: experimental+> -- Portability: portable+> --+> -- This module provides a definition of a /simple processor/+> -- with a unit request type and an unspecified acknowledgement+> -- type, together with a number of common combinators for their+> -- definitions.++> {-# LANGUAGE PatternSynonyms, RankNTypes, ScopedTypeVariables, TupleSections #-}++> module Control.Quiver.SP (+> SP,+> SPResult,+> pattern SPIncomplete,+> pattern SPComplete,+> pattern SPFailed,+> spfetch,+> sppure, spid, spconcat,+> spfold, spfoldl, spfoldr,+> ) where++> import Control.Quiver++> -- | A /simple processor/ with a unit request type and an unspecified+> -- response type:++> type SP a b f r = forall b' . P () a b b' f r++> -- | Simple processor result type.++> type SPResult e = Maybe (Maybe e)++> -- | Simple processor result value indicating premature termination of the consumer.++> pattern SPIncomplete = Nothing++> -- | Simple processor result value indicating successful processing of the entire input stream.++> pattern SPComplete = Just Nothing++> -- | Simple processor result value indicating unsuccessful processing of the input stream.++> pattern SPFailed e = Just (Just e)++> -- | @spfetch@ represents a singleton simple stream processor that+> -- sends the request value @x@ upstream and delivers the+> -- next input value received, or @Nothing@ if the upstream+> -- processor has been depleted.++> spfetch :: Functor f => SP a b f (Maybe a)+> spfetch = fetch ()++> -- | @sppure f@ produces an infinite consumer/producer that+> -- uses a pure function @f@ to convert every input value into+> -- an output; equivalent to @qpure id f (const ())@.++> sppure :: (a -> b) -> SP a b f ()+> sppure f = cloop+> where+> cloop = consume () ploop (deliver ())+> ploop x = produce (f x) (const cloop) (deliver ())++> -- | A simple identity processor, equivalent to 'sppure id'.++> spid :: SP a a f ()+> spid = cloop+> where+> cloop = consume () ploop (deliver ())+> ploop x = produce x (const cloop) (deliver ())++> -- | A simple list flattening processor requests.++> spconcat :: SP [a] a f [a]+> spconcat = cloop+> where+> cloop = consume () ploop (deliver [])+> ploop (x:xs) = produce x (const $ ploop xs) (deliver xs)+> ploop [] = cloop++> -- | A processor that folds an entire stream into a single value.++> spfold :: (Functor f, Monoid a) => SP a a f ()+> spfold = cloop mempty+> where+> cloop r = consume () (cloop . mappend r) (emit_ r)++> -- | A processor that folds an entire stream into a single value.++> spfoldl :: (b -> a -> b) -> b -> SP a b f ()+> spfoldl f = cloop+> where+> cloop r = consume () (cloop . f r) (emit_ r)++> -- | A processor that folds an entire stream into a single value.++> spfoldr :: (a -> b -> b) -> b -> SP a b f ()+> spfoldr f = cloop+> where+> cloop r = consume () (cloop . flip f r) (emit_ r)+