为什么没有选项有折叠方法?

我想知道为什么scala.Option没有像这样定义的方法fold

 fold(ifSome: A => B , ifNone: => B) 

相当于

 map(ifSome).getOrElse(ifNone) 

有没有比使用map + getOrElse更好?

你可以做:

 opt foldLeft (els) ((x, y) => fun(x)) 

要么

 (els /: opt) ((x,y) => fun(x)) 

(这两个解决scheme都会 根据价值 评估 els ,这可能不是你想要的。感谢Rex Kerr指出了这一点。)

编辑:

但是,你真正想要的是斯卡拉斯的变形 cata (基本上是一个fold ,不仅处理Some值,而且映射None部分,这是你所描述的)

 opt.cata(fun, els) 

定义为(其中value是pimped选项值)

 def cata[X](some: A => X, none: => X): X = value match { case None => none case Some(a) => some(a) } 

相当于opt.map(some).getOrElse(none)

虽然我应该说,只有在“更自然”的expression方式时才应该使用cata。 有很多情况下,一个简单的mapgetOrElse就足够了,尤其是当它涉及到可能链接大量的map 。 (当然,你也可以把function组合连锁在一起,这取决于你是想把重点放在function组合还是价值转换上。)

我个人觉得像cata这样以两个封闭为参数的方法经常是过度的。 你真的通过map + getOrElse获得可读性吗? 想想你的代码的新手:他们会做什么

 opt cata { x => x + 1, 0 } 

你真的觉得比这更清楚吗?

 opt map { x => x + 1 } getOrElse 0 

事实上,我会争辩说,对于那些古老的人来说,这两者都不是好事

 opt match { case Some(x) => x + 1 case None => 0 } 

与往常一样,额外的抽象不会给您带来好处,并且会产生相反的效果。

它最终被添加到Scala 2.10 ,带有签名fold[B](ifEmpty: => B)(f: A => B): B

正如Debilski所提到的,你可以使用Scalaz的OptionW.cata或者fold 。 正如贾森评论说,命名参数使这看起来不错:

 opt.fold { ifSome = _ + 1, ifNone = 0 } 

现在,如果对于某些Monoid[M] ,在None情况下你想要的值是mzero对于某些情况你有一个函数f: A => M ,你可以这样做:

 opt foldMap f 

所以,

 opt map (_ + 1) getOrElse 0 

 opt foldMap (_ + 1) 

就个人而言,我认为Option应该有一个apply方法,这将是变形。 这样你就可以做到这一点:

 opt { _ + 1, 0 } 

要么

 opt { some = _ + 1, none = 0 } 

事实上,对于所有的代数数据结构来说,这将是很好的。