[英]Why doesn't Option have a fold method?
我想知道為什么scala.Option
沒有像這樣定義的方法fold
:
fold(ifSome: A => B , ifNone: => B)
相當於
map(ifSome).getOrElse(ifNone)
沒有比使用map
+ getOrElse
更好的了嗎?
我個人發現像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
。
不幸的是,這有一個共同的負面后果: B
僅根據ifEmpty
參數進行調用, ifEmpty
參數通常更為狹窄。 例如(正確的版本已經在標准庫中,這僅用於演示)
def toList[A](x: Option[A]) = x.fold(Nil)(_ :: Nil)
Scala會將B
推斷為Nil.type
而不是所需的List[A]
並抱怨f
不返回Nil.type
。 相反,你需要一個
x.fold[List[A]](Nil)(_ :: Nil)
x.fold(Nil: List[A])(_ :: Nil)
這使得fold
不完全等同於相應的match
。
你可以做:
opt foldLeft (els) ((x, y) => fun(x))
要么
(els /: opt) ((x,y) => fun(x))
(兩種解決方案都會 按價值 評估 els
,這可能不是你想要的。感謝Rex Kerr指點它。)
編輯:
但你真正想要的是Scalaz的catamorphism 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)
。
雖然我應該說,只有在表達它的“更自然”的方式時才應該使用cata。 在許多情況下,一個簡單的map
- getOrElse
就足夠了,特別是當它涉及潛在地鏈接大量的map
。 (當然,你也可以用功能組合來鏈接fun
- 這取決於你是否要專注於功能組合或價值轉換。)
如Debilski所述,您可以使用Scalaz的OptionW.cata
或fold
。 正如Jason評論的那樣,命名參數使它看起來很漂亮:
opt.fold { ifSome = _ + 1, ifNone = 0 }
現在,如果在None
案例中你想要的值對於某些Monoid[M]
是mzero
而你有一個函數f: A => M
for Some
case,你可以這樣做:
opt foldMap f
所以,
opt map (_ + 1) getOrElse 0
變
opt foldMap (_ + 1)
就個人而言,我認為Option
應該有一個apply
方法,這將是catamorphism。 那樣你就可以這樣做:
opt { _ + 1, 0 }
要么
opt { some = _ + 1, none = 0 }
實際上,對於所有代數數據結構而言,這將是很好的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.