2016-05-26 9 views
3

私はScala forの仕組みを理解するために積み重ねています。 以下のコードはforと書かれていると思いますが、どういう考え方はありません。 誰かが私にそのことをどうやって説明することができますか?ScalaのflatMap/mapの代わりにforを使用するには?

def foo: Future[Option[Int]] = ??? 
def bar: Future[Throwable Xor Option[Int]] = ??? 
def baz: Future[Option[Boolean]] = ??? 

foo.flatMap { 
    case Some(x) => 
    Future.successful(x) 
    case None => 
    bar.flatMap { 
     case Xor.Right(Some(x)) => 
     baz.map { 
      case true => 1 
      case false => 0 
     } 
     case Xor.Right(None) => 
     Future.successful(0) 
     case Xor.Left(_) => 
     Future.successful(-1) 
    } 
} 
+0

多分これは役立ちます:http://stackoverflow.com/questions/19045936/scalas-for-comprehension-with-futures – meucaa

答えて

2

for-comprehensionsでパターンマッチングすることはできません。 Allow pattern matching on type in for comprehensionsを参照してください。

おそらくMonad Transformersを使用できます。私はあなたのコードをそのように実装したいと思いますが、今はそのための時間がありません。たぶんヒントがあなたを助けることができます。

/編集これは、Sergeyのコメントで指摘されているように完全に正確ではありません。すべての一致が同じタイプである限り、for-comprehensionsでパターンマッチングを行うことができます。すべてのパターンがJSONから継承second lesson of the first week of Functional Program Design in Scala Coursera Courseから撮影したこの画像を参照してください:flatMap関数内のすべての分岐で

For-comprehension and pattern matching

+2

これは、1に加えて、正しいです:それは実際にパターンマッチする可能_is_しかし、あなたはマッチに対して1つのケースだけを提供することができ、MatchErrorを投げるのではなくフィルターとして機能します: 'for {Some(x)< - List(Some(1)、None、Some )}} yield x'は 'List(1,2)'を返す – Sergey

+0

あなたがリンクした最初のプレゼンテーションは、私が読んだ先進的なScalaの理解に最も役立つリソースです。 – LMeyer

4

を、理解のためとしてこれを書きすることはできません。

パターンマッチングをfoldメソッドで置き換えることはできますが、これは個人的な好みの問題かもしれません。

Option("suish") match { 
    case Some(name) => s"hello $name" 
    case None => "hello world" 
} 
// is analogous to 
Option("suish").fold("hello world")(name => s"hello $name") 

私はXorTOptionOptionTfold方法(tutorial)を使用して、パターンマッチングを書き直したが、私は、これはあなたのネストされたパターンが一致した以上に読みやすいかはわかりません。

import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 
import cats.implicits._ 
import cats.data.{Xor, XorT, OptionT} 

def foo: Future[Option[Int]] = none[Int].pure[Future] 
def bar: Future[Throwable Xor Option[Int]] = 2.some.right.pure[Future] 
def baz: Future[Option[Boolean]] = true.some.pure[Future] 

OptionT(foo).getOrElseF { 
    // foo : case None 
    XorT(bar).fold(
    // bar : case Xor.Left 
    _ => -1.pure[Future], 
    barO => barO.fold(
     // bar : case Xor.Right(None) 
     0.pure[Future])(
     // bar : case Xor.Right(Some(x)) 
     _ => baz.map(_.fold(0 /* ? */)(b => if (b) 1 else 0))) 
).flatten 
} 
// Future[Int] 
+0

お返事ありがとうございます。あなたが答えで言及したように、ネストされたパターンのマッチは私にとってより読みやすいです。私はモナド変圧器が行く方法だと思います – suish

+0

@suish 'OptionT'と' XorT'はモナド変圧器です。 –

+0

私の悪い。私はモナド変圧器を使用して 'のた​​めに'が行く方法であると言うことを試みていました。 – suish

関連する問題