2012-02-09 48 views
2

为什么不能正常工作?函数签名中的F#模式匹配

type RetryBuilder(max) = 
    member x.Return(a) = a    // Enable 'return' 
    member x.Delay(f) = f    // Gets wrapped body and returns it (as it is) 
             // so that the body is passed to 'Run' 
    member x.Zero() = failwith "Zero" // Support if .. then 
    member x.Run(f) =     // Gets function created by 'Delay' 
    let rec loop 0 (Some(ex)) = raise ex 
    let rec loop n maybeEx = try f() with ex -> loop (n-1) (Some(ex)) 
    loop max None 

let retry = RetryBuilder(4) 

它说'不完整的模式匹配这个表达式。例如,值'1'可能表示模式未涵盖的情况'。

但为什么不能匹配下面的那个?如果我没有记错,Haskell会匹配,为什么不F#?

回答

5

您正在用Haskell语法编写F#代码。你的代码编译的原因是F#编译器认为有两个loop函数,前者被后者遮蔽。很明显,在第一个loop函数中,模式匹配失败,第一个参数的任何整数与0不同,而第二个参数的None不同。

的声明接近Haskell语法可能是:

let rec loop = function 
    | 0, Some ex -> raise ex 
    | n, maybeEx -> try f() with ex -> loop (n-1, Some ex) 
loop(max, None) 
+0

有趣;不错的和紧凑的,但W /元组,而不是F - N的应用 – Henrik 2012-02-09 19:21:50

+0

虽然我仍然感兴趣;为什么F#无法完成上述工作? – Henrik 2012-02-09 19:22:24

+1

我认为这是由于历史原因。您的声明也不适用于OCaml/SML。与Haskell不同,在OCaml/F#中,你必须使用'let(rec)'来声明函数;让“rec”似乎不合算。 – pad 2012-02-09 19:38:31