2012-09-10 8 views
11

Seq[Option[A]]xsの場合、 if(xs.contains(None)) None else Some(xs.flatten)と同じように、モナド(およびおそらくはモノ)を利用するより一般的なソリューションを探しています。AとBがモナドの場合、A [B [C]]をB [A [C]]に変換するにはどうすればよいですか?

どうすればScalazで対応できますか?私は何かが明らかに欠けているように感じる。もちろん、しかしMTraverseインスタンスを持っており、Nをすることができます、Applicativeインスタンスを持っている場合の十分ではないにつながります-which

答えて

14

2つのモナドを持つこと(Mのために)十分の両方ではなく、(Nのための)十分すぎるほど、 sequenceを使用してください。例:

import scalaz._, Scalaz._ 

def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence 

これは、必要なセマンティクスを持っています。 Scalaz 7はに必要なTraverseインスタンスを提供していないため、私はSeqの代わりにListを使用しています(自分でも簡単に書くことができます)。


あなたが気づいてきたように、次のようにコンパイルされません。

List(Some(1), Some(45)).sequence 

をあなたがそこにNoneを投げる場合、それは大丈夫ですが:

scala> List(Some(1), None, Some(45)).sequence 
res0: Option[List[Int]] = None 

推測されたためですList(Some(1), Some(45))のタイプはList[Some[Int]]となり、SomeApplicativeインスタンスはありません。

ScalazはSome.applyのように動作しますが、あなたはすでにOptionとして入力された何かを与える便利なsome方法を提供し、あなたは次のように記述することができます

scala> List(some(1), some(45)).sequence 
res1: Option[List[Int]] = Some(List(1, 45)) 

エキストラタイピング必要。

+0

Scalaz 7のREPLでは、SeqのTraverse型クラスインスタンスを見つけることができないため、失敗します。たぶん私は輸入すべき何かがありますか? –

+0

'Seq'ではなく' List'を使うこともできますし、 'Seq'に独自のインスタンスを提供することもできます。なぜSeqインスタンスが7で消えたのか分かりません。 –

+0

ありがとうございました!しかし、私はその動作に不満を持っています。Seqの問題の他に、型を明示的に指定する必要があるもう1つの問題があります: 'val xs = List(Some(1)、Some(45)); (xs:List [Option [Int]])sequence' –

関連する問題