2017-01-17 7 views
3

Eitherは、右向きのScala 2.12を使用して、投影なしで、Optionのように投影/出力ブロックで使用できるようにします。しかし、明らかに、これはflatMapと一緒に使用するとOptionのように振る舞うには不十分です。スカラのリスト[どちらか一方]のflatMapを使用する

object Main { 

    def main(args: Array[String]): Unit = { 

    val nums = List.range(1,10) 

    println(nums.flatMap(evenOption)) 
    println(nums.flatMap(evenEither)) // fails 

    } 

    def evenOption(x: Int): Option[Int]  = if (x % 2 == 0) Some(x) else None 
    def evenEither(x: Int): Either[String, Int] = if (x % 2 == 0) Right(x) else Left("not even") 

} 

マイ最小限圏論の知識は私がEitherがモナドではないため、これは失敗したと思いますか?あるいは、上記の例をどのように機能させることができますか?

+0

この問題は、TraversableOnceを拡張しないという問題に関連している可能性がありますか? – Mikel

答えて

7

モナドであるかどうかは関係ありません。いくつかのデータ構造上でflatMapメソッドを実行しているとき、渡している関数はそのデータ構造のインスタンスを返さなければなりません。だからOptionを使ってフラットマッピングするとき、あなたの関数はOptionを返す必要があります。あなたが未来をフラットマッピングしているなら、関数は未来を返す必要があります。 Listと同じことが起こります。リストをフラットマッピングするとList自身が返されます。では、List.flatMap(Option)の仕事とList.flatMap(Either)の違いは何ですか? OptionからIterable(Option.option2Iterable)への暗黙的な変換があり、その変換があなたの例で行われたためです。 Eitherデータ型の変換はありません(自分で作成しない限り)。

+0

for/yieldはどのようにフラットマッピングを行いますか?たとえば、 'for {n < - nums; x ' - evenEither(n)} yield n' – TomTom

+0

各ジェネレータ( '< - ')は 'flatMap'演算に変換され、最後の' yield'は 'map'演算に変換されます。詳細については、http://docs.scala-lang.org/tutorials/FAQ/yield.htmlの公式ドキュメントをチェックしてください。さらなる質問がある場合はお気軽にお問い合わせください。 –

2

List[Either[String,Int]]List[Int]にフラット化するための暗黙のルールはありません。そのためには、その手段を提供する必要があります。

nums.map(evenEither).flatten {case Right(e) => List(e) 
           case _ => List()} 

しかしこれは少し直接的に表現できます。

nums.collect{case x if evenEither(x).isRight => x} 
関連する問題