Scalaをやっていて、val x: Option[String] = None
を""
に写したいことが100万回くらいある。しかしx.getOrElse("")
と書くのは納得いかない、という状況になっていた。
なぜかというと、String
はモノイドだし、モノイドには空要素empty
があるはずで、Option[A : Monoid]
みたいな型があったら、None
のときはempty
に写したい、というのは結構自明によくあるシチュエーションなのではないかと思って悶々としていた。どこかに既に実装があるはずだけれど、どこにあるのかわからない!!!
Option[String]
だったら""
に写せばよいOption[List[A]]
だったら[]
に写せばよい- などなど
Option[String]、Noneのときに空文字に写すことでStringにできると思うんだけど、モノイド的ななんかでこういう変換を自然にやれないだろうか
— Windymelt (Scala) (@windymelt) 2022年5月17日
Option[String]のgetOrElseに空文字渡したいのは結構自明という感じなので、Zeroが定義されてたらそれにする、みたいなやつないのかな
— Windymelt (Scala) (@windymelt) 2022年5月17日
F外失
— あさだ (@AeroSmithBz) 2022年5月17日
こういったのでしょうか pic.twitter.com/QqT0XezIAK
そうそう、そういうのが欲しいんです。
すると、人々に助けてもらえて、combineAll
というのがcats
のFoldable
に定義されているということがわかった。
モノイド的ななんかで自然にやる方法の一つに Foldable#combineAll がありますね pic.twitter.com/IQwbWljdfM
— がくぞ (@gakuzzzz) 2022年5月17日
Foldable
だったのか〜〜〜
確かに、畳み込むという文脈で考えれば、自然とNone
はempty
にするべきでしょ、と考えることになりそう。
import cats._ import cats.implicits._ val x: Option[String] = Some("foo") val y: Option[String] = None // 顧客が本当に必要だったもの println(s"x = '${x.combineAll}'") println(s"y = '${y.combineAll}'") // combineしてももちろん使える val xy = x |+| y println(s"xy = '${xy.combineAll}'") /* x = 'foo' y = '' xy = 'foo' */
追記
cats でしたら orEmpty という関数が Option の sintax にモノイド的ななんかとして用意されています。 pic.twitter.com/i4Ys6WegSX
— nozomitaguchi (@nozomitaguchi) 2022年5月17日
orEmpty
というのもあるとのことだった。Option
であればこれで良さそう。List
などであればFoldable
のcombineAll
を使うと良さそう。