2011-05-04 5 views
2

열거 자 -0.4.10을 사용하고 있고 수신 스트림의 서로 다른 부분을 다른 반복자에 배포해야합니다 (저는 거대한 XML 파일을 구문 분석하고 다른 하위 트리마다 다른 프로세싱 로직). 서브 트리가 교차하지 않기 때문에 한 번에 하나의 iteratee 만 활성화됩니다.필터링/브랜칭 열거 자

나는 스트림을 필터링하고 결과를 을 하나의 iteratee로 전달하는 간단한 예제를 작성했다. 아래를 봐주세요. 그러나 다중 중첩 된 iteratees를 사용하면 더 이상 열거자를 사용할 수 없다고 생각됩니다. 내가 다중 내부 iteratees을 보유하고 내 자신의 다중 enumeratee 쓸 필요합니까? 더 좋은 아이디어?

여기에 하나의 중첩 된 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에서 Data.Iteratee.sequence_Data.Iteratee.Parallel.psequence_ 같은 여러 iteratees에 스트림으로 전달하는 enumeratee이 필요합니다. sequence_은 반복 실행 목록을 동시에 실행하고 각 입력 청크를 해당 목록에서 mapM으로 처리합니다. psequence_은 비슷한 인수를 사용하지만 별도의 forkIO 스레드에서 각 입력 iteratee를 실행합니다.

지난 해에 haskell-cafe와 iteratee 메일 링리스트에 관한 토론이있었습니다. 예를 들어 http://www.haskell.org/pipermail/haskell-cafe/2011-January/088319.html주의 할 점은 inner iteratees의 오류를 처리하는 것입니다 : 애플리케이션에서 하나의 inner iteratee가 실패하면 모든 iteratees 또는 그 중 하나만 종료하고 [해당] 오류를 전파하려면 어떻게합니까?