映射Scala期货

d80*_*tb7 2 scala

假设我有一个Future[Seq[Int]]我要转换的内容Future[Seq[String]].目前我这样做:

 val futureSeqString = futureSeqInt.map( x => x.map(_.toString()))
Run Code Online (Sandbox Code Playgroud)

这可行,但嵌套的地图似乎有点尴尬.等效转换Future[Option[Int]]稍微好一点,但它仍然不觉得我这样做是最好的方式:

val futureOptionString = futureOptionInt.map {       
  case Some(x) => x.toString(); 
  case _ => None;
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来解决这个问题?

Gab*_*lla 8

双重嵌套需要双重映射,所以是的,在vanilla scala中,你所做的是正确的.

但是,如果我们把这个理论考虑一下,两者都有List并且Future有一个map操作,这就使得它们Functors(这是一个过于简单化的,但请耐心等待)

两个Functors一般可以组成,这样你就可以组成FunctorFutureFunctorList实行"联合" map操作.

这是一个使用示例cats:

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"))
Run Code Online (Sandbox Code Playgroud)

当然,你也可以这样做Option.

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

奖励,无论嵌套的深度如何,您都可以使用相同的技术:

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")))
Run Code Online (Sandbox Code Playgroud)

  • 喔好吧.子类型多态必须死!:) (2认同)

Dim*_*ima 5

就个人而言,我没有看到嵌套地图有任何问题.你只需要更好地格式化和缩进它:

  future.map { seq =>
    seq.map(_.toString)
  }
Run Code Online (Sandbox Code Playgroud)

有些人for在这种情况下也会发现有用的理解(更重要的是,当你需要一起处理几个未来时).

 for {
   seq <- future
 } yield seq.map(_.toString)
Run Code Online (Sandbox Code Playgroud)