Option.fold - 为什么它的第二个参数不是二元运算符?

时间:2014-10-17 11:16:15

标签: scala fold scala-option

我确定这是一个很好的理由,但我没有看到它。

(例如)Fold上的

List会返回

  

在所有元素和op

之间应用折叠运算符z的结果

它与foldLeftfoldRight有明显的关系,它们做同样的事情,但是定义了顺序(因此不需要关联运算符)

Fold上的

Option返回

  

如果f非空,则返回将scala.Option应用于此scala.Option值的结果。否则,计算表达式ifEmpty

ifEmpty是列表的z(位置)。 fop

的(位置)

对于None(使用我的Option心理模型作为"容器"可能包含或不包含值,是"空&#34 ;容器),一切正常,Option.fold返回零(ifEmpty的值)。

对于Some(x),不应该f采用两个参数zx,因此它与fold一致在序列上(包括与foldLeftfoldRight具有相似的关系。)

肯定是针对此的实用程序论点 - 让f在实践中将x作为参数可能更方便。在大多数情况下,如果确实需要忽略z。但是一致性也很重要......

所以有人可以向我解释为什么选项上的fold仍然是"正确的" fold

2 个答案:

答案 0 :(得分:2)

为什么会这样?

折叠“正常”采用二元运算符的原因是因为“正常”用于可以使用二元运算符(和种子值z)逐个处理的列表。

实际上,折叠选项是具有默认大小写的地图功能。如果你看一下它的定义,它的字面意思是:

if (isEmpty) ifEmpty else f(this.get)

由于您只有一个可能的参数,因此f必须是一元运算符。有人可能会争辩有一个选项fold,它接受一个二元运算符,并在定义选项的情况下使用ifEmpty值作为种子,但是你的合理种子值和当选项为空时的合理值可能会大不相同。

正如有人所指出的,对于不同的结构,你需要不同的元素(例如树木),因为减少的“合理”应用具有不同的结构。

答案 1 :(得分:0)

scala.Option.fold是一个错误; API设计不佳。

Option {
  // This is equivalent to:  map f getOrElse ifEmpty.
  def fold[B](ifEmpty: => B)(f: A => B): B = if (isEmpty) ifEmpty else f(this.get)
}

Option.fold方法可能很方便,但它不是fold(同样适用于Either.fold)。

TraversableOnce {
  // List, et alia
  def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)
}

标准方法的好处是概念和类型签名是一致的(无需再次审阅文档)。

此外,Option.foldLeft 一致,并且确实采用二元运算符。