斯卡拉:类型注解使尾递归检查失败 [英] Scala: type annotations make tail recursion check fail

查看:190
本文介绍了斯卡拉:类型注解使尾递归检查失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我添加类型注解这个模式匹配只是我自己的理解。

I'm adding type annotations to this pattern match just for my own understanding.

@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))
    }
  }
}

为什么这些类型注解打破尾递归检查?随着新的类型定义和类型标注添加的,我不很清楚地看到一个昂贵的新递归。

Why do these type annotations break the tail recursion check? With the new type definitions and type annotations added, I don't clearly see a costly new recursion.

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))
    }
  }
}

该案件对类所匹配:

The case classes being matched against:

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的行

As long as the type annotations are omitted, type of 'a' in line

 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)))


奖金问题。


Bonus question.

这似乎对案件类中的函数,模式匹配,像这样的,是不允许的:

It seems that pattern matching against a function inside a case class, like this, is not allowed:

io match {
  ...
  case Suspend(r: Unit => A) => r()
  /* or */
  case Suspend(r: () => A) => r()
  ...
}

这编译:

io match {
  ...
  case Suspend(r: Function0[A]) => r()
  ...
}

这是为什么?

这些类型的注释不会有,因为类型擦除到底有多大用途。注释这些类型后,我可以期待看到一个编译器警告是这样的:

These type annotations won't have much use in the end because of type erasure. After annotating these types, I can expect to see a compiler warning like this:

abstract type pattern ... is unchecked since it is eliminated by erasure


这code是第13章,或包装fpinscala.iomonad的斯卡拉函数式编程。 https://github.com/fpinscala/fpinscala

感谢

推荐答案

奖金的答案:
有很多关于类型擦除问题,看看<一个href=\"http://stackoverflow.com/questions/1094173/how-do-i-get-around-type-erasure-on-scala-or-why-cant-i-get-the-type-paramete\">How我避开类型擦除斯卡拉上?或者说,为什么我不能让我的藏品的类型参数?你可以写类似

Bonus answer: There are a lot of questions about type erasure, take a look at How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections? You can write something like

    case FlatMap(y: IO[A], g: gType@unchecked) if g.isInstanceOf[gType] =>

这篇关于斯卡拉:类型注解使尾递归检查失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆