2016-12-15 7 views
2

도관을 사용하여 일부 데이터를 스트림 방식으로 구문 분석하고 있습니다. 스트림의 어느 시점에서 나는 매 12 번째 요소가 필요합니다. 이 작업을 수행하는 편리한 방법이 있습니까?도관 스트림의 모든 n 번째 요소를 유지하십시오.

나는 현재 명시 적으로 단지 첫 번째 요소 반환 (12 개) 요소를 기다리고 있어요 :

get12th :: Monad m => Conduit Int m Int 
get12th = loop 
    where 
    loop = do 
     v1 <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     _ <- await 
     case v1 of 
      Nothing -> return() 
      Just x -> do 
       yield x >> loop 

그것은 작동하지 않습니다,하지만이 그것을 할 수있는 가장 좋은 방법이 있는지 궁금 하군요.

+0

또한, 현재 하나를 전달하기 전에 더 많은 요소를 기다리고 있습니다 ('v1 <- await'는 하단에서 더 나을 것입니다 - trampoline 호출은'await'으로 시작해야한다는 사실을 처리 할 수 ​​있습니다) – Alec

+0

@Alec 당신이 말하는 것을 이해하고 해결책을 생각하고 있습니다. 그러나, 나는'v1 <- await'을 바닥으로 움직이는 것이 어떻게 문제를 해결하는지 보지 못한다. –

+0

여기에서 11 개의 요소를 기다렸다가 다음 요소를 보냈습니다 (11 개의 요소를 받기 전에!). 'v1 <- await'을 움직이면 곧바로'v1'을 보냅니다. – Alec

답변

2

덕분에, 나는 다음과 같은 솔루션에 왔어요 :

get12th :: Monad m => Conduit Int m Int 
get12th = loop 
    where loop = do 
      v <- await 
      case v of 
      Just x -> yield x >> CL.drop 11 >> loop 
      Nothing -> return() 

이 솔루션은 중복 기다리고 제거 할 수있는 drop 함수를 사용합니다. 다른 값을 기다리기 전에 먼저 값을 받으면 즉시 값을 반환합니다.

7

await 행을 제거하려면 replicateM_을 사용할 수 있습니다. 알렉, 차드 길버트와 마이클 Snoyman에

v1 <- await 
replicateM_ 11 await 
case v1 of 
    ... 
+3

['drop' 함수] (https://www.stackage.org/haddock/lts-7.13/conduit-1.2.8/Data-Conduit-List.html#v:drop)는 아마도 관련성이 있습니다. –

+0

@MichaelSnoyman 좋은 지적입니다! Drop은 아마도 메모리에 값을 저장할 필요가 없으므로 아마도 더 효율적입니다. 나는 replicateM_11이 기다리는 지 확신하지 못하지만. –

+1

@MichaelSnoyman 당신은 옳은 것 같습니다. 'drop' 함수가 가장 효율적인 것 같습니다. 복제본'await'을'replicateM_11 await'으로 바꾸면 성능에 부정적인 영향을 미칩니다. 'replicateM_11'을'Data.Conduit.List.drop 11'로 바꾸면 성능이 눈에 띄게 증가하는 것 같습니다. –