Mandubian 是正确的,StateT 的 flatMap 不允许您绕过堆栈累积,因为在调用包装的 monad 的绑定之前立即创建了新的 StateT (在您的情况下,这将是 Free[Function0] )。
所以 Trampoline 无法提供帮助,但 State 函子上的 Free Monad 是确保堆栈安全的一种方法。
我们想要从 State[List[Int],Unit] 转到 Free[a[State[List[Int],a],Unit] 并且我们的 flatMap 调用将是 Free 的 flatMap (除了创建自由数据结构)。
val s = (1 to 100000).foldLeft(
Free.liftF[({ type l[a] = State[List[Int],a]})#l,Unit](state[List[Int], Unit](()))) {
case (st, i) => st.flatMap(_ =>
Free.liftF[({ type l[a] = State[List[Int],a]})#l,Unit](setS(i)))
}
现在我们已经构建了一个自由数据结构,我们可以轻松地通过它来线程化状态:
s.foldRun(List[Int]())( (a,b) => b(a) )
调用 liftF 相当难看,所以我有一个 PR 来让 State 和 Kleisli monad 更容易,所以希望将来不需要 lambda 类型。
编辑:PR 已接受,所以现在我们有了
val s = (1 to 100000).foldLeft(state[List[Int], Unit](()).liftF) {
case (st, i) => st.flatMap(_ => setS(i).liftF)
}