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