Haskell OCaml中的反向状态monad

Haskell OCaml中的反向状态monad,haskell,ocaml,monads,lazy-evaluation,state-monad,Haskell,Ocaml,Monads,Lazy Evaluation,State Monad,您将如何在OCaml中实现?(由于它严重依赖于惰性,我想人们必须使用标准库中的惰性模块)。我提出了一个解决方案 棘手的一点是: type's l='s Lazy.t 类型('a,'s)st='s->('a*'s l) 让bind(mx:('a,'s)st)(f:('a->('b,'s)st))(s:'sl:('b*'sl)= (*概念上我们想要 让rec(lazy(y,s')=lazy(mx-s')) 和(lazy(z,s'))=lazy(fy-s) in(强制z,s“”) 但那不是合法的Cam

您将如何在OCaml中实现?(由于它严重依赖于惰性,我想人们必须使用标准库中的惰性模块)。

我提出了一个解决方案

棘手的一点是:

type's l='s Lazy.t
类型('a,'s)st='s->('a*'s l)
让bind(mx:('a,'s)st)(f:('a->('b,'s)st))(s:'sl:('b*'sl)=
(*概念上我们想要
让rec(lazy(y,s')=lazy(mx-s'))
和(lazy(z,s'))=lazy(fy-s)
in(强制z,s“”)
但那不是合法的Caml。
因此,我们取而代之的是类型为('a*'s l)l和we的惰性对
懒洋洋地把我们需要的东西投射出来。
*)
让rec ys'=lazy(mx(LazyUtils.join(LazyUtils.snd zs'))
和(zs':('b*'sll)l)=懒惰(f(lazy.force(LazyUtils.fst ys'))s)
在(Lazy.force(LazyUtils.fst zs')、LazyUtils.join(LazyUtils.snd ys')中
正如我在评论中提到的,有点棘手的一点是,您不希望意外地过早地强制计算状态。不幸的是,为了获得正确的相互递归,您还被迫暂时使计算的答案(向前流动)也变懒。所以拇指的基本规则是:

  • 按照类型告诉你的去做
  • 除非在
    惰性e
    构造下,否则切勿强制执行状态
  • 特别是,
    LazyUtils.join:'a Lazy.t Lazy.t->'a Lazy.t
    不能是:

    因为那会过早地迫使外部撞击。相反,它必须是:

    let join xll = lazy (Lazy.force (Lazy.force xll))
    

    这看起来像是口吃,但事实上正确地延迟了所有的计算。

    那这个呢?非常适合计算分数,尤其是其他方面。@BoydStephenSmithJr:你在问另一个问题吗?我想是的。但是,在我发布我的答案之前,我会等待答案。@Bob,你试过什么?我可以告诉您,使用Lazy模块实现它的效果与您期望的非常接近。你是在寻找存在的确认,还是有更具体的问题?@Lambdageek:我的问题是“如何在不循环OCaml的情况下做到这一点?”。无论我把懒惰放在哪里,我总是以递归循环结束。如果你能写一个答案就太好了。非常感谢你的回答。在研究了你的诀窍之后,我能够自己重新找到你的答案。然后,我花了一整天的时间试图将其推广到反向状态monad转换器的情况。但我被困住了:我无法定义束缚。我能模糊地想象的唯一解决方案是使用monad in参数的mfix,但这本身就很难定义,因为它会导致循环递归。这就是为什么我要问。有什么想法吗?
    let join xll = lazy (Lazy.force (Lazy.force xll))