【问题标题】:Computation Expression doesn't execute Let计算表达式不执行 Let
【发布时间】:2009-04-03 21:00:46
【问题描述】:

我使用的是 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# 被破坏,无法阅读。)

spec for computation expressions 似乎已更改。 let 绑定是否不再被视为语法糖,计算工作流中是否不再需要 Let 成员?

【问题讨论】:

    标签: f# monads computation-expression


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 谢谢 :) 在发布我的问题之前,我实际上通读了这些发行说明,但并不完全确定,因为 100% 的示例演示了可能的 monad 定义了一个 Let 成员。
    【解决方案2】:

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

    【讨论】:

    • 为什么是悲伤的脸?我的意思是,我可以看到你失去了一些灵活性,但你有它的用例吗?乍一看,它看起来比有用更令人困惑。
    • 我不认为这是一件坏事,我个人不喜欢重新定义 let 含义的想法。
    • 上次我检查它(几个月前)是编写一个组合工作流,它执行一些“异步”(特定于应用程序)以及在每个执行的语句上都有提前终止的可能性。不难解决,只是会很可爱。我当然没有像 F# 那样分析它:)。
    【解决方案3】:

    【讨论】:

      猜你喜欢
      • 2018-07-05
      • 2012-12-16
      • 2011-09-05
      • 2012-04-29
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      • 2011-12-30
      • 2014-07-22
      相关资源
      最近更新 更多