Skip to content

Instantly share code, notes, and snippets.

@Davorak
Last active December 17, 2015 23:48
Show Gist options
  • Save Davorak/5691458 to your computer and use it in GitHub Desktop.
Save Davorak/5691458 to your computer and use it in GitHub Desktop.
Examples of resumable parsers with pipes-parse a Haskell package. Each example explains its purpose in the comments above it.
import Control.Proxy
import Control.Proxy.Trans.State
import Control.Proxy.Parse
import Control.Monad
chunkLine'
:: (Monad m, Proxy p) =>
() -> StateP [Char] p () (Maybe Char) a [Char] m ()
chunkLine' () = loop
where
loop = do
as <- (passWhile (/='\n') >-> evalStateK mempty drawAll) ()
endOfLine <- (draw) -- remove '\n'
case endOfLine of
Nothing -> (unDraws) (reverse as) >> return ()
Just '\n' -> do
respond as
eof <- isEndOfInput
unless eof loop
unDraws :: (Monad m, Proxy p) => [a] -> StateP [a] p x' x y' y m ()
unDraws = mapM_ unDraw
{- | Chunk a stream of `Char`s in to lines leaving unfinished lines in the
- buffer. Then resume pipeline with new input.
-
- >>> main
- "Take steam of `Char`s and chunk them into lines until end of in put saving leftovers"
- "hi"
- "you"
- "there"
- "Now rerun the pipe with saved buffers and the extra input \"hi\nyou\nthere\nnow\""
- "now"
- "how's"
- "life"
- ((),"")
-}
example1 = do
print "Take steam of `Char`s and chunk them into lines until end of in put saving leftovers"
(_, buffers) <- runProxy
$ runStateK mempty
$ wrap . (fromListS "hi\nyou\nthere\nnow")
>-> wrap . (chunkLine') >-> unwrap >-> printD
putStrLn $ "The buffers currently are: " ++ show buffers
print "Now rerun the pipe with saved buffers and the extra input \"hi\nyou\nthere\nnow\""
runProxy $ runStateK "now"
$ wrap . (fromListS "\nhow's\nlife\n")
>-> wrap . (chunkLine') >-> unwrap >-> printD
-- | Fake function to count spelling errors on a line
countSpellingErrors x = length x `div` 3
partition ln overlap () = loop
where
loop = do
mes <- drawN ln ()
case mes of
Nothing -> return ()
Just es -> do
mapM unDraw $ drop (ln - overlap) es
respond es
eof <- isEndOfInput
unless eof loop
{- | drawN n pulls n items from the stream if it fails in drawing n items it
- pushes them back to the stream.
-}
drawN n0 () = loop n0 []
where
loop 0 as = return $ Just (reverse as)
loop n as = do
ma <- draw
case ma of
Nothing -> unDraws as >> return Nothing
Just a -> loop (n - 1) (a:as)
{- | Chunk a stream of `Char`'s into lines. Transform into a stream of spelling
- errors per line then partition stream with n-1 overlap for later convolution.
-
- > example2
- "Chunk steam of `Char`s into lines, transform into a stream of spelling per line then partition into list of 2 with 1(n - 1) overlap for latter convolution."
- [2,3]
- [3,5]
- The buffers currently are: ("ow",[5])
- "Continue parsing with both old buffers and new input."
- [5,3]
- [3,5]
- [5,4]
- [4,9]
- ((),("",[9]))
-}
example2 = do
print "Chunk steam of `Char`s into lines, transform into a stream of spelling per line then partition into list of 2 with 1(n - 1) overlap for latter convolution."
(_, buffers) <- runProxy $ runStateK mempty
$ wrap . (fromListS "hi\nyou\nthere\now")
>-> wrap . (zoom _fst . chunkLine')
>-> fmapPull (mapD length)
>-> (zoom _snd . partition 2 1)
>-> printD
putStrLn $ "The buffers currently are: " ++ show buffers
print "Continue parsing with both old buffers and new input."
runProxy $ runStateK ("now",[5])
$ wrap . (fromListS "\nhow's\nlife\nrecently?\n")
>-> wrap . (zoom _fst . chunkLine')
>-> fmapPull (mapD length)
>-> (zoom _snd . partition 2 1)
>-> printD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment