2010-10-01 43 views
3

爲什麼這編譯:混淆錯誤使用F#有源圖案

let (|T|F|) b = 
    let f (o:int) : obj = null 
    if b then T else F(f) 

而失敗:

let (|T|F|) b = 
    let f (o:obj) : obj = null 
    if b then T else F(f) 

的兩個例子之間的差異是參數「O」被強制轉換到任何一個' int'(compiles)或'obj'(編譯失敗)

+0

我不禁想知道你的目標是什麼。 – ChaosPandion 2010-10-01 22:00:58

+0

是的,我知道它的奇怪的代碼。我正在編寫一些F#類型的反射代碼,活動模式返回一個在'obj'上運行的函數。我貼的代碼顯然是無用的:) – 2010-10-02 11:49:19

回答

8

這是一個不幸的類型推斷角的情況。這將工作:

let (|T|F|) b : Choice<unit,obj -> obj> = 
    let f (o:obj) : obj = null 
    if b then T else F(f) 

在你的原代碼,儘管你的註釋(o:obj),F#推斷o實際上可以是任何類型'a,從而導致bool -> Choice<unit,'a -> obj>類型的通用活動模式。由於'a是一個自由類型變量,因此F#不會接受此活動模式定義。你可以看到一個類似的問題,如果你這樣做:

let (|T|F|) b = 
    if b then T else F [] 

此外,該解決方案將是monomorphize定義:

let (|T|F|) b : Choice<unit,int list> = 
    if b then T else F [] 
+0

很好的解釋,謝謝! – 2010-10-02 11:47:16