【问题标题】:Why can't scala infer the type of the omitted parameters in partial application?为什么scala不能推断部分应用中省略参数的类型?
【发布时间】:2012-10-11 16:59:28
【问题描述】:

考虑一下:

scala> def sum(x:Int,y:Int) = x+y
sum: (x: Int, y: Int)Int

scala> sum(1,_:String)
<console>:9: error: type mismatch;
 found   : String
 required: Int
              sum(1,_:String)

显然 Scala 非常清楚 sum(1,_)_ 的确切类型,但您必须 say sum(1,_:Int)。为什么 ?

显然 Scala 随机(?)选择了一个:

scala> def sum(x:Int,y:String) = 1
sum: (x: Int, y: String)Int

scala> def sum(x:Int,y:Double) = 1
sum: (x: Int, y: Double)Int

scala> class Ashkan
defined class Ashkan

scala> sum(1,_:Ashkan)
<console>:10: error: type mismatch;
 found   : Ashkan
 required: Double
              sum(1,_:Ashkan)

【问题讨论】:

  • 我相信this will 会回答你的问题吗?

标签: scala type-inference currying partial-application


【解决方案1】:

从这个issue 来看,听起来他们可以做到,但对于一般情况而言,相对于它所提供的好处而言,它太复杂了。它通常很复杂的原因是重载方法的可能性。如果您还拥有:

def sum (x : Int , y : Double ) = x + y

在范围内,如果没有类型规范,您所指的功能将是模棱两可的。在没有重载的情况下,类型推断可以很容易地弄清楚,但我觉得他们不觉得为这种特定情况提供服务是值得的。

简而言之,这听起来像是一种实践,而不是理论限制。

我相信错误消息是通过简单地获取具有适当名称和数量的第一个函数生成的,在非重载函数的情况下,它给人的印象是它已经完全推理出类型。

【讨论】:

  • 无论如何要确定最后一段(+1)?
  • @ashy_32bit 我通过在同一范围内定义函数的 (Int,Int) 版本和 (Int,Double) 版本来非正式地测试了这一点。当仅定义 (Int,Int) 版本时,错误消息引用了它。定义 (Int,Double) 版本后,错误消息引用了该版本。我从中推断,它只是在出错时选择一个(可能是最近定义的一个)。
【解决方案2】:

我建议它是 The Good Book 中这个侧边栏或框的扩展,它表达了最小惊喜原则:

http://www.artima.com/pins1ed/functions-and-closures.html#8.7

或者我们不叫它“最小的惊喜”,而是两个惊喜中较小的一个。

考虑以下情况,您要求编译器在两个继承的函数之间进行选择。如果应用正常的重载规则,它将选择子类中定义的方法。但这是一个好政策吗?

scala> class Foo {
     | def f(x: Int, y: Int) = x + y
     | }
defined class Foo

scala> class Bar extends Foo {
     | def f(x: Int, y: String) = x + y.toInt
     | }
defined class Bar

scala> class Baz extends Bar {
     | val f = super.f(1, _) // overloading says f(Int,String), did you mean it?
     | }

在一个面向对象的世界里,有太多的方式可以让自己感到惊讶,所以要交一点税。理智税。

(请注意,在此示例中,可能会启动重载分辨率,但通过要求您指定 f(1, _: MyWhatever),我们已经定义了适用性的含义。)

【讨论】:

  • +1 用于将继承引入其中。现在我知道它有多复杂了。
【解决方案3】:

this question 的答案是否对您有所启发?正如@oxbow_lakes 的answer 所证明的那样,这似乎是一种不一致。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 2010-11-14
    • 1970-01-01
    • 2019-02-11
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多