pipes-parse 2.0.0 → 2.0.1
raw patch · 2 files changed
+69/−12 lines, 2 filesdep ~free
Dependency ranges changed: free
Files
- pipes-parse.cabal +2/−2
- src/Pipes/Parse.hs +67/−10
pipes-parse.cabal view
@@ -1,5 +1,5 @@ Name: pipes-parse-Version: 2.0.0+Version: 2.0.1 Cabal-Version: >=1.8.0.2 Build-Type: Simple License: BSD3@@ -30,7 +30,7 @@ HS-Source-Dirs: src Build-Depends: base >= 4 && < 5 ,- free >= 3.1 && < 3.5,+ free >= 3.1 && < 4.2, pipes >= 4.0 && < 4.1, transformers >= 0.2.0.0 && < 0.4 Exposed-Modules: Pipes.Parse
src/Pipes/Parse.hs view
@@ -8,8 +8,8 @@ * The monadic approach, using parser combinators - The top half of this module provides the list-like approach. The key idea- is that:+ The top half of this module provides the list-like approach, which is easier+ to use, but less powerful. The key idea is that: > -- '~' means "is analogous to" > Producer a m () ~ [a]@@ -64,10 +64,47 @@ `Producer` without concatenating elements together, preserving the laziness of the underlying 'Producer'. - The bottom half of this module contains the lower-level monadic parsing- primitives. These are more useful for `pipes` implementers, particularly- for building splitters. I recommend that application developers use the- list-like style whenever possible.+ The bottom half of this module lets you implement your own list-like+ transformations using monadic parsers.++ For example, if you wanted to repeatedly sum every 3 elements and yield the+ result, you would write:++> import Control.Monad (unless)+> import Pipes+> import qualified Pipes.Prelude as P+> import Pipes.Parse+>+> sum3 :: (Monad m, Num a) => Producer a (StateT (Producer a m ()) m) ()+> sum3 = do+> eof <- lift isEndOfInput+> unless eof $ do+> n <- lift $ P.sum (input >-> P.take 3)+> yield n+> sum3++ When you are done building the parser, you convert your parser to a+ list-like function using `evalStateP`:++> import Pipes.Lift (evalStateP)+>+> -- sum3' ~ (Num a) => [a] -> [a]+>+> sum3' :: (Monad m, Num a) => Producer a m () -> Producer a m ()+> sum3' p = evalStateP p sum3++ ... then apply it to the `Producer` you want to transform:++>>> runEffect $ sum3' (P.readLn >-> P.takeWhile (/= 0)) >-> P.print+1<Enter>+4<Enter>+5<Enter>+10+2<Enter>+0<Enter>+2+>>>+ -} {-# LANGUAGE RankNTypes #-}@@ -80,6 +117,7 @@ -- * Transformations takeFree,+ dropFree, -- * Joiners concat,@@ -107,12 +145,11 @@ import Control.Applicative ((<$>), (<$)) import qualified Control.Monad.Trans.Free as F-import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Free (FreeF(Pure, Free), FreeT(FreeT, runFreeT)) import qualified Control.Monad.Trans.State.Strict as S import Control.Monad.Trans.State.Strict ( StateT(StateT, runStateT), evalStateT, execStateT )-import Pipes (Producer, Pipe, await, yield, next, (>->), Producer')+import Pipes import Pipes.Lift (runStateP) import qualified Pipes.Prelude as P import Prelude hiding (concat, takeWhile)@@ -177,7 +214,7 @@ Pure r -> return r Free p -> do f' <- p- concat f'+ loop f' {-# INLINABLE concat #-} {-| Join a 'FreeT'-delimited stream of 'Producer's into a single 'Producer' by@@ -205,7 +242,7 @@ go1 f' {-# INLINABLE intercalate #-} --- | @(take n)@ only keeps the first @n@ functor layers of a 'FreeT'+-- | @(takeFree n)@ only keeps the first @n@ functor layers of a 'FreeT' takeFree :: (Functor f, Monad m) => Int -> FreeT f m () -> FreeT f m () takeFree = go where@@ -218,6 +255,26 @@ Free w -> return (Free (fmap (go $! n - 1) w)) else return () {-# INLINABLE takeFree #-}++{-| @(dropFree n)@ peels off the first @n@ layers of a 'FreeT'++ Use carefully: the peeling off is not free. This runs the first @n@+ layers, just discarding everything they produce.+-}+dropFree+ :: (Monad m) => Int -> FreeT (Producer a m) m r -> FreeT (Producer a m) m r+dropFree = go+ where+ go n ft+ | n <= 0 = ft+ | otherwise = FreeT $ do+ ff <- runFreeT ft+ case ff of+ Pure _ -> return ff+ Free f -> do+ ft' <- runEffect $ for f discard+ runFreeT $ go (n-1) ft'+{-# INLINABLE dropFree #-} {- $lowlevel @pipes-parse@ handles end-of-input and pushback by storing a 'Producer' in