Haskell 严格语言中的MonadFix

Haskell 严格语言中的MonadFix,haskell,f#,ocaml,monads,monadfix,Haskell,F#,Ocaml,Monads,Monadfix,我正在研究Ocaml中类似haskell的do表示法的camlp4扩展,并试图找出GHC如何编译递归do绑定(使用-XDoRec启用)。 我想知道一元不动点组合器是否可能存在于严格的语言中(比如Ocaml/F#/SML/…) 如果是,它会是什么样子?这会非常有用吗?F#计算表达式语法(与Haskelldo相关)支持递归: let rec ones = seq { yield 1 yield! ones } 这是受支持的,因为除了其他单子(或MonadPlus)操作外,计算生成器还必须支

我正在研究Ocaml中类似haskell的do表示法的camlp4扩展,并试图找出GHC如何编译递归do绑定(使用-XDoRec启用)。
我想知道一元不动点组合器是否可能存在于严格的语言中(比如Ocaml/F#/SML/…)
如果是,它会是什么样子?这会非常有用吗?

F#计算表达式语法(与Haskell
do相关)支持递归:

let rec ones = seq {
  yield 1
  yield! ones }
这是受支持的,因为除了其他单子(或MonadPlus)操作外,计算生成器还必须支持
延迟
操作。代码被转换为如下内容:

let rec ones = 
  seq.Combine
    ( seq.Yield(1),
      seq.Delay(fun () -> seq.YieldFrom(ones)) )
一般来说,
延迟的类型是
(unit->M
,诀窍在于它将具有效果的计算(或即时递归引用)封装到一个延迟的计算中,并根据需要进行评估

如果您想进一步了解该机制在F#中的工作原理,请参阅以下两篇文章:


第一个描述了F#计算表达式语法是如何设计的(以及如何插入
Delay
,以及一般来说,F#如何将延迟和急切的计算与效果结合起来)第二个描述了F#如何处理带有值的
let rec
声明,就像上面的
one
值一样。

所以,不,这不可能完全以严格的方式实现。因为所有函数式语言都有一些惰性的概念(主要使用函数、闭包和变量),所以在“严格的语言”中是可能的通过惰性构造。通常惰性已经存在,但如果您的monad位于抽象类型之后,OCaml将不允许您利用它--
这种表达式不允许作为“let rec”
的右侧。在这种情况下,您需要使用虚假的
单元
参数(或者如果需要记忆,可能是“惰性”)