【问题标题】:Why scala can't infer the type in a partial method?为什么scala不能在部分方法中推断类型?
【发布时间】:2011-08-19 17:58:11
【问题描述】:

看这个例子:

def hello(a:String, b:String) = println(a + ":" + b)
val m1 = hello("aaa", _ )
m1("bbb")

无法编译,需要在partial方法中添加类型:

val m1 = hello("aaa", _: String)

为什么scala不知道方法hello的第二个参数是String

【问题讨论】:

    标签: scala types partial-application


    【解决方案1】:

    Scala 的类型推断是基于流的。方法和函数需要显式参数类型,用于推断其他类型。参数类型不能从方法或函数体中推断出来。然而,有时,参数类型是从外部上下文中获知的,因此不必标记。两个例子,

    val f: String => Unit = hello("aaa", _)
    val s = Seq(1,2).map(_+1) // Seq[Int].map expects a function of Int argument type
    

    下面是 Martin Odersky 引用的关于 Scala 类型推断与 ML 和 Haskell 等相比的局限性。挑战包括 Scala 的重载、记录选择和子类型化,以及需要保持简单,

    Scala 没有 Hindley/Milner 类型推断的原因是 很难与重载( ad-hoc 变体,而不是类型类)、记录选择和子类型。 我并不是说不可能——存在许多扩展 合并这些功能;事实上,我对他们中的一些人感到内疚 我。我只是说很难让这项工作在 练习,需要有小类型的表达式,并且很好 错误信息。这也不是一个完结的案例——许多研究人员都 努力突破这里的界限(例如在 Remy's 多边基金)。但现在它是更好的类型推理与 更好地支持这些功能。您可以在两者之间做出权衡 方法。我们想与 Java 集成的事实使天平倾斜 支持子类型化,远离 Hindley/Milner。

    来源:Universal Type Inference is a Bad Thing下的评论。

    【讨论】:

      【解决方案2】:

      简单地说,Scala 使用参数类型来寻找合适的方法,而不是方法类型来推断参数的类型。

      要做你想做的事,它必须使用两个参数搜索对hello的所有可能调用,其中第一个参数String——可能包括隐式转换——然后,如果一个最具体的找到选项,使用它来推断第二个参数的类型。除了已经做的所有事情之外,它还必须这样做,从而进一步减慢已经相当慢的编译速度。并非不可能,但它不会那样做。

      【讨论】:

        【解决方案3】:

        这可能是因为此定义存在潜在的歧义,因为 hello 可能被重载。

        // inside some class context
        def hello(a:String, b:String) = println(a + ":" + b)
        def hello(a:String, b:Int) = println(a + ":" + b.toString)
        val m1 = hello("aaa", _ ) // which one to choose?
        

        请考虑,val m1 = hello("aaa", _) 不只是你可以做。您的班级可能有一个用户,正在做val my_hello = (new C).hello("aaa", _)。然后,您通过向原始字符串 hello 方法添加重载来破坏源代码兼容性,因为突然之间不再清楚应该做什么。

        我不确定这是唯一的原因,但肯定可以将其视为一种安全措施。

        【讨论】:

        • 但在我的代码中,只有一个hello 方法。你的意思是,类可以扩展,子类可以覆盖hello方法,破坏代码?
        • 我必须承认,我不确定子类化是否真的可行。但即使没有它,我认为始终需要类型注释会更加一致。否则,如果您选择添加重载,所有没有类型注释的代码都会突然中断。
        • 我很好奇为什么在这种情况下,m1 不仅仅是其参数类型的多态性。
        • vals 不能是多态的。但是你也不能说def m1[T] = hello("aaa", _:T )
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 2014-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多