我使用Scala2.11.12进行编译,并且声明:
import scala.collection.mutable.Stack
def stackToInt(stack: Stack[Int]): Int =
stack.zipWithIndex.fold(0){ case (z: Int, (piece: Int, index: Int)) =>
piece match {
case 1 => (1 << index) + z
case _ => z
}
}
给出:
stack.zipWithIndex.fold(0){ case (z: Int, (piece: Int, index: Int)) =>
^
error: type mismatch;
found : Any
required: Int
当我在这个项目中编写折叠时,我已经处理过很多次这样的事情(第一次是在Scala中(,我总是找到一种不同的方法来实现它,但如果我理解了它,也许我会停止碰壁。
fold
方法期望一个关联二进制运算作为其第二个参数,即满足的某个运算f(_, _)
f(x, f(y, z)) = f(f(x, y), z)
您的折叠函数f
将Int
与(Int, Int)
组合在一起。它不能是关联的,因为f(x, f(y, z))
和f(f(x, y), z)
不可能同时键入check:
- 如果
f(x, f(y, z))
类型检查,则x: Int
和f(y, z): (Int, Int)
- 但是CCD_ 11的返回类型必须是CCD_
- 但是,
f(f(x, y), z)
不能进行类型检查,因为它在第一个参数中得到了(Int, Int)
,其中需要Int
因此,在这里谈论关联性是没有意义的:这种说法甚至不是错误的,它根本就不能被陈述。
由于操作不是关联的,所以不能简单地让语言来决定处理元素的顺序;必须选择折叠方向,即决定是否为
f(...f(f(f(a0, x1), x2), x3)...)
(折页左(
或
f(...f(x(n-3), f(x(n-2), f(x(n-1), a0))...)))))
(foldRight(
在您的情况下,它必须是foldLeft
。
类型Any
被推断为Int
和(Int, Int)
之间的最小上界,因为编译器试图将f
解释为关联运算,该运算必然具有相同类型的两个参数。
因为您需要使用foldLeft
而不是fold:
import scala.collection.mutable.Stack
def stackToInt(stack: Stack[Int]): Int =
stack.zipWithIndex.foldLeft(0) { case (z: Int, (piece: Int, index: Int)) =>
piece match {
case 1 => (1 << index) + z
case _ => z
}
}
Scatie:https://scastie.scala-lang.org/VzfKqHZ5QJyNPfwpLVGwSw
fold
不起作用,因为它是语义的:fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1
-因此在您的案例中,zipWithIndex
给出的是(Int, Int)
类型,而不是预期的Int
,并且里面的函数返回Int
-因此在推断类型的末尾,您可以看到Any
-(Int, Int)
和Int
之间的共同祖先。
foldLeft[Z](zero: Z)
已经推断出Int
,因为你给了0