2015-11-29 31 views
1

以下代碼將流構造爲由flatMap平坦化的流。問題是迭代結果流時它不安全。什麼是這個代碼的堆棧安全等價物?scalaz的堆棧安全性StreamT的flatMap

import scalaz.Id._ 
import scalaz.StreamT 

object StreamOverflow extends App { 

    def streams(branchingFactor: Int, depth: Int): StreamT[Id, Int] = { 
    if(depth == 0) { 
     StreamT.empty 
    } else { 
     StreamT.fromIterable(1 to branchingFactor) flatMap { _ => 
     streams(branchingFactor, depth-1) } 
    } 
    } 

    streams(10, 10) foreach { _ => } // stack overflow 
} 

我正在使用scalaz 7.2.0-RC1。

回答

2

可以使用Trampoline代替Id

import scalaz.Id.Id 
import scalaz.{ StreamT, ~> } 
import scalaz.Free.Trampoline 
import scalaz.syntax.applicative._ 

object trampolineId extends (Id ~> Trampoline) { 
    def apply[A](i: A): Trampoline[A] = i.point[Trampoline] 
} 

def streams(branchingFactor: Int, depth: Int): StreamT[Trampoline, Int] = 
    if (depth == 0) StreamT.empty else { 
    StreamT.fromIterable(1 to branchingFactor).trans(trampolineId).flatMap { _ => 
     streams(branchingFactor, depth - 1) 
    } 
    } 

現在像streams(10, 10).foreach(_ =>().point[Trampoline]).run可能會爲一個很長很長的時間運行,但它不應該使棧溢出。

+0

謝謝!我認爲堆棧安全將以某種方式構建到'StreamT'中。我會補充說,我可以通過'def hideTrampoline [A](stream:StreamT [Trampoline,A])來隱藏'Trampoline':StreamT [Id,A] = StreamT.unfold [A,StreamT [Trampoline,A]] (流){_.uncons.run}'和堆棧安全性被保留。 –