为什么折叠地狱任何



我使用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)

您的折叠函数fInt(Int, Int)组合在一起。它不能是关联的,因为f(x, f(y, z))f(f(x, y), z)不可能同时键入check:

  • 如果f(x, f(y, z))类型检查,则x: Intf(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

最新更新