Этот вопрос связан с другим вопросом, но сводится к гораздо более простому случаю:
Я предполагаю следующий импорт:
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
, и преобразовывать извлеченное значение ввода-вывода в приостановку?
Monoid
дляIO[A: Monoid]
, кажется, работает. То есть просто измените свой операторyield
наioa |+| iob
. Однако для более широкой картины мне нечего порекомендовать. - person folone   schedule 23.04.2013Monad
дляIO
. Если вы используете его экземплярApplicative
, он работает нормально.yield (ioa |@| iob){_ + _}
- person folone   schedule 23.04.2013IO
был батутом, а не функция, выстраивающая огромную цепочку вложенныхIO
действий. Ваш код позволяет вам создать действиеIO
без переполнения стека, но то, как вы его создаете, приведет к переполнению стека при запуске действияIO
. - person Mysterious Dan   schedule 23.04.2013F.lift2
. Я бы хотел, чтобы у scalaz7 все еще был источник с перекрестными ссылками, построенный на основе рентгеновского снимка Харры. - person huynhjl   schedule 24.04.2013recio
не является хвостовой рекурсией. Так что мне как бы нужно два уровня батута. Итак, мой вопрос на самом деле заключается в том, как добиться этого второго для IO. - person huynhjl   schedule 24.04.2013