计算表达式不执行Let

时间:2009-04-03 21:00:46

标签: f# monads computation-expression

我正在使用F#v 1.9.6.2,我已经定义了一个非常简单的计算表达式:

type MaybeBuilder() =
    member this.Let(x, f) =
        printfn "this.Let: %A" x
        this.Bind(Some x, f)
    member this.Bind(x, f) =
        printfn "this.Bind: %A" x
        match x with
        | Some(x) when x >= 0 && x <= 100 -> f(x)
        | _ -> None
    member this.Delay(f) = f()
    member this.Return(x) = Some x

let maybe = MaybeBuilder()

我在代码中添加了一些print语句,告诉我在计算表达式中调用了哪些方法。当我执行以下语句时:

maybe {
    let x = 12
    let! y = Some 11
    let! z = Some 30
    return x + y + z
}

我希望控制台打印出以下内容:

this.Let 12
this.Bind Some 12
this.Bind Some 11
this.Bind Some 30

但我的实际结果如下:

this.Bind: Some 11
this.Bind: Some 30

换句话说,F#似乎没有执行Let成员。当我重写Let以抛出异常时,代码运行时没有异常。此外,当我完全注释掉Let成员时,我收到一条说明The field, constructor or member 'Let' is not defined的错误消息,代码按预期执行。

(我已经尝试用Reflector调查代码,但通常情况下,反编译的F#超出了可读性。)

看起来spec for computation expressions已发生变化。 let绑定不再被视为语法糖,并且计算工作流程中不再需要Let成员吗?

3 个答案:

答案 0 :(得分:4)

你自己得到了答案。从描述计算表达式如何翻译的F# spec开始:

{| let binds in cexpr |}C  = let binds in {| cexpr |}C)

所以不,你不需要再明确定义let了,它是由编译器翻译的。

更新:the detailed release notes of the September CTP中提到了此更改。

答案 1 :(得分:0)

正确 - 你不能再为let :(。

提供绑定

答案 2 :(得分:0)