【问题标题】:Scala local type inference underscore notationScala 本地类型推断下划线表示法
【发布时间】:2016-01-10 12:36:59
【问题描述】:

通过“Scala 中的函数式编程”,我想知道为什么下面的代码会出现缺少参数类型的错误。

定义如下树形数据结构:

sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]

还有以下方法:

object Tree {

  def fold[A,B](t: Tree[A])(z: A => B)(f: (B,B) => B): B = t match {
    case Leaf(v) => z(v)
    case Branch(l,r) => f(fold(l)(z)(f), fold(r)(z)(f))   }

  def size2[A](t: Tree[A]): Int = fold(t)((_) => 1)(_ + _ + 1)

  def maximum2(t: Tree[Int]): Int = fold(t)((a) => a)(_ max _)

  def depth2[A](t: Tree[A]): Int = fold(t)((_) => 0)(1 + (_ max _))

}

size2maximum2 方法编译得很好,但是 depth2 不能推断最后一个函数的类型。

方法如下:

def depth2[A](t: Tree[A]): Int = fold(t)((_) => 0)((a,b) => 1 + (a max b))

让它编译得很好。

问:为什么 Scala 不能用下划线表示法推断第一种方法的类型,而用第二种方法推断类型?是什么让其他方法编译得很好?

感谢您的帮助。

scalac 版本:2.11.4

【问题讨论】:

标签: scala compilation compiler-errors functional-programming type-inference


【解决方案1】:

1 + (_ max _) 扩展为 1 + ((a, b) => a max b) 向 1 添加一个函数。如果您指定了类型,您会得到另一个错误:

<console>:22: error: overloaded method value + with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int <and>
(x: String)String
cannot be applied to ((Int, Int) => Int)
           def depth2[A](t: Tree[A]): Int = fold(t)((_) => 0)(1 + ((_: Int) max (_: Int)))

如您所见,您需要明确放置参数

(a,b) => 1 + (a max b)

或跳过括号

1 + _ max _

你实际上不能在这里做,因为它会像你说的那样工作

(a,b) => (1 + a) max b

【讨论】:

    【解决方案2】:

    事实证明,删除第一种方法中的括号,删除所有编译错误,如下所示:

    def depth2[A](t: Tree[A]): Int = fold(t)((_) => 0)((a,b) => 1 + a max b)
    

    因此,似乎下划线符号总是选择最接近的范围来推断类型。

    【讨论】:

      猜你喜欢
      • 2012-03-03
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2015-12-03
      • 2017-09-08
      • 1970-01-01
      • 1970-01-01
      • 2014-12-27
      相关资源
      最近更新 更多