Скал Батут и ИО

Этот вопрос связан с другим вопросом, но сводится к гораздо более простому случаю:

Я предполагаю следующий импорт:

import scalaz._, Scalaz._
import Free._, effect._

У меня есть следующие генераторы:

val fromOneIO: () => IO[Int] = {
  var i = 0; () => { i += 1; IO(i) }
} 
val fromOne: () => Int = {
  var i = 0; () => { i += 1; i }
}

и следующие не хвостовые рекурсивные определения:

def rec(i: Int): Int = {
  if (i == 0) {
    fromOne()
  } else {
    rec(i - 1) + fromOne()
  }
}
def rec1(i: Int): Trampoline[Int] = {
  if (i == 0) {
    Return(fromOne())
  } else {
    suspend {
      for {
        a <- rec1(i - 1)
        b <- Return(fromOne()): Trampoline[Int]
      } yield a + b
    }
  }
}
def recio(i: Int): Trampoline[IO[Int]] = {
  if (i == 0) {
    Return(fromOneIO())
  } else {
    suspend {
      for {
        ioa <- recio(i - 1)
        iob <- Return(fromOneIO()): Trampoline[IO[Int]]
      } yield {
        for (a <- ioa; b <- iob) yield a + b
      }
    }
  }
}

Результат:

rec(100) // overflows for arg 10000
rec1(10000).run // works
recio(10000).run.unsafePerformIO() //overflows

Как сделать так, чтобы IO map/flatMap также трамплировали? Кажется, у меня есть другие вложенные стеки, созданные внутри второго для понимания. Нужно ли мне писать TrampolineT что будет использовать unsafePerformIO и обернуть извлеченное значение IO в приостановить?

1 ответ

Так IO(_) уже батут, для чего это стоит. В дополнение к предложению от folone, я могу избежать переполнения, изменив второе следующим образом:

val s = for (a <- ioa; b <- iob) yield a + b
val s1 = s.unsafePerformIO()
IO(s1)

Или вот так:

IO(for (a <- ioa; b <- iob) yield a + b).flatMap(identity)

Также IO(_) принимает параметр по имени, так IO(expr) а также val e = expr; IO(e) не ведет себя так же. Это переполнится!

val s = for (a <- ioa; b <- iob) yield a + b
IO(s.unsafePerformIO())

Таким образом, хотя это не очень удовлетворительный ответ, он, по возможности, использует аппликатив или оборачивает в другой IO и сплющивание было бы обходными путями к уносу стека.

Другие вопросы по тегам