オプションに折りたたみ方式がないのはなぜですか?
-
26-10-2019 - |
質問
なぜだろうか 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))
(両方のソリューションが評価されます els
価値によって、それはあなたが望むものではないかもしれません。ありがとう レックス・カー それを指摘してください。)
編集:
しかし、あなたが本当に欲しいのはScalazのものです カタルフィズム cata
(基本的にa 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
s。 (ただし、チェーンすることもできます fun
もちろん、関数の構成を伴う - それは、関数の構成に焦点を合わせるか、値変換に焦点を合わせるかによって異なります。
他のヒント
私は個人的にのような方法を見つけます cata
議論がしばしばそれをやりすぎているので、それは2つの閉鎖を取ります。あなたは本当に読みやすさを獲得していますか? 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
実際には、より狭いことが多い議論です。たとえば(正しいバージョンはすでに標準ライブラリにあり、これはデモンストレーション専用です)
def toList[A](x: Option[A]) = x.fold(Nil)(_ :: Nil)
Scalaは推測します B
することが Nil.type
希望する代わりに List[A]
そして不平を言う f
戻っていない Nil.type
. 。代わりに、1つが必要です
x.fold[List[A]](Nil)(_ :: Nil)
x.fold(Nil: List[A])(_ :: Nil)
これは作ります fold
対応するものとはまったく同等ではありません match
.
Debilskiが述べたように、Scalazを使用できます OptionW.cata
また fold
. 。ジェイソンがコメントしたように、名前付きパラメーターはこれを見栄えを良くします:
opt.fold { ifSome = _ + 1, ifNone = 0 }
さて、あなたが望む価値が None
ケースはです mzero
いくつかのための Monoid[M]
そして、あなたは機能を持っています f: A => M
のために Some
ケース、あなたはこれを行うことができます:
opt foldMap f
そう、
opt map (_ + 1) getOrElse 0
なります
opt foldMap (_ + 1)
個人的に私は思います Option
を持っている必要があります apply
カタモルフィズムとなる方法。そうすれば、これを行うことができます:
opt { _ + 1, 0 }
また
opt { some = _ + 1, none = 0 }
実際、これはすべての代数データ構造に適していると便利です。