Scalaz 中的 State 和 Free monad 示例 [英] Example of State and Free monad in Scalaz

查看:46
本文介绍了Scalaz 中的 State 和 Free monad 示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以举个例子如何使用 ScalaZ Free monad 吗?

Can somebody give an example how to use ScalaZ Free monad ?

例如,如果我有一个简单的 State 函数并且想要应用它 10,000 次,我会得到 StackOverflowError:

For example, if I have a simple State function and want to apply it 10,000 times, I'd get StackOverflowError:

def setS(i: Int) :State[List[Int], Unit] = State { l => ( i::l, () ) }

val state = (1 to 10000).foldLeft( put(Nil :List[Int]) ) {
    case (st, i) => st.flatMap(_ => setS(i))
}

state(Nil)

据我所知,Free monad 可以帮助避免这种情况.我将如何使用 Free monad 重写这段代码,以免导致堆栈溢出?

As I understand, Free monad can help avoid this. How would I re-write this piece of code using Free monad to not cause stack overflow ?

推荐答案

正如我在上面的评论中所说,将 State 计算提升到 StateT[Free.Trampoline, S, A] 似乎应该可以工作:

As I say in a comment above, lifting the State computations into StateT[Free.Trampoline, S, A] seems like it ought to work:

import scalaz._, Scalaz._, Free.Trampoline

def setS(i: Int): State[List[Int], Unit] = modify(i :: _)

val s = (1 to 10000).foldLeft(state[List[Int], Unit](()).lift[Trampoline]) {
  case (st, i) => st.flatMap(_ => setS(i).lift[Trampoline])
}

s(Nil).run

不幸的是,这仍然会溢出堆栈,但正如 Dave Stevens 指出的那样,使用适用的 *> 而不是 flatMap 进行排序可以解决这个问题:

Unfortunately this still overflows the stack, but as Dave Stevens notes, sequencing with the applicative *> instead of flatMap fixes the issue:

val s = (1 to 100000).foldLeft(state[List[Int], Unit](()).lift[Trampoline]) {
  case (st, i) => st *> setS(i).lift[Trampoline]
}

s(Nil).run

我不知道为什么会这样,我已经提出了一个新问题,特别是关于差异的问题,但是这应该可以让您开始使用 Free.

I'm not sure why this is, and I've asked a new question specifically about the difference, but that should get you started with Free.

这篇关于Scalaz 中的 State 和 Free monad 示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆