[Haskell-cafe] Can pipes solve this problem? How?
oleg at okmij.org
oleg at okmij.org
Thu Aug 16 10:19:09 CEST 2012
> Consider code, that takes input from handle until special substring matched:
>
> > matchInf a res s | a `isPrefixOf` s = reverse res
> > matchInf a res (c:cs) = matchInf a (c:res) cs
> > hTakeWhileNotFound str hdl = hGetContents hdl >>= return.matchInf str []
>
> It is simple, but the handle is closed after running. That is not good,
> because I want to reuse this function.
This example is part of one of Iteratee demonstrations
http://okmij.org/ftp/Haskell/Iteratee/IterDemo1.hs
Please search for
-- Early termination:
-- Counting the occurrences of the word ``the'' and the white space
-- up to the occurrence of the terminating string ``the end''
The iteratee solution is a bit more general because it creates an
inner stream with the part of the outer stream until the match is
found. Here is a sample application:
run_bterm2I fname =
print =<< run =<< enum_file fname .| take_until_match "the end"
(countWS_iter `en_pair` countTHE_iter)
It reads the file until "the end" is found, and counts white space and
occurrences of a specific word, in parallel. All this processing
happens in constant space and we never need to accumulate anything
into string. If you do need to accumulate into string, there is
an iteratee stream2list that does that.
The enumeratee take_until_match, as take and take_while, stops when the
terminating condition is satisfied or when EOF is detected. In the
former case, the stream may contain more data and remains usable.
A part of IterDemo1 is explained in the paper
http://okmij.org/ftp/Haskell/Iteratee/describe.pdf
I am not sure though if I answered your question since you were
looking for pipes. I wouldn't call Iteratee pipes.
More information about the Haskell-Cafe
mailing list