2010-01-27 45 views
1

爲什麼不允許這樣做?類型(unit - > unit)的函數是否可以在F#中靜態解析類型參數?

type Foo() = 
    static member Bar() =() 

let inline bar<^a>() = //ERROR: unexpected infix operator in pattern 
    (^a : (static member Bar : unit -> unit)()) 

//Hypothetical usage: let _ = bar<Foo>() 

...但這工作正常嗎?

type Foo() = 
    static member Bar() = new Foo() 

let inline bar() : ^a = 
    (^a : (static member Bar : unit -> ^a)()) 

let x : Foo = bar() 

函數是否具有靜態解析類型參數以返回解析類型的實例?

回答

6

正如您所注意到的,F#將字符序列<^視爲中綴運算符,因此您需要使用空格將它們分開。至於什麼時候需要明確指定約束的問題,我相信規則是當你明確地給出一個函數類型參數時,你還需要指定任何必要的約束。否則,如果F#可以推斷出類型參數和約束,則不需要指定它們。

所以,從你的問題這個例子正常工作:

let inline bar() :^a = 
    (^a : (static member Bar : unit -> ^a)()) 

爲將這樣的:

let inline bar(x : ^a) = 
    (^a : (static member Bar : unit -> unit)()) 

因爲有一個泛型類型參數,但是你有沒有明確的把它放在功能,和F#可以推斷出所需的約束條件。

在另一方面,如果你試圖修改其他例子省略明確泛型參數:

let inline bar() = 
    (^a : (static member Bar : unit -> unit)()) 

你會看到,F#不會允許這一點,因爲沒有辦法爲它圖瞭解如何爲bar()的任何給定調用實例化^a。因此,你需要明確地提供類型參數,一旦你這樣做,你也必須明確提供約束。

+0

'F#將字符序列<^作爲中綴運算符,因此您需要將它們與空格分開+1 – 2016-05-10 11:53:09

1

想通了。需要尖括號內的空格以及約束條件。

這工作:

type Foo() = 
    static member Bar() =() 

let inline bar< ^a when ^a : (static member Bar : unit -> unit) >() = 
    (^a : (static member Bar : unit -> unit)()) 

let _ = bar<Foo>() 

由此我們可以推測,該約束是可選的,如果該函數返回靜態解析類型的實例。有誰知道這是否是規則?

相關問題