【发布时间】:2015-06-25 19:17:53
【问题描述】:
我在此模式匹配中添加类型注释只是为了我自己的理解。
@annotation.tailrec def run[A](io: IO[A]): A = {
io match {
case Return(a) => a
case Suspend(r) => r()
case FlatMap(x, f) => x match {
case Return(a) => run(f(a))
case Suspend(r) => run(f(r()))
case FlatMap(y, g) =>
run(y flatMap (a => g(a) flatMap f))
}
}
}
为什么这些类型注释会破坏尾递归检查?添加新的类型定义和类型注释后,我并没有清楚地看到代价高昂的新递归。
could not optimize @tailrec annotated method run: it contains a recursive call not in tail position
io match {
^
@annotation.tailrec def run[A](io: IO[A]): A = {
type rType = Unit => A
type fType = A => IO[A]
type gType = A => IO[A]
io match {
case Return(a: A) => a
case Suspend(r: rType) => r()
case FlatMap(x: IO[A], f: fType) => x match {
case Return(a: A) => run(f(a))
case Suspend(r: rType) => run(f(r()))
case FlatMap(y: IO[A], g: gType) =>
run(y flatMap (a => g(a) flatMap f))
}
}
}
匹配的案例类:
case class Return[A](a: A) extends IO[A]
case class Suspend[A](resume: () => A) extends IO[A]
case class FlatMap[A,B](sub: IO[A], k: A => IO[B]) extends IO[B]
只要省略类型注解,'a'的类型就在一行中
F.flatMap(r)((a: A) => run(f(a)))
必须是“任何”:
[error] found : A => F[A]
[error] required: Any => F[A]
[error] F.flatMap(r)((a: A) => run(f(a)))
这样编译:
F.flatMap(r)(a => run(f(a)))
奖金问题。
似乎不允许像这样与案例类中的函数进行模式匹配:
io match {
...
case Suspend(r: Unit => A) => r()
/* or */
case Suspend(r: () => A) => r()
...
}
这样编译:
io match {
...
case Suspend(r: Function0[A]) => r()
...
}
这是为什么?
由于类型擦除,这些类型注释最终不会有太大用处。在对这些类型进行注解后,我可以预期会看到如下编译器警告:
abstract type pattern ... is unchecked since it is eliminated by erasure
此代码来自“Scala 中的函数式编程”的第 13 章或 fpinscala.iomonad 包。 https://github.com/fpinscala/fpinscala
谢谢
【问题讨论】:
标签: scala annotations tail-recursion type-erasure