【问题标题】:Trampolining scalaz' Monad.whileM_ to prevent stack overflowTrampolining scalaz' Monad.whileM_ 以防止堆栈溢出
【发布时间】:2015-06-04 19:56:08
【问题描述】:

我正在使用 scalaz'Monad.whileM_ 以如下功能方式实现 while 循环:

object Main {

  import scalaz._
  import Scalaz._

  import scala.language.higherKinds

  case class IState(s: Int)

  type IStateT[A] = StateT[Id, IState, A]
  type MTransT[S[_], A] = EitherT[S, String, A]
  type MTrans[A] = MTransT[IStateT, A]

  def eval(k: Int): MTrans[Int] = {
    for {
      state <- get[IState].liftM[MTransT]
      _ <- put(state.copy(s = (state.s + 1) % k)).liftM[MTransT]
    } yield (k + 1)
  }

  def evalCond(): MTrans[Boolean] = {
    for {
      state <- get[IState].liftM[MTransT]
    } yield (state.s != 0)
  }


  def run() = {
    val k = 10
    eval(k).whileM_(evalCond()).run(IState(1))
  }
}

虽然这适用于小型 k,但它会导致大型 k 的 StackOverflow 错误(例如 1000000)。有没有办法蹦床whileM_ 或者有更好的方法来保证堆栈安全?

【问题讨论】:

    标签: monads scalaz scalaz7 trampolines


    【解决方案1】:

    使用scalaz.Free.Trampoline 而不是scalaz.Id.Id

    type IStateT[A] = StateT[Trampoline, IState, A]
    

    这里使用的状态操作返回State[S, A],它只是StateT[Id, S, A] 的别名。您需要使用StateT 上定义的lift[M[_]] 函数将StateT[Id, S, A] 提升为StateT[Trampoline, S, A]

    def eval(k: Int): MTrans[Int] = {
      for {
        state <- get[IState].lift[Trampoline].liftM[MTransT]
        _ <- put(state.copy(s = (state.s + 1) % k)).lift[Trampoline].liftM[MTransT]
      } yield (k + 1)
    }
    
    def evalCond(): MTrans[Boolean] = {
      for {
        state <- get[IState].lift[Trampoline].liftM[MTransT]
      } yield (state.s != 0)
    }
    

    最后,调用.run(IState(1)) 现在会得到Trampoline[(IState, String \/ Unit)]。你也必须另外run这个。

    eval(k).whileM_(evalCond()).run(IState(1)).run
    

    【讨论】:

    • 在我的例子中给出了 monad 堆栈。有没有办法在本地将东西提升到蹦床上而无需修改 monad 堆栈?
    • 我不确定这是否可能。向邮件列表groups.google.com/forum/#!forum/scalaz 提问可能会更好
    猜你喜欢
    • 2012-02-03
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    • 2016-10-02
    • 2010-10-29
    • 2013-11-15
    • 2012-08-24
    • 1970-01-01
    相关资源
    最近更新 更多