假设我有一种机制可以进行长时间运算,而这些运算可以暂停并在以后继续执行:
sealed trait LongRunning[+R];
case class Result[+R](result: R) extends LongRunning[R];
case class Suspend[+R](cont: () => LongRunning[R]) extends LongRunning[R];
最简单的运行它们的方法是:
@annotation.tailrec
def repeat[R](body: LongRunning[R]): R =
body match {
case Result(r) => r
case Suspend(c) => {
// perhaps do some other processing here
println("Continuing suspended computation");
repeat(c());
}
}
问题在于如何创建这样的计算。假设我们想要实现一个尾递归阶乘函数,每10个循环暂停一次:
@annotation.tailrec
def factorial(n: Int, acc: BigInt): LongRunning[BigInt] = {
if (n <= 1)
Result(acc);
else if (n % 10 == 0)
Suspend(() => factorial(n - 1, acc * n))
else
factorial(n - 1, acc * n)
}
但是这个无法编译:
如何在非挂起调用中保留尾递归?error: could not optimize
@tailrec
annotated methodfactorial
: it contains a recursive call not in tail position
Suspend(() => factorial(n - 1, acc * n))
LongRunning
是偏函数单子! - Mysterious DanFree[() => _, R]
或者Free[ChunkOfData => _, R]
,在根本上都没有什么区别。 - Mysterious Dan