2011-10-03 7 views
6

IO 모나드를 사용하고 싶습니다.스칼라즈의 입체 모나드 트래버스 _

그러나이 코드는 큰 파일과 함께 실행되지 않습니다. StackOverflowError가 나타납니다. -DXss 옵션을 시도했지만 동일한 오류가 발생합니다.

val main = for { 
    l <- getFileLines(file)(collect[String, List]).map(_.run) 
    _ <- l.traverse_(putStrLn) 
} yield() 

어떻게하면됩니까?


모든 요소가 출력되는 Iteratee를 작성했습니다.

def putStrLn[E: Show]: IterV[E, IO[Unit]] = { 
    import IterV._ 
    def step(i: IO[Unit])(input: Input[E]): IterV[E, IO[Unit]] = 
    input(el = e => Cont(step(i >|> effects.putStrLn(e.shows))), 
     empty = Cont(step(i)), 
      eof = Done(i, EOF[E])) 
    Cont(step(mzero[IO[Unit]])) 
} 
val main = for { 
    i <- getFileLines(file)(putStrLn).map(_.run) 
} yield i.unsafePerformIO 

이것은 동일한 결과입니다.

IO 구현으로 인해 발생한다고 생각합니다.

+1

첫 번째 질문은 * 왜/*이 큰 파일을 실행하지 않는 당신은 어떻게을 받고있다 스택 오버플로 오류, 메모리 부족 오류 또는 다른 것? –

+1

StackOverflowError가 나타납니다. 나는 -DXss 옵션을 시도했지만 같은 오류가 발생했습니다. –

+0

동의, 나는 IO 모나드가 약간의 도전을 추가한다고 생각한다. – huynhjl

답변

4

scalac은 꼬리 전화의 경우 loop 안에 getReaderLines을 최적화하지 않았기 때문입니다. loop 꼬리 재귀하지만 익명 함수 구문 case 것 같아요.

: 사실 꼬리 재귀 (IO 모나드의 줄 바꿈)로 인해 재귀 호출 후 적어도 하나 이상의 호출이 발생하지 않습니다. 어제 테스트를 할 때도 비슷한 코드를 사용했지만 IO 모나드를 삭제 했으므로 Iteratee 꼬리를 재귀 적으로 만들 수있었습니다. 아래 텍스트는 입출력 모나드가 없다고 가정합니다 ...

어제 iteratees를 실험하면서 우연히 발견되었습니다.

@annotations.tailrec 
def loop(it: IterV[String, A]): IO[IterV[String, A]] = it match { 
    // ... 
} 

우리는 아마도합니다 (scalaz 민속에게보고해야하며 향상 티켓 열려있을 수 있습니다 : 당신이 getFilesLinesgetReaderLines가 다시 구현해야 당분간 있도록 (도움이에 loop의 서명을 변경하는 생각 .) 스칼라에 대한

getReaderLines.loop에 희미하게 유사한 (코드)를 어떻게되는지 보여줍니다?

@annotation.tailrec 
def f(i: Int): Int = i match { 
    case 0 => 0 
    case x => f(x - 1) 
} 
// f: (i: Int)Int 

@annotation.tailrec 
def g: Int => Int = { 
    case 0 => 0 
    case x => g(x - 1) 
} 
/* error: could not optimize @tailrec annotated method g: 
it contains a recursive call not in tail position 
     def g: Int => Int = { 
         ^
*/ 
+0

개선 할 수 있도록 보고서를 보내주십시오! – AndreasScheinert