2012-02-03 97 views
4

考慮以下幾點:類型和功能

type T() = 
    member x.y = 4 

let a = 
    let fn() (k: T) =() 
    fn() 

let b = 
    let fn() (k: System.IO.Directory) =() 
    fn() 

ab是確定的失敗。錯誤消息是:

當'_a:> T或者將參數設置爲'a'時,值'a'已被推斷爲泛型類型val a:('_a - > unit)如果你不打算這是通用的,添加一個類型註釋

爲什麼以及如何解決這個問題?

回答

6

錯誤消息本身會告訴你到底你需要做的是什麼 - 添加類型註釋:

let a : T -> unit = 
    let fn() (k: T) =() 
    fn() 

,你看到的錯誤擺在首位的原因是編譯器試圖概括的定義a(請參閱規範的this part),這會導致您在錯誤消息中看到的奇怪簽名。

你不需要這樣做的原因是bSystem.IO.Directory是密封的,所以不需要一概而論。

1

您正面臨價值限制,因爲a看起來像一個常量,但它返回一個函數。 看一看這個問題:

Understanding F# Value Restriction Errors

一個簡單的方法來解決它是加入一個變量的a定義。

let a x = 
    let fn() (k: T) =() 
    fn() x 

我不知道爲什麼有些類型它的工作原理,這是b

+0

但是,向定義中添加'x'會將'a'從函數值更改爲函數,這意味着它不會在啓動過程中進行評估。有關完整的解釋,請參見[F#值,函數和一點點](http://blog.wezeku.com/2010/08/01/values-functions-and-a-bit-of-both)。 – 2012-02-03 14:07:19

0

如果T,其中一條記錄,而不是一類,它會工作的情況。但由於某些原因,你必須拼出來的,如果T是一個類的編譯器,

type T() = 
    member x.y = 4 

let a<'U when 'U :> T> = 
    let fn() (k: 'U) =() 
    fn() 

let test0 = a<T> (T()) // You can be explicit about T, 
let test1 = a (T())  // but you don't have to be. 

編輯:所以我打得多一點這個,和古怪,編譯器似乎滿足於僅僅任何類型的限制:

type T() = 
    member x.y = 4 

type S() = 
    member x.z = 4.5 

let a<'U when 'U :> S> = 
    let fn() (k: T) =() 
    fn() 

let test = a (T())  // Is OK 
let test = a<T> (T()) // Error: The type 'T' is not compatible with the type 'S' 

S型無關,與上面的代碼中任何東西,還編譯器是幸福的,只是有什麼樣的限制。