Re: [Haskell-cafe] [Pipes] Can pipes solve this problem? How?

2012-08-16 Thread Michael Snoyman
On Wed, Aug 15, 2012 at 9:54 PM, Daniel Hlynskyi abcz2.upr...@gmail.comwrote:

 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#L270
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] [Pipes] Can pipes solve this problem? How?

2012-08-16 Thread Mario Blažević

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



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] [Pipes] Can pipes solve this problem? How?

2012-08-15 Thread 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