2011-05-04 82 views
2

我使用的是枚舉器-0.4.10,我需要將處理的 傳入流的不同部分分配給不同的迭代(我是 解析一個巨大的XML文件,並且不同的子樹有不同的 處理邏輯)。由於子樹不相交,因此只有一個迭代器在 時激活。過濾/分支枚舉

我寫了一個簡單的例子,過濾流並將結果 傳遞給一個迭代器;請看下面。但是,對於多重嵌套的 迭代,我認爲我不能再使用枚舉器。 是否需要編寫自己的多重枚舉器來保存多個迭代器的內部 ?任何更好的想法?

下面是一個嵌套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

是的,你需要的是從流iteratee-0.8.6傳遞到多個iteratees,像Data.Iteratee.sequence_Data.Iteratee.Parallel.psequence_的enumeratee。 sequence_需要迭代列表同時運行,並通過該列表處理每個輸入塊mapMpsequence_採用類似的參數,但在單獨的forkIO線程中運行每個輸入迭代器。

在過去的一年中,haskell-cafe和iteratee郵件列表已經有一些關於這些的討論,例如:http://www.haskell.org/pipermail/haskell-cafe/2011-January/088319.html要小心處理的主要問題是處理來自內部迭代的錯誤:在您的應用程序中,如果一個內部迭代失敗是否要終止所有迭代或只是那一個,以及[你]如何傳播這些錯誤。