2016-10-12 10 views
0

私はスカラ座でmyselfeを見つける一般的な状況は、以下の流れである。パターンは[未来[int]は]未来への変換[オプション[INT]]

  1. ウィッヒを返すいくつかの小道具を読みますOption
  2. Option

この利回りを返し将来の結果にいくつかの変換を行いますFuture

  • に小道具を使用例えばOption[Future[Option[_]]]としてタイプより良い解決策は、以下のようなものを使用して、例えばそのようなFuture[Option[Option[_]]]として変換を使用することになる。

    def transform[A](o: Option[Future[A]]): Future[Option[A]] = 
        o.map(f => f.map(Option(_))).getOrElse(Future.successful(None)) 
    

    hereから盗まれたコード)

    そしてIは、Optionsの任意の数で動作することができflatmapを使用してFutureの内部にあります。

    これは、私が変換メソッドを何度も実装しなくても、何らかの理想的な方法でScalaで使用可能であることを確かめるような一般的なパターンのようです。

    私の質問は:上記の例のようにOption[Future[Option[_]]]を外部に回す最も理想的な方法は何ですか?

  • +1

    モナド変圧器はあなたが探しているものかもしれません。 – mfirry

    +0

    あなたは 'Option [Future [A]] => Future [Option [A]]がほしいと言っていますが、詳細はあなたが' Option [Option [A]]] => Option [ A] '?だから、それは?あなたは例を挙げることができますか? – Cubic

    答えて

    0
    val a: Option[Future[Option[T]]] = ... 
    
    val b: Future[Option[T]] = a.getOrElse(Future(None)) 
    
    +1

    'Future' [docs](http://www.scala-lang.org/api/current/#scala.concurrent.Future$)を見ると、' Future.apply'より 'Future.successful'を選択しますすなわち、「未来(...)」。前者は次のように書いています: '指定された結果を持つ未完成のFutureを作成します。 '、後者のdocsは'非同期計算を開始し、その計算結果を持つFutureオブジェクトを返します。注 - 実際の違いはわかりません。単にドキュメントを指しています。 –

    1

    catsライブラリのtypeclassがここで役立つかもしれません。 Option[Future[Something]]Future[Option[Something]]に変換するという定型句の世話をすることができます。アンモナイトREPL使用

    例:

    @ val optionOfFuture: Option[Future[String]] = Some(Future.successful("hello")) 
    optionOfFuture: Option[Future[String]] = Some([email protected]) 
    

    我々はTraverseを使用 ':

    $ amm 
    Loading... 
    Welcome to the Ammonite Repl 0.7.7 
    (Scala 2.11.8 Java 1.8.0_101) 
    @ import $ivy.`org.typelevel::cats-core:0.7.2` 
    import $ivy.$ 
    

    まず、いくつかの輸入...

    @ import cats.Traverse 
    import cats.Traverse 
    @ import cats.implicits._ 
    import cats.implicits._ 
    @ import scala.concurrent.ExecutionContext.Implicits.global 
    import scala.concurrent.ExecutionContext.Implicits.global 
    @ import scala.concurrent.Future 
    import scala.concurrent.Future 
    

    をここでは、変換したい事がありますsequenceOptionと0123を切り替える方法:

    @ val futureOfOption: Future[Option[String]] = Traverse[Option].sequence(optionOfFuture) 
    futureOfOption: Future[Option[String]] = Success(Some(hello)) 
    

    それとも、構文、砂糖バージョンを好む場合:Traverseが行うことができます他に何の詳細については

    @ import cats.syntax.traverse._ 
    import cats.syntax.traverse._ 
    @ val futureOfOption2: Future[Option[String]] = optionOfFuture.sequence 
    futureOfOption2: Future[Option[String]] = Success(Some(hello)) 
    

    を、cats documentationを見てみましょう。

    1

    あなたの問題は、あなたの質問で#3であると思います。なぜ、「結果に何らかの変換」があり、それはFutureを返します。Optionを返しますか?それは間違っている。最初にFutureを返してください。この問題は発生しません。

    そして、「flatMapを使用して任意の数のオプションを扱うことができる」ということを正確にはわかりませんが、ほとんど間違っています。flatMap地図の時刻に余分なレベルSome(Some("foo")).flatMap(x => Some(s))Some(Some("foo"))です。 .flattenは、同じことを明示的に行います。 Some(Some(Some("foo"))).flattenは、で、Some("foo")または"foo"ではありません。

    いずれの場合も、オプションのレベルは1つしかないことに注意してください。フラット化は「任意の数」ではなく、処理されます。 通常の方法は、余分なオプションを取り除くことです(すぐに平らにして、ではなく、常にFuture[Option[T]]にする)。