簡體   English   中英

為什么Option沒有折疊方法?

[英]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.catafold 正如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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM