-- | Type for "pipes", having multiple writers and readers. -- -- Each element (of type 'a') written to the pipe is "presented" to each reader (continuation) (of type @a -> r@). -- -- Elements and readers can be adder in any order. When a new element is added, it is presented to the existing readers. When a new reader is adder, it is presented with the existing elements. -- -- This type is used internally in the implementation of 'EarleyM', but it may be more widely useful. module EarleyM.Pipe( Pipe, empty, write, read, firstWrite, firstRead, elems, readers ) where import Prelude hiding (read,elem) -- | A "pipe" containing elements of type @a@, and readers of type @a -> r@. data Pipe a r = Pipe { -- | Get the elements of a pipe. elems :: [a], -- | Get the readers of a pipe. readers :: [a -> r] } empty :: Pipe a r -- | An empty pipe with no elements or readers. empty = Pipe { elems = [], readers = [] } -- | Create a pipe from a single element. firstWrite :: a -> Pipe a r firstWrite elem = Pipe { elems = [elem], readers = [] } -- | Create a pipe from a single reader. firstRead :: (a -> r) -> Pipe a r firstRead k = Pipe { elems = [], readers = [k] } -- | Write an element to a pipe, returning the new pipe and presentation results. write :: a -> Pipe a r -> (Pipe a r, [r]) write elem p = (Pipe (elem : elems p) (readers p) , rs) where rs = map (\k -> k elem) (readers p) -- | Attach a reader to a pipe, returning the new pipe and presentation results. read :: (a -> r) -> Pipe a r -> (Pipe a r, [r]) read k p = (Pipe (elems p) (k : readers p) , rs) where rs = map k (elems p)