私は、モナド(およびおそらくモノイド)を利用
if( xs.contains(None) ) None else Some(xs.flatten)
してxs
of typeと同じことを達成する、より一般的なソリューションを探していSeq[Option[A]]
ます。
Scalaz でそれを行うにはどうすればよいですか? 明らかな何かが欠けているように感じます。
2 つのモナドを持つことは ( の場合) 十分ではなく ( の場合M
)十分すぎる ( の場合) の両方ですN
— これはもちろん十分ではありません — しかしM
、Traverse
インスタンスN
がありインスタンスがある場合はApplicative
、 を使用できますsequence
。例えば:
import scalaz._, Scalaz._
def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence
これには、必要なセマンティクスがあります。Scalaz 7 では に必要なインスタンスが提供されなくなったため、List
代わりに を使用していることに注意してください(ただし、独自のインスタンスを簡単に作成できます)。Seq
Traverse
Seq
お気付きのとおり、次のコードはコンパイルされません。
List(Some(1), Some(45)).sequence
そこにa を入れても問題ありませんNone
が:
scala> List(Some(1), None, Some(45)).sequence
res0: Option[List[Int]] = None
これは、 の推定型が でList(Some(1), Some(45))
あり、 のインスタンスList[Some[Int]]
がないためです。Applicative
Some
Scalaz は のように動作する便利なsome
メソッドを提供しますSome.apply
が、すでに として型付けされているものを提供するOption
ので、次のように記述できます。
scala> List(some(1), some(45)).sequence
res1: Option[List[Int]] = Some(List(1, 45))
余分な入力は必要ありません。