【问题标题】:Is it possible to extend the Scala compiler to infer return types of recursive methods?是否可以扩展 Scala 编译器来推断递归方法的返回类型?
【发布时间】:2011-10-11 18:57:32
【问题描述】:

Scala 编译器目前无法推断递归方法的返回类型,如下代码所示

def foo(i:Int) = if (i > 0) foo (i-1) else 0

上述说法有歧义吗? (即,除了Int 之外的任何类型都可能吗?)

我可以想象,在更复杂的例子中,很难推断出类型。

是否有可能进一步描述我们可以(不能)推断类型的递归方法的情况?

[编辑:] 编译器足够聪明,可以发现 String 不正确。

scala> def foo(i:Int):String = if (i > 0) foo (i-1) else 0
<console>:5: error: type mismatch;
found   : Int(0)
required: String

【问题讨论】:

  • 我猜Double 是另一种可能的类型。
  • @Jus12 foo: Double 是可能的,就像将def f = 2 声明为: Double 一样。然而,编译器将def f = 2 推断为: Int。出于与您的示例相同的原因,合理的递归类型推断器不会假定 foo: Double

标签: scala


【解决方案1】:

如果你的递归调用总是在最后一个位置,即它的值从不使用并且只返回,那么应该可以将类型确定为所有其他分支的公共超类型。

但是,在这样的情况下

def foo(i: Int) = if (i > 0) foo(i - 1) + 1 else 0

你不会知道foo(i - 1) + 1 的类型(或者理解+ 的操作,因为它实际上是foo 上的一个方法——在对象存在的情况下事情变得更加复杂)而不知道foo 是什么.所以,你又在绕圈子了。

【讨论】:

    【解决方案2】:

    您需要一种比 Scala 提供的更强大的统一算法。 Scala 会从左到右、从上到下进行类型检查。所以推断会有点像这样:

    What is the type of expression "if (i > 0) foo(i - 1) + 1 else 0"?
    Unify "foo(i - 1) + 1" and "0"
    What is the type of "foo(i - 1) + 1"?
    What is the type of "foo(i - 1)"
    What is "foo"?
    foo is the current definition, so we don't know it's type
    error
    

    如果您以相反的方式执行if,您将拥有:

    What is the type of expression "if (i <= 0) 0 else foo(i - 1) + 1 "?
    Unify "0" and "foo(i - 1) + 1"
    What is the type of "0"?
    "0" <: Int >: Nothing
    What is the type of "foo(i - 1) + 1"?
    What is the type of "foo(i - 1)"
    What is "foo"?
    foo is the current definition, so we don't know it's type
    error
    

    【讨论】:

    • 很好地解释了 Scala 编译器如何推断类型。
    猜你喜欢
    • 1970-01-01
    • 2018-08-22
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    相关资源
    最近更新 更多