使用scalaz的免费monad时如何避免堆栈溢出?
发布时间:2020-12-16 08:54:51 所属栏目:安全 来源:网络整理
导读:我以前认为实现的部分目标是避免这个问题,所以也许我做的事情显然是愚蠢的? 这是一些代码: // Stack overflowimport scalaz._sealed trait Command[T]case class Wait(ms: Long) extends Command[Unit]case object Evaluator extends (Command ~ Id.Id) {
我以前认为实现的部分目标是避免这个问题,所以也许我做的事情显然是愚蠢的?
这是一些代码: // Stack overflow import scalaz._ sealed trait Command[T] case class Wait(ms: Long) extends Command[Unit] case object Evaluator extends (Command ~> Id.Id) { override def apply[T](cmd: Command[T]) = cmd match { case Wait(t) => Thread.sleep(t) } } object Api { def sleep(ms: Long): Free.FreeC[Command,Unit] = Free.liftFC(Wait(ms)) } val sleep: Free.FreeC[Command,Unit] = Api.sleep(1).flatMap { _ => sleep } Free.runFC(sleep)(Evaluator) 注意:我意识到这很愚蠢:)在实践中,我的命令类有很多命令,我有一个命令,它执行相同的循环…基本上,轮询一些状态,如果真正中止,如果为false,继续等待. 我想避免这导致的堆栈溢出…我认为这已经蹦了过来,但我想我需要再次手动执行此操作?是否有一种干净的方式在免费的monad思维方式中做到这一点? 更新: 进一步思考这个问题,我认为这个问题不是睡眠免费Monad,而是我们在评估中绑定的Id.Id monad …所以我尝试了类似的东西: case object Evaluator2 extends (Command ~> ({ type t[x] = Free[Id.Id,x] })#t) { override def apply[T](cmd: Command[T]) = cmd match { case Wait(t) => Thread.sleep(t); Free.liftF[Id.Id,Unit](()) } } Free.runFC[Command,({ type t[x] = Free[Id.Id,x] })#t,Unit](sleep)(Evaluator2)(Free.freeMonad[Id.Id]) 但问题是它只会评估一步.理想情况下,我希望runFC阻塞,直到满足某些条件(或者在这种情况下,永远循环直到我杀死它,但没有堆栈溢出) 解决方法
Id monad不是蹦床.最终,在Id monad的bind方法和free monad的foldMap方法之间进行无限的相互递归.使用Trampoline或Task代替Id.
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |