Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Fs2如何折叠然后附加到流_Scala_Fs2 - Fatal编程技术网

Scala Fs2如何折叠然后附加到流

Scala Fs2如何折叠然后附加到流,scala,fs2,Scala,Fs2,我想附加到一个流 但下一个流依赖于前一个流的折叠结果 我是这样做的,但是流s被计算了两次 如何实现只计算一次的foldAppend方法。您考虑过使用scala.collection.immutable.Stream吗?它是缓存的,因此不会被多次计算。Brian的回答是错误的,s实际上是懒惰的,因此整个流被计算两次。绑定到s的变量是严格的,但fs2中的流是一个惰性流,只有在运行它时才会对其进行计算 您的主要问题是,Pure并不像IO那样是安全实现副作用的monad。你不应该用纯文本打印。一个有效的

我想附加到一个流

但下一个流依赖于前一个流的折叠结果

我是这样做的,但是流s被计算了两次

如何实现只计算一次的foldAppend方法。

您考虑过使用scala.collection.immutable.Stream吗?它是缓存的,因此不会被多次计算。

Brian的回答是错误的,s实际上是懒惰的,因此整个流被计算两次。绑定到s的变量是严格的,但fs2中的流是一个惰性流,只有在运行它时才会对其进行计算

您的主要问题是,Pure并不像IO那样是安全实现副作用的monad。你不应该用纯文本打印。一个有效的例子是:

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())

这将评估流一次

最终使用Pull完成工作


您确定没有写入def s而不是val s吗?目前,我不确定是否有足够的信息来回答这个问题。一个完整的例子会很有帮助,这意味着一个完整的s@BrianMcCutchon定义。我添加了scasite链接,我使用println只是为了表明流是两次计算的。这个解决方案实际上将首先将所有数据存储到内存中,然后发射到一个新的流,我担心它无法扩展。
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())
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
    }
  }