3

我正在使用 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()

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

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

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

this.Let 12
this.Bind 一些 12
this.Bind 一些 11
this.Bind 一些 30

但我的实际结果如下:

this.Bind: 一些 11
this.Bind: 大约 30

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

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

看起来计算表达式的规范已经改变。let绑定不再被视为语法糖,计算Let工作流程中不再需要成员吗?

4

3 回答 3

4

你自己有答案。来自描述如何翻译计算表达式的F# 规范

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

所以不,您不再需要明确定义 let ,它由编译器翻译。

更新:9 月 CTP 的详细发行说明中提到了此更改。

于 2009-04-03T21:18:54.900 回答
0

正确 - 您不能再为 let :( 提供绑定。

于 2009-04-03T21:29:51.363 回答
0

另请参阅 http://cs.hubfs.net/forums/thread/6950.aspx

于 2009-04-03T22:59:38.980 回答