Scala 本地类型推断下划线表示法
Scala local type inference underscore notation
通过"Functional programming in 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 _))
}
size2 和 maximum2 方法编译得很好,但是 depth2 不推断键入最后一个函数。
编写方法如下:
def depth2[A](t: Tree[A]): Int = fold(t)((_) => 0)((a,b) => 1 + (a max b))
编译正常。
问:为什么 Scala 不能在第一个带有下划线符号的方法上推断出类型,而在第二个方法上可以推断出类型?是什么让其他方法编译得很好?
感谢您的帮助。
scalac 版本:2.11.4
原来,在第一个方法中删除括号,删除了所有编译错误,如下所示:
def depth2[A](t: Tree[A]): Int = fold(t)((_) => 0)((a,b) => 1 + a max b)
因此,下划线符号似乎总是选择最接近的范围来推断类型。
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
通过"Functional programming in 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 _))
}
size2 和 maximum2 方法编译得很好,但是 depth2 不推断键入最后一个函数。
编写方法如下:
def depth2[A](t: Tree[A]): Int = fold(t)((_) => 0)((a,b) => 1 + (a max b))
编译正常。
问:为什么 Scala 不能在第一个带有下划线符号的方法上推断出类型,而在第二个方法上可以推断出类型?是什么让其他方法编译得很好?
感谢您的帮助。
scalac 版本:2.11.4
原来,在第一个方法中删除括号,删除了所有编译错误,如下所示:
def depth2[A](t: Tree[A]): Int = fold(t)((_) => 0)((a,b) => 1 + a max b)
因此,下划线符号似乎总是选择最接近的范围来推断类型。
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