用let!内部匹配语句导致编译错误

Oen*_*ria 14 f#

使用let有一些限制!里面的比赛声明?我不确定为什么这不会编译.

module Foo =
  let Bar =
    async {      
      let result =
        match 1 with
        | 1 ->
          let! num = async.Return 12345 // Doesn't compile
          1
        | _ -> 2

      return result
    }
Run Code Online (Sandbox Code Playgroud)

编译失败,"此构造只能在计算表达式中使用"

Tom*_*cek 10

如前所述,问题在于异步工作流只允许某些类型的嵌套 - 您不能let!在普通表达式中使用,而只能在计算表达式中使用.在您的例子的问题是不是真的match,但let(包含match).为了更好地了解发生了什么,规范(粗略地)看起来如下:

cexpr:= 让!x = expr in cexpr
           |   X = EXPR cexpr
           |  返回! expr
           | (......)

关键是参数只是一个普通的表达式expr和正文跟随let或是let!另一个可以包含更多异步操作的计算表达式.

所以,如果你有let x = e1 in e2,那么你只能let!e2,但不是e1.

在实践中,您可以执行Daniel建议并使用嵌套异步工作流,或者您可以重写代码,以便需要异步的代码不会使用等待内部表达式,这是不可能的 - 很难说如何做一般情况下,但在您的具体示例中,您可以写:

let bar = async {      
  match 1 with
  | 1 ->
      let! num = async.Return 12345 
      return 1
  | _ -> 
      return 2 }
Run Code Online (Sandbox Code Playgroud)


Dan*_*iel 7

Bind(via let!)的调用必须出现在计算表达式的顶层.您可以通过创建嵌套async { }块来修复它:

module Foo =
  let Bar =
    async {      
      let result = async {
        match 1 with
        | 1 ->
          let! num = async.Return 12345
          return 1
        | _ -> return 2
      }
      return result
    }
Run Code Online (Sandbox Code Playgroud)