当状态满足某些条件时,如何停止状态转换?



我对scalaz/cats很陌生,对monadState有疑问(catsscalaz无关紧要(。考虑以下著名的Stack示例:

object StateTest {
type Stack = List[Int]
def main(args: Array[String]) = {
println(transition.run(List(1, 2, 3, 4)).value) //(List(4),Some(3))
println(transition.run(List(1, 2)).value) //(List(),None)
}
def transition: State[Stack, Option[Int]] = for {
_ <- pop
_ <- pop
a <- pop
} yield a
def pop: State[Stack, Option[Int]] = State {
case x::xs => (xs, Some(x))
case Nil => (Nil, None)
}
}

问题是我想执行状态转换(pop(,直到状态(List[Int](满足某些条件(我想检查List[Int]::isEmpty(,然后立即停止。

在当前的实现中,我只能在调用run后知道状态是否满足条件。

是否可以在带有状态单体的猫/斯卡拉兹中这样做,或者我需要其他东西?

您将使用由另一个表示终止的 monad 参数化的状态 monad。

一般来说,这种参数化的单子变压器称为单子变压器。在这种特定情况下,您将使用StateT单体变压器。模化一些实现细节,StateT相当于

type StateT[F[_], S, A] = S => F[(S, A)]

现在,您可以选择F作为Option,表示立即终止。

import scalaz.StateT
import scalaz.std.option._
object StateTest {
type Stack = List[Int]
def main(args: Array[String]) = {
println(transition.run(List(1, 2, 3, 4))) // Some((List(4), 3))
println(transition.run(List(1, 2)))       // None
}
def transition: StateT[Option, Stack, Int] = for {
_ <- pop
_ <- pop
a <- pop
} yield a
def pop: StateT[Option, Stack, Int] = StateT {
case x::xs => Some((xs, x))
case Nil   => None
}
}

如果要返回某些类型为B的值,即使在提前终止的情况下,也可以使用Either[B, ?]而不是Option来参数化StateT

type ErrorOr[A] = Either[String, A]
def pop1: StateT[ErrorOr, Stack, Int] = StateT {
case x::xs => Right((xs, x))
case Nil   => Left("Cannot pop from an empty stack.")
}

相关内容

  • 没有找到相关文章

最新更新