我曾尝试使用此代码在LinkedList上实现foldLeft,一个是curried foldLeft2,另一个是foldLeft:
sealed trait LinkedList[+E] {
@tailrec
final def foldLeft[A](accumulator: A, f: (A, E) => A): A = {
this match {
case Node(h, t) => {
val current = f(accumulator, h)
t.foldLeft(current, f)
}
case Empty => accumulator
}
}
@tailrec
final def foldLeft2[A](accumulator: A)(f: (A, E) => A): A = {
this match {
case Node(h, t) => {
val current = f(accumulator, h)
t.foldLeft2(current)(f)
}
case Empty => accumulator
}
}
}
但是当我使用foldLeft时,似乎我需要为accumulator和item声明类型,但对于foldLeft2,我没有.有人可以解释为什么会这样吗?
class LinkedListSpecification extends Specification {
"linked list" should {
"foldLeft correctly" in {
val original = LinkedList(1,2,3,4)
original.foldLeft(0, (acc: Int, item: Int) => acc + item) === 10
}
}
"linked list" should {
"foldLeft2 correctly" in {
val original = LinkedList(1,2,3,4)
original.foldLeft2(0)((acc, item) => acc + item) === 10
}
}
}
最佳答案 这是因为Scala中的类型推断跨参数列表从左到右工作.
因此,在第二版本foldLeft2中,它能够在继续到下一个参数列表之前将类型A推断为Int,其中它现在期望函数(Int,E)=> Int.
在第一个版本foldLeft中,它试图通过两个参数(累加器和f)同时推断A.它抱怨你传递给它的匿名函数,因为它还没有推断出类型A.