为啥折叠推断任何?

Posted

技术标签:

【中文标题】为啥折叠推断任何?【英文标题】:Why fold infers Any?为什么折叠推断任何? 【发布时间】:2021-06-17 03:24:04 【问题描述】:

我正在使用 Scala 2.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 中的第一个)中编写折叠时,我一直在处理类似的事情很多次,我总是找到一种不同的方法来使它工作,但也许如果我理解它,我将不再碰壁.

【问题讨论】:

相关***.com/questions/16111440/scala-fold-vs-foldleft 【参考方案1】:

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) 不可能同时进行类型检查:

如果f(x, f(y, z)) 类型检查,则x: Intf(y, z): (Int, Int), 但是,f的返回类型必须是(Int, Int), 但是,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))...)))))

(右折叠)

在你的情况下,它必须是foldLeft

Any 类型被推断为Int(Int, Int) 之间的最小上限,因为编译器试图将f 解释为关联操作,它必然具有两个相同的参数输入。

【讨论】:

【参考方案2】:

因为你需要使用foldLeft而不是折叠:

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
    
  

斯卡蒂:https://scastie.scala-lang.org/VzfKqHZ5QJyNPfwpLVGwSw

fold 不起作用,因为它是语义的:fold[A1 &gt;: A](z: A1)(op: (A1, A1) =&gt; A1): A1 - 因此在你的情况下,zipWithIndex 给出了(Int, Int) 类型而不是预期的Int,并且函数内部返回Int - 所以最后推断类型你看 Any - (Int, Int)Int 之间的共同祖先。

foldLeft[Z](zero: Z) 推断出Int 因为你给了0

【讨论】:

最好解释一下foldfoldLeft 之间的区别以及为什么会导致Any 类型。 @LuisMiguelMejíaSuárez 几乎完成了,谢谢!

以上是关于为啥折叠推断任何?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用vi编辑器Linux打开时行折叠

为啥 TreeView 控件会折叠所有子节点?

为啥 UIStackView 不断折叠标签?

为啥 Bootstrap Navbar 总是折叠? [复制]

为啥需要使用合并来折叠/展开以进行条件插入?

为啥边框折叠在 html2pdf 中不起作用?