package Pull(Pull(..), apply, tee, pass, passed, buffer, buffered, (»), pipe, sink, spew) where --@ \subsubsection{Pull} --@ --@ \index{Pull@\te{Pull} (interface type)|textbf} --@ The {\mbox{\te{Pull a}}} interface represents a stream that --@ produces values of type ``\te{a}'' only when ``pulled'' by a consumer. --@ --@ Modules with the Pull interface can be combined using --@ \te{»} to model computations that comprise several steps, --@ each of which may be buffered. --@ infixl 12 » --@ \begin{libverbatim} --@ interface Pull #(type a); --@ method ActionValue#(a) pull(); --@ endinterface: Pull --@ \end{libverbatim} interface Pull a = pull :: ActionValue a --@ Apply a function to the data in the stream. --@ \begin{libverbatim} --@ function Pull#(b) apply(function b f(a x1), Pull#(a) src); --@ \end{libverbatim} apply :: (a -> b) -> Pull a -> Pull b apply f src = interface Pull { pull = src.pull `bind` (return · f) } --@ Allow an action to peek at the stream. --@ \begin{libverbatim} --@ function Pull#(a) tee(function Action p(a x1), Pull#(a) src); --@ \end{libverbatim} tee :: (a -> Action) -> Pull a -> Pull a tee p src = interface Pull pull = do v :: a v <- src.pull p v return v --@ Wrap the stream in a module (without buffering). --@ \begin{libverbatim} --@ module pass#(Pull#(a) p)(Pull#(a)); --@ \end{libverbatim} pass :: (IsModule m c) => (Pull a) -> m (Pull a) pass p = module interface pull = p.pull --@ Apply a function to the data in the stream --@ and wrap the stream in a module (without buffering). --@ \begin{libverbatim} --@ module passed#(function b f(a x1))(Pull#(b)); --@ \end{libverbatim} passed :: (IsModule m c) => (a -> b) -> Pull a -> m (Pull b) passed f = pass · apply f --@ Wrap a stream in a module --@ (with a buffer initialized to the first argument). --@ \begin{libverbatim} --@ module buffer#(a init, Pull#(a) src)(Pull#(a)) --@ provisos (Bits#(a, sa)); --@ \end{libverbatim} buffer :: (IsModule m c, Bits a sa) => a -> Pull a -> m (Pull a) buffer init src = module r :: Reg a r <- mkReg init interface pull = do x :: a x <- src.pull action (r := x) return r --@ Apply a function to the data in the stream --@ and wrap the stream in a module --@ (with a buffer initialized to `\US'). --@ \begin{libverbatim} --@ module buffered#(function b f(a x1))(Pull#(b)) --@ provisos (Bits#(b, sb)); --@ \end{libverbatim} buffered :: (IsModule m c, Bits b sb) => (a -> b) -> Pull a -> m (Pull b) buffered f = buffer _ · apply f --@ A consumer that always pulls data from the given stream --@ and throws it away. --@ \begin{libverbatim} --@ module sink#(Pull#(a) p)(Empty); --@ \end{libverbatim} sink :: (IsModule m c) => Pull a -> m Empty sink p = module rules "sink": when True ==> p.pull --@ A producer of junk. --@ \begin{libverbatim} --@ module spew(Pull#(a)); --@ \end{libverbatim} spew :: (IsModule m c) => m (Pull a) spew = module interface { pull = return _ } --@ Combine two streams (e.g., \te{spew » sink}). (Note: in BSV the function --@ \te{pipe} must be used instead.) --@ \begin{libverbatim} --@ function m#(b) (»)() --@ provisos (Monad#(m)); --@ \end{libverbatim} (») :: (Monad m) => m a -> (a -> m b) -> m b (») = bind pipe :: (Monad m) => m a -> (a -> m b) -> m b pipe = bind