Scala Cats IO-在flatmap内进行尾部递归调用

Scala Cats IO-在flatmap内进行尾部递归调用,scala,scala-cats,Scala,Scala Cats,我试图使返回IO尾部的函数递归,但它不编译,因为我在flatMap中使用它。我知道有些东西是为这个目的而构建的,比如tailRec,但我正在寻找一些关于如何使用它们的指导。下面是示例代码 import cats.effect.IO import scala.annotation.tailrec def process(since: Option[String]): IO[Seq[String]] = { @tailrec def go(star

我试图使返回IO尾部的函数递归,但它不编译,因为我在flatMap中使用它。我知道有些东西是为这个目的而构建的,比如tailRec,但我正在寻找一些关于如何使用它们的指导。下面是示例代码

    import cats.effect.IO
    import scala.annotation.tailrec

    def process(since: Option[String]): IO[Seq[String]] = {

      @tailrec
      def go(startIndex: Int): IO[(Int, Seq[String])] = {

        val program = since match {
          case Some(s) =>
            for {
              r <- fetchResponse(s, startIndex)
              size = r.size
              ss = r.data
              _ <- writeResponse(ss)

            } yield (size,  r)
          case None => IO((0, Seq.empty[String]))
        }

        program.flatMap { case (size, _) =>
          if (startIndex <= size) go( startIndex + size)
          else IO((0, Seq.empty))
        }
      }

      go(0).map(o => o._2)
    }

    case class Response(size: Int, data: Seq[String])

    def fetchResponse(s: String, i: Int): IO[Response] = ???

    def writeResponse(r: Seq[String]): IO[Int] = ???
导入cats.effect.IO
导入scala.annotation.tailrec
def进程(自:选项[String]):IO[Seq[String]={
@泰勒克
def go(startIndex:Int):IO[(Int,Seq[String])]={
val程序=自匹配{
案例部分=>
为了{
R
if(起始索引o._2)
}
案例类响应(大小:Int,数据:Seq[String])
def fetchResponse(s:String,i:Int):IO[Response]=???
def writeResponse(r:Seq[String]):IO[Int]=???

简单的回答是:别担心

cats构造和执行
IO
实例的方式,特别是使用
flatMap
的方式,是非常安全的堆栈

当您执行
x.flatMap(f)
时,
f
不会在同一堆栈中立即执行。稍后由cats以基本上在内部实现尾部递归的方式执行。作为一个简化的示例,您可以尝试运行:

def calculate(start: Int, end: Int): IO[Int] = {
  IO(start).flatMap { x =>
    if (x == end) IO(x) else calculate(start + 1, end)
  }
}

calculate(0, 10000000).flatMap(x => IO(println(x))).unsafeRunSync()

这基本上与您正在做的相同,它打印出的
10000000
很好。

整个构造的哪个部分应该是尾部递归的?您打算对
val
上的
@tailrec
注释做什么?抱歉。Go应该是递归的。修复了代码