首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Fs2如何折叠,然后追加到流中

Fs2如何折叠,然后追加到流中
EN

Stack Overflow用户
提问于 2017-11-17 01:45:39
回答 3查看 1.2K关注 0票数 1

我想附加到一个Stream

但是下一个流依赖于先前Stream的折叠结果。

我是这样做的,但是对Stream s进行了两次评估

闪长链

代码语言:javascript
复制
import fs2._

def ints(start: Int) = Stream.iterate(start) { i => 
  println(i)
  i + 1
}.take(10)

val s = ints(0)

def foldAppend(init: Int)(f: (Int, Int) => Int)(next: Int => Stream[Pure, Int]) = {
  s ++ s.fold(init)(f).flatMap(next)
}

val res = foldAppend(0)((s, i) => s + 1)(ints)
println(res.toList)

如何实现只对s进行一次评估的s方法。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-11-21 09:17:45

最后用Pull完成工作

代码语言:javascript
复制
implicit class StreamSyntax[F[_], A](s: Stream[F, A]) {
    def foldAppend[S](init: S)(f: (S, A) => S)(next: S => Stream[F, A]): Stream[F, A] = {

      def pullAll(s: Stream[F, A]): Pull[F, A, Option[(Chunk[A], Stream[F, A])]] = {
        s.pull.unconsChunk.flatMap {
          case Some((hd, tl)) =>
            Pull.output(hd) *> pullAll(tl)
          case None =>
            Pull.pure(None)
        }
      }

      def foldChunks(i: S, s: Stream[F, A]): Pull[F, A, Option[(Chunk[A], Stream[F, A])]] = {
        s.pull.unconsChunk.flatMap {
          case Some((hd, tl)) =>
            val sum: S = hd.toVector.foldLeft(i)(f)
            Pull.output(hd) *> foldChunks(sum, tl)
          case None =>
            pullAll(next(i))
        }
      }
      foldChunks(init, s).stream
    }
  }
票数 1
EN

Stack Overflow用户

发布于 2017-11-17 07:31:19

Brian的答案是错误的,s实际上是懒惰的,所以整个流会被评估两次。绑定到s的变量是严格的,但是fs2中的Stream是一个惰性流,只有在您对其进行run后才会对其进行评估。

您的主要问题是,Pure不是一个安全实现副作用的单体,就像IO一样。你不应该单纯的println。一个行之有效的例子是:

代码语言:javascript
复制
import cats.effect.IO
import fs2._

def ints(start: Int) = Stream.iterate(start) { i => println(i)
  i + 1
}.take(10)

val s = ints(0)

def foldAppend(init: Int)(f: (Int, Int) => Int)(next: Int => Stream[IO, Int]) = {

  val result = s.covary[IO].runLog
  Stream.eval(result).covary[IO].flatMap {
    s =>
      Stream.emits(s) ++ Stream.emits(s).fold(init)(f).flatMap(next)
  }
}
val res = foldAppend(0)((s, i) => s + 1)(ints)
println(res.runLast.unsafeRunSync())

这将对流进行一次评估。

票数 0
EN

Stack Overflow用户

发布于 2017-11-17 04:58:09

你考虑过使用scala.collection.immutable.Stream吗?它是缓存的,所以不会被多次评估。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47342046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档