过滤/分支枚举

时间:2011-05-04 22:45:24

标签: haskell enumerator iterate

我正在使用枚举器-0.4.10,我需要分发处理 传入流的不同部分到不同的迭代(我是 解析一个巨大的XML文件,不同的子树有不同 处理逻辑)。一次只能激活一个iteratee 因为子树不相交。

我写了一个简单的例子来过滤流并传递结果 到一个迭代;请看下面。但是,有多个嵌套 在我看来,我不能再使用枚举。我 需要编写我自己的多枚举数,它包含多个内部 iteratees?有更好的想法吗?

这是我的(初学者)代码,用于单个嵌套的iteratee:

module Main ( main ) where

import qualified Data.Enumerator as E ( Enumeratee, Step(..), Stream(..),
  checkDone, checkDoneEx, continue, enumList, joinI, run_, yield )
import Data.Enumerator ( ($$), (>>==) )
import qualified Data.Enumerator.List as EL ( consume )

-- cribbed from EL.concatMap
concatMapAccum :: Monad m => (s -> ao -> (s, [ai])) -> s ->
E.Enumeratee ao ai m b
concatMapAccum f s0 = E.checkDone (E.continue . step s0)
  where
    step _ k E.EOF = E.yield (E.Continue k) E.EOF
    step s k (E.Chunks xs) = loop s k xs
    loop s k [] = E.continue (step s k)
    loop s k (x:xs) = case f s x of
      (s', ais) -> k (E.Chunks $ ais) >>==
        E.checkDoneEx (E.Chunks xs) (\k' -> loop s' k' xs)

passFromTo :: Monad m => ((a -> Bool), (a -> Bool)) -> Bool -> E.Enumeratee a a m b
passFromTo (from, to) pass0 =
  concatMapAccum updatePass pass0
    where
      updatePass pass el = case (pass, from el, to el) of
        (True, _, to_el) -> (not to_el, [el])
        (False, True, _) -> (True, [el])
        (False, False, _) -> (False, [])

main :: IO()
main = do
  E.run_ (E.enumList 3 [1..20] $$
    E.joinI $ passFromTo ((\e -> e == 3 || e == 13), (\e -> e == 7 || e == 17)) False $$
    EL.consume) >>= print

$ ./dist/build/StatefulEnumeratee/StatefulEnumeratee
[3,4,5,6,7,13,14,15,16,17]

1 个答案:

答案 0 :(得分:1)

是的,您需要一个枚举器,它将流传递给多个迭代器,例如来自iteratee-0.8.6的Data.Iteratee.sequence_Data.Iteratee.Parallel.psequence_sequence_获取一个迭代列表以同时运行,并在该列表中按mapM处理每个输入块。 psequence_采用类似的参数,但在一个单独的forkIO线程中运行每个输入iteratee。

在过去的一年里,有一些关于haskell-cafe和iteratee邮件列表的讨论,例如:http://www.haskell.org/pipermail/haskell-cafe/2011-January/088319.html要注意的主要事情是处理来自内部迭代的错误:在你的应用程序中,如果一个内部迭代失败你想要终止所有迭代或只是那个,并且[你如何]传播这些错误。