Right, I think you are looping because you aren't dealing with the eof case, so it keeps spanning and breaking an empty stream.
You need something like 'next' in there somewhere. I think there are a number of places to do the inspection. The following is I think the same idea you had, formulated with pipes and streaming. import Pipes import qualified Pipes.Prelude as P import qualified Pipes.Parse as P import Streaming import qualified Streaming.Prelude as S import Lens.Simple import Data.List pFiltered start = do s0 <- view (P.span (\line -> not ("{-" `isPrefixOf` line))) start let s1 = view (P.span (\line -> not ("-}" `isSuffixOf` line))) s0 s2 <- lift $ runEffect $ s1 >-> P.drain e <- lift $ P.next s2 case e of Left r -> return r Right (_,s3) -> pFiltered s3 sFiltered start = do s0 <- S.break (\line -> "{-" `isPrefixOf` line) start let s1 = S.break (\line -> "-}" `isSuffixOf` line) s0 s2 <- lift $ S.effects s1 e <- lift $ S.next s2 case e of Left r -> return r Right (_,s3) -> sFiltered s3 main = do putStrLn "--------" runEffect $ pFiltered (each a) >-> P.stdoutLn putStrLn "--------" S.stdoutLn $ sFiltered (S.each a) putStrLn "--------" runEffect $ pFiltered (each b) >-> P.stdoutLn putStrLn "--------" S.stdoutLn $ sFiltered (S.each b) where a = [ "good" , "{- hi" , "bad" , "there -}" , "good" , "{- whoops" , "bad" , "unwhoops -}" , "good" , "{- start" , "bad" , "end -}" , "good" ] b = [] This gives me > main -------- good good good good -------- good good good good -------- -------- On Saturday, December 12, 2015 at 4:47:35 PM UTC-5, Mitchell Rosen wrote: > > Hi, > > I'm wondering if it's possible to use a pipes-like stream to express > "contextual" filtering of elements. For example, taking a simplistic view > of a block comment as a groups lines such that the first line that begins > with "{-" and the last line begins with "-}", I'd like to be able to filter > a stream like: > > [ "foo" > , "{- hi" > , "there -}" > , "bar" > , "{- whoops" > ] > > into > > [ "foo" > , "bar" > ] > > Using the *streaming *library (similar to pipes + pipes-group + > pipes-parse), my first attempt was something like: > > import Streaming > import qualified Streaming.Prelude as S > > filterBlockComments :: forall m r. Stream (Of String) m r -> Stream (Of > String) m r > filterBlockComments s0 = do > -- s0 == ["foo", "{- hi", "there -}", "bar", "{- whoops"] > > -- yield ["foo"], leaving > -- s1 == ["{- hi", "there -}", "bar", "{- whoops"] > s1 :: Stream (Of String) m r > <- S.span (\line -> not ("{-" `isPrefixOf` line)) s0 > > -- break s1 into (["{- hi"], ["there -}", "bar", "{- whoops"]), > -- then drop the first element of the second half, leaving > -- (["{- hi"], ["bar", "{- whoops"]) > let s2 :: Stream (Of String) m (Stream (Of String) m r) > s2 = fmap (S.drop 1) (S.break (\line -> "-}" `isSuffixOf` line) s1) > > -- run s2 without yielding its elements, leaving > -- s3 == ["bar", "{- whoops"] > s3 <- lift (S.effects s2) > > -- loop > filterBlockComments s3 > > However, this doesn't terminate, for reasons I haven't quite figured out > other than I'm doing streaming "wrong". So, is there a more idiomatic way > to write such a function? > > Thanks, > Mitchell > > > > -- You received this message because you are subscribed to the Google Groups "Haskell Pipes" group. To unsubscribe from this group and stop receiving emails from it, send an email to haskell-pipes+unsubscr...@googlegroups.com. To post to this group, send email to haskell-pipes@googlegroups.com.