2016-05-08 12 views
2

私がFuture[Seq[String]]に変換したいFuture[Seq[Int]]を持っているとしましょう。現在、私はこれを次のようにしています:スカラ先物のマッピング

val futureSeqString = futureSeqInt.map(x => x.map(_.toString())) 

これは機能しますが、ネストされたマップはちょっと面倒です。これに対処する良い方法が

val futureOptionString = futureOptionInt.map {  
    case Some(x) => x.toString(); 
    case _ => None; 
} 

あります:私はそれを最善の方法をやっているようFuture[Option[Int]]の等価変換がわずかに良いですが、それはまだ感じていませんか?

+0

オプションは、マップ・メソッドを持っているので、あなたは(私がすべきだと思う)と同じ方法で変換を行うことができますSeqのためにそれをしました。 –

答えて

8

ダブルネストにはダブルマッピングが必要です。したがって、バニラスケーラでは、何をしているのが正しいのですか。 、我々は第二のための理論を考慮すれば

はしかし、ListFutureの両方がmap操作を持っており、これは彼らFunctors(これは単純化しすぎですが、私と一緒にクマ)

Functorsは、一般的に構成することができますFunctorFutureで、FunctorListの場合は、「結合」map操作を実装できます。

import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 
import cats._ 
import cats.std.future._ 
import cats.std.list._ 

// create a `Functor[Future[List]` 
val futureListF = Functor[Future].compose(Functor[List]) 

val data = Future.successful(List(1, 2, 3)) 

// only one map!  
futureListF.map(data)(_.toString) // Future(List("1", "2", "3")) 

そしてもちろん、あなたがOptionと同じ操作を行うことができます。ここでは

catsを使った例です。

val futureOptionF = Functor[Future].compose(Functor[Option]) 
val data = Future.successful(Option(42)) 
futureOptionF.map(data)(_.toString) // Future(Some("42")) 

ボーナスは、あなたは、ネストの深さに関係なく、同じ技術を使用することができます。

type ListOption[+A] = List[Option[A]] 
implicit val listOptionF = Functor[List].compose(Functor[Option]) 
val futureListOptionF = Functor[Future].compose(Functor[ListOption]) 

// the above three lines could just be 
// val futureListOptionF = Functor[Future].compose(Functor[List].compose(Functor[Option])) 
// if only SI-2712 were fixed 

val data = Future.successful(List(Some(42), None, Some(2))) 

// triple nesting? Still a single map! 
futureListOptionF.map(data)(_.toString) // Future(List(Some("42"), None, Some("2"))) 
+0

1つの小さな事柄:OPは未来の[List [Int]]ではないFuture [Seq [Int]]を持っているので、Seqをリストに変換するために二重マッピングをとらなければならない – lambdista

+0

'Seq'は抽象的な特性であり、実装は 'List'なので、OPの' Seq'は既に 'List'である可能性が高いです。そうでなければ、具体的なユースケースの詳細が必要です –

+0

しかし、私はあなたがvalデータを持っている場合でも具体的な値ではないタイプを見ていると思います:Future [Seq [Int]] = Future.successful(List(1,2、 3))あなたは手動でそれを動作させるためにリストに手動で変換する必要があります。 – lambdista

5

個人的には、ネストされたマップには何も問題はありません。 (あなたが一緒にいくつかの先物を処理する必要があるときに、より多くのようにして)

future.map { seq => 
    seq.map(_.toString) 
    } 

一部の人々はこの場合にも便利for理解を見つける:あなただけフォーマットし、より良い、それをインデントする必要があります。

for { 
    seq <- future 
} yield seq.map(_.toString)