我正在研究使用State monad实现的堆栈示例。它使用scalaz中的状态monad实现。
这个例子取自Eugene Yokota的帖子http://eed3si9n.com/learning-scalaz/State.html
public void ChangBackColor_Click(object sender, EventArgs e)
{
if (ColorDialog.ShowDialog() == DialogResult.OK)
{
Form1.ChangeBack(ColorDialog.Color);
}
}
我一直试图以功能方式实现一段代码来清空堆栈。 public static void ChangeBack(Color clr)
{
this.BackColor = clr;
}
的定义使用 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))
两次,但如果我想要pop的数量与状态中的元素数量(stackManip
)相同怎么办?
弹出的第一个问题是&#34;你为什么需要这个?&#34;答案是我试图实现一个非常类似的情况,我需要在statt中执行pop的次数。如果有人可以帮我处理堆栈示例,那么我就能够实现我的特定情况。
答案 0 :(得分:1)
如果你想像堆栈中的元素一样多次调用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)
}
答案 1 :(得分:0)
您可以在示例中添加以下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