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を使うと良さそう。