[Pipes] Can pipes solve this problem? How?

Hello Cafe. 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. Code can be rewritten without hGetContent, but it is much less comprehensible: hTakeWhileNotFound str hdl = fmap reverse$ findStr str hdl [0] [] where findStr str hdl indeces acc = do c <- hGetChar hdl let newIndeces = [ i+1 | i <- indeces, i < length str, str!!i == c] if length str `elem` newIndeces then return (c : acc) else findStr str hdl (0 : newIndeces) (c : acc) So, the question is - can pipes (any package of them) be the Holy Grail in this situation, to both keep simple code and better deal with handles (do not close them specifically)? How?

On Wed, Aug 15, 2012 at 9:54 PM, Daniel Hlynskyi
Hello Cafe. 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. Code can be rewritten without hGetContent, but it is much less comprehensible:
hTakeWhileNotFound str hdl = fmap reverse$ findStr str hdl [0] [] where findStr str hdl indeces acc = do c <- hGetChar hdl let newIndeces = [ i+1 | i <- indeces, i < length str, str!!i == c] if length str `elem` newIndeces then return (c : acc) else findStr str hdl (0 : newIndeces) (c : acc)
So, the question is - can pipes (any package of them) be the Holy Grail in this situation, to both keep simple code and better deal with handles (do not close them specifically)? How?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
This is essentially what we do in wai-extra for multipart body parsing[1]. This code uses `conduit`. The tricky part is that you have to remember that the substring you're looking for might be spread across multiple chunks, so you need to take that into account. A simple approach would be: * If the search string is a substring of the current chunk, success. * If the end of the current chunk is a prefix of the search string, grab the next chunk, append the two, and repeat. (Note: there are more efficient approaches than appending.) * Otherwise, skip to the next chunk. * If no more chunks available, the substring was not found. Michael [1] https://github.com/yesodweb/wai/blob/master/wai-extra/Network/Wai/Parse.hs#L...

On 12-08-15 02:54 PM, Daniel Hlynskyi wrote:
Hello Cafe. 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 []
So, the question is - can pipes (any package of them) be the Holy Grail in this situation, to both keep simple code and better deal with handles (do not close them specifically)? How?
It's more complex than Pipes, but SCC gives you what you need. If you cabal install it, you have the choice of using the shsh executable on the command line to accomplish your task: $ shsh -c 'cat input-file.txt | select prefix (>! substring "search string")' or using the equivalent library combinators from Haskell code:
import System.IO (Handle, stdin) import Control.Monad.Coroutine (runCoroutine) import Control.Concurrent.SCC.Sequential
pipeline :: String -> Handle -> Producer IO Char () pipeline str hdl = fromHandle hdl >-> select (prefix $ sNot $ substring str)
hTakeWhileNotFound :: String -> Handle -> IO String hTakeWhileNotFound str hdl = fmap snd $ runCoroutine $ pipe (produce $ pipeline str hdl) (consume toList)
main = hTakeWhileNotFound "up to here" stdin >>= putStrLn
participants (3)
-
Daniel Hlynskyi
-
Mario Blažević
-
Michael Snoyman