Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
scalaz Free Monad控件中断和暂停一系列计算_Scala_Monads_Scalaz - Fatal编程技术网

scalaz Free Monad控件中断和暂停一系列计算

scalaz Free Monad控件中断和暂停一系列计算,scala,monads,scalaz,Scala,Monads,Scalaz,我有一个计算链,它改变了上下文的状态: case class Context(...) type Step = (Context => Context) val step1: Step = ctx => { ctx.copy(...) } val step2: Step val step3: Step // ... val stepN: Step val chain = List(step1, step2, step3, ..., stepN).toStream 我想引入计算的返回

我有一个计算链,它改变了上下文的状态:

case class Context(...)
type Step = (Context => Context)
val step1: Step = ctx => { ctx.copy(...) }
val step2: Step
val step3: Step
// ...
val stepN: Step
val chain = List(step1, step2, step3, ..., stepN).toStream
我想引入计算的返回值来控制该链的流量:

trait Cont
case class Break[Context](ctx: Context) extends Cont
case class Pause[Context](ctx: Context) extends Cont
case class Continue[Context](ctx: Context) extends Cont
中断-表示在执行当前步骤后取消链

暂停-意味着在执行当前步骤后暂停计算,能够在以后继续下一步并检查其是否可恢复

继续-表示流的正常继续

每个步骤都应该返回Cont中包装的上下文的当前值

目前,我正在通过展开步骤流val chain:stream[Cont[Step]]并检查chain.isEmpty和chain.head来检查是否还有一些计算


如何在scalaz中使用免费的单子呢?

您可以通过使用scalaz的延续单子scalaz.Cont来实现这一点

遗憾的是,没有关于如何使用scalaz.Cont的文档和示例。所以,为了对连续体有一个基本的了解,以及它们的用途,我们来看看

在 . 对于使用免费monad,建议阅读Debassh Ghosh的功能和反应域建模。 使用continuations的本质是,我们不会从计算中返回值,而是将控制传递给continuation,通常使用变量k,continuation指定接下来会发生什么

这就是说,让我们看看您的具体示例中的情况:

首先是一些类型定义;请注意,下一步是一个Continuation函数,它接受上下文并返回Return类型的内容

然后定义一些类型来控制计算链中的流;请注意,Pause还返回一个Continuation,因为我们希望以后能够继续计算

trait Return
case class Break(context: Context) extends Return
case class Pause(context: Context, continuation: Continuation) extends Return
case class Done(context: Context) extends Return
接下来,我们将我们的步骤定义为类,以便能够将它们与免费的monad一起使用

trait Step[A]
case class Step1(c: Context) extends Step[Context]
case class Step2(c: Context) extends Step[Context]
case class Step3(c: Context) extends Step[Context]
。。。并将它们提升到自由单子的上下文中

type Command[A] = Free[Step, A]
protected implicit def liftStep[A](step: Step[A]): Command[A] =
    Free.liftF(step)

def step1(c: Context): Command[Context] = Free.liftF(Step1(c))
def step2(c: Context): Command[Context] = Free.liftF(Step2(c))
def step3(c: Context): Command[Context] = Free.liftF(Step3(c))
现在我们建立计算链;请注意,我们将上一次计算的结果(如c1)传递到下一次计算,如步骤2C1;如果这种情况更隐晦地发生,那么可能应该考虑使用状态monad将状态从continuation传递到continuation

val script = for {
  c0 <- Free.point(Context(0))
  c1 <- step1(c0)
  c2 <- step2(c1)
  c3 <- step3(c2)
} yield c3
val process: Cont[Return, Context] = script.foldMap(step)
使用解释器步骤运行脚本以获得延续

val script = for {
  c0 <- Free.point(Context(0))
  c1 <- step1(c0)
  c2 <- step2(c1)
  c3 <- step3(c2)
} yield c3
val process: Cont[Return, Context] = script.foldMap(step)
运行延续过程;请注意,run方法需要一个Continuation,它将是最后一个计算步骤的Continuation,即c将是步骤3中的Context3

最后,编写一些代码来执行整个链,如果计算刚刚暂停,则继续;如果结果是Break或Done,则停止

var continue = true
do {
  continue = result match {
    case Pause(c, continuation) =>
      println(s"Pause: $c")
      result = continuation(c)
      true
    case Break(c) =>
      println(s"Break: $c")
     false
    case Done(c) =>
      println(s"Done: $c")
     false
   }
} while(continue)
结果是:

Pause: Context(2)
Done: Context(3)
Pause: Context(2)
Done: Context(3)