在计算表达式中运行方法

时间:2010-10-14 20:27:51

标签: f#

计算方法中Run()方法的状态是什么?我在几个例子中看到了它(hereherehere),我在其中看到了F#的编译器源代码,但它不在specMSDN documentation。我提交了一份关于此问题的issue in MS Connect,它被“按设计”关闭,没有进一步解释。

它是否已弃用/未记录/不受支持?我应该避免吗?

更新:MS Connect问题状态已及时更改,MSDN页面已更新为包含Run()

2 个答案:

答案 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和其他延迟计算根本不是一个好主意。