计算方法中Run()
方法的状态是什么?我在几个例子中看到了它(here,here,here),我在其中看到了F#的编译器源代码,但它不在spec或MSDN documentation。我提交了一份关于此问题的issue in MS Connect,它被“按设计”关闭,没有进一步解释。
它是否已弃用/未记录/不受支持?我应该避免吗?
更新:MS Connect问题状态已及时更改,MSDN页面已更新为包含Run()
答案 0 :(得分:8)
6.3.10计算表达式
更具体地说,计算 表达式的形式 builder-expr {cexpr}其中cexpr是, 句法上,语法 附加表达式 comp-expr中定义的构造。 计算表达式用于 序列和其他非标准 F#表达式的解释 句法。表达式builder-expr { cexpr}转换为
let b = builder-expr in b.Run (b.Delay(fun () -> {| cexpr |}C))
表示新变量b。如果此时没有方法Run在推断类型的b上存在 检查表达式,然后省略该调用。同样,如果>上没有方法延迟。检查此表达式时的b类型,然后省略该调用
答案 1 :(得分:4)
我认为Run
方法在开发过程中很晚才添加,所以这可能是文档中缺少它的原因。正如desco所解释的那样,该方法用于“运行”计算表达式。这意味着无论何时编写expr { ... }
,翻译的代码都将包含在对Run
的调用中。
该方法有点问题,因为它破坏了组合性。例如,要求对于任何计算表达式,以下两个示例表示相同的事情是明智的:
expr { let! a = foo() expr { let! c = expr {
let! b = bar(a) let! a = foo()
let! c = woo(b) let! b = bar(a)
return! zoo(c) } return! woo(b) }
return! zoo(c) }
但是,Run
方法仅在左侧示例中的整体结果上调用,在右侧调用两次(对于整体计算表达式和嵌套式)。该方法的通常类型签名是M<T> -> T
,这意味着正确的代码甚至不会编译。
出于这个原因,最好在创建 monads 时避免它(因为它们通常在Haskell中定义和使用),因为Run
方法打破了一些不错的方面单子。但是,如果你知道自己在做什么,那么它就会很有用......
例如,在我的break
代码中,计算构建器立即执行其主体(在声明中),因此添加Run
以打开结果不会破坏组合性 - 组合意味着只运行另一个码。但是,为Run
定义async
和其他延迟计算根本不是一个好主意。