Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.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
F# 试图让bind为State和Delayed monad的组合工作_F#_Monads_Free Monad_Recursive Type - Fatal编程技术网

F# 试图让bind为State和Delayed monad的组合工作

F# 试图让bind为State和Delayed monad的组合工作,f#,monads,free-monad,recursive-type,F#,Monads,Free Monad,Recursive Type,如果答案是“你完全错了”,请务必让我知道一个更恰当的方法。我有这样的代码结构: type Res<'T> = | E of (DC -> 'T) | V of 'T 但也注意到一些帖子(尤其是 让结果v=Res.E dc,Res.v 也许我遵循的是一种我不应该遵循的模式,但在当时这似乎是一个好主意,特别是在试图重构无数样板代码并用计算表达式替换它时,但也许我应该坚持直接求值,它适合我的头脑;) 但我觉得我很接近。。。有什么想法吗 我不太确定这个单子是什么意思

如果答案是“你完全错了”,请务必让我知道一个更恰当的方法。我有这样的代码结构:

type Res<'T> =
    | E of (DC -> 'T)
    | V of 'T
但也注意到一些帖子(尤其是

让结果v=Res.E dc,Res.v
也许我遵循的是一种我不应该遵循的模式,但在当时这似乎是一个好主意,特别是在试图重构无数样板代码并用计算表达式替换它时,但也许我应该坚持直接求值,它适合我的头脑;)

但我觉得我很接近。。。有什么想法吗

我不太确定这个单子是什么意思,但是
好的,在仔细考虑并阅读了问题的标题:-)之后,我确实理解了它的含义,并且我可以看到如何为它构建
bind

您的错误是,
Res.E
中包装的函数应该返回一个元组,但您让它只返回
Res'b Res)(Res:'a Res:'b Res=
匹配
|V a->k a
|E->
E
设dc',res'=e dc
dc',绑定k res'

我不认为晚期病例也应该延迟。也就是说,我看不出有什么理由。据我所知,对
vx
情况的解释应该是“一个不改变状态并返回
x
”的计算,在这种情况下,使其延迟只会增加一个额外的lambda表达式。

在Haskell中,当一个人想要同时应用两个Monad时,他使用Monad转换器。我不确定这些在F#中是否可用(或者它们是否可以在中实现——我自己还没有实现)。为了弄清楚这个概念,我听说这篇论文很好。@paul,谢谢,我来看看。但不知何故,要求一个一维的实现来保持stateá并对其进行延迟评估似乎并不过分。github上有一个项目完成了其中的一部分(我现在找不到它,但我认为它使用了-我肯定有人记得它Hanks,你是对的,这很有效!我没有(去)tupling;)。至于它的含义,我之所以使用嵌套类型,是因为这里有关于构造延迟monad(带单位参数)的建议。在元组中添加的
dc
参数和是一个状态,该状态随每次执行一起标记并弹出/推送。它遵循(如果我做得正确的话)状态单子的模式。整个过程是两者的结合。顺便说一句,我不完全确定它现在是否仍然是尾部递归的,因为递归调用
bind
现在取决于
edc
的结果。但是,因为这本身不是递归的,所以我可能是安全的(虽然这里的深度不是可笑的深,但最终可能无关紧要)。第二,我不认为在这个定义下,你能使它成为尾部递归的,但好消息是,如果你仔细想想,这个东西实际上根本不是递归的。尽管它在
bind
的定义中调用
bind
,但该调用并不是真正的“递归”,因为
bind
不将自身作为其自身评估的一部分进行调用。相反,它返回一个闭包,再次调用
bind
进行编辑。是的,你完全正确。虽然它是递归的(
rec
关键字),但它使用continuations,这就是编写这种绑定表达式的全部思想。在计算时,闭包被递归地扩展/调用,但正如您所说,这最终不是真正的递归;)。顺便说一句,乔恩·哈洛普曾经告诉我,通常,通过使用连续体,一切都可以通过尾部递归实现。乔恩·哈洛普是正确的。但要做到这一点,你最终会得到一种不同的类型。这就是为什么我说“在这个定义下不能使尾部递归”。
type Res<'T> =
    | E of (DC -> DC * 'T)
    | V of 'T
type Res<'T> =
    | E of (DC -> DC * Res<'T>)
    | V of 'T
let rec bind k res =
    match res with
    | Res.V v -> k v      // not delayed, should it be?
    | Res.E e -> 
        Res.E <| fun dc -> bind k (e dc)   // here's my error, on 'e dc'
         //(fun dc -> dc, bind f (e dc))
bind k res
let result v = Res.V v
let result v = Res.E <| fun dc -> dc, Res.V v
let rec bind (k: 'a -> 'b Res) (res: 'a Res) : 'b Res =
  match res with
  | V a -> k a
  | E e -> 
      E <| fun dc -> 
        let dc', res' = e dc 
        dc', bind k res'