2015-11-29 34 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}'和堆栈安全性被保留。 –