我需要在 State Monad 中计算与状态中剩余元素一样多的次数

I need to compute as many times as remaining elements in the state in a State Monad

我正在研究这个用 State monad 实现的堆栈示例。它使用 scalaz 中的状态 monad 实现。

示例取自 Eugene Yokota post http://eed3si9n.com/learning-scalaz/State.html

  import scalaz._
  import scalaz.Scalaz._

  type Stack = List[Int]

  val pop = State[Stack, Int] {
    case x :: xs => (xs, x)
  }

  def push(a: Int) = State[Stack, Unit] {
    case xs => (a :: xs, ())
  }

  def stackManip: State[Stack, Int] = for {
    _ <- push(3)
    a <- pop
    b <- pop
  } yield(b)


  val res: (Stack, Int) = stackManip(List(5, 8, 2, 1))

我一直在尝试实现一段代码以功能方式清空堆栈。 stackManip的定义使用了两次pop但是如果我希望pop的数量与状态中元素的数量相同(List[Int])怎么办?

第一个弹出的问题是 "Why would you need that?" 答案是我正在尝试实现一个非常相似的案例,在该案例中我需要执行 pop 的次数与 statt 中的元素一样多。如果有人可以帮助我处理堆栈示例,那么我就可以实现我的特定案例。

您可以在示例中添加以下 empty 定义:

val empty = State[Stack, List[Int]] {
    case xs => (Nil, xs)
}

然后更改stateManip函数来使用它:

def stackManip: State[Stack, List[Int]] = for {
    _ <- push(3)
    l <- empty
} yield l

如果您想调用 pop 与堆栈中的元素一样多的次数,您可以这样做:

val emptyStack: State[Stack, Unit] = State.init.flatMap { stack =>
    if(stack.isEmpty) {
        State.state( () )
    } else {
        for {
        _ <- pop
        _ <- emptyStack
        } yield ()
    }
}

编辑:另一种方式,滥用 scalaz:

type StackState[X] = State[Stack,X]

val emptyStack: State[Stack, Unit] = State.init.flatMap { stack =>
    Applicative[StackState].replicateM_(stack.length, pop)
}