mapping a Stream with a function returning a Future

后端 未结 3 1995
礼貌的吻别
礼貌的吻别 2021-02-13 11:29

I sometimes find myself in a situation where I have some Stream[X], and a function X => Future Y, that I\'d like to combine to a Future[Stream

3条回答
  •  半阙折子戏
    2021-02-13 11:54

    You're on the right track with traverse, but unfortunately it looks like the standard library's definition is a little broken in this case—it shouldn't need to consume the stream before returning.

    Future.traverse is a specific version of a much more general function that works on any applicative functor wrapped in a "traversable" type (see these papers or my answer here for more information, for example).

    The Scalaz library provides this more general version, and it works as expected in this case (note that I'm getting the applicative functor instance for Future from scalaz-contrib; it's not yet in the stable versions of Scalaz, which are still cross-built against Scala 2.9.2, which doesn't have this Future):

    import scala.concurrent._
    import scalaz._, Scalaz._, scalaz.contrib.std._
    
    import ExecutionContext.Implicits.global
    
    def toFutureString(value: Int) = Future(value.toString)
    
    val result: Future[Stream[String]] = Stream.from(0) traverse toFutureString
    

    This returns immediately on an infinite stream, so we know for sure that it's not being consuming first.


    As a footnote: If you look at the source for Future.traverse you'll see that it's implemented in terms of foldLeft, which is convenient, but not necessary or appropriate in the case of streams.

提交回复
热议问题