如果我有一個函數定義爲任何避免這種類型推斷問題的方法?
let test = function
| [] -> None
| head::tail -> Some(head)
FSI可以讓我定義這個編譯就編譯它;但如果我真的試圖做test []
,它會崩潰。
現在我知道推理,當我給它一個空集,它不能推斷類型,所以通用函數失敗,但它可以做一些有點聰明嗎? (沿着「我不知道'a
的類型,但在這種情況下,我不使用'a
,所以我打算允許這樣做」)。這個問題?
如果我有一個函數定義爲任何避免這種類型推斷問題的方法?
let test = function
| [] -> None
| head::tail -> Some(head)
FSI可以讓我定義這個編譯就編譯它;但如果我真的試圖做test []
,它會崩潰。
現在我知道推理,當我給它一個空集,它不能推斷類型,所以通用函數失敗,但它可以做一些有點聰明嗎? (沿着「我不知道'a
的類型,但在這種情況下,我不使用'a
,所以我打算允許這樣做」)。這個問題?
有一個偉大的article about value restriction MSDN和additional notes about tricky aspects布賴恩,詳細解釋這個問題。
當您編寫test []
時,結果的類型爲option<'a>
,因此編譯器需要知道要使用的類型來代替'a
。您實際上並未使用類型'a
的值,但編譯器需要編譯使用它的代碼。 F#不允許使用通用值(一般),因此該值需要具體的類型。
您可以編寫類似:
let foo() = test []
這是unit -> option<'a>
類型的標準通用功能,所以這是一個完全有效的結構。您還可以使用類型批註指定結果明確的類型:
(test []:option<obj>)
很好的類型,你可以寫讓foo()= test [] - 但當你試圖執行它時,foo仍然會出錯...那裏的樂趣在哪裏?標記爲答案因爲指定obj看起來像是唯一的方法。 – Massif 2011-06-07 14:01:32
@Massif - 問題是,你想如何使用結果,輸入列表從哪裏來?在任何實際的例子中,你都會在一些指定類型的上下文中使用代碼。 (Brian的文章中的部分函數應用程序示例並非如此,但是您的代碼可能會出現在更廣泛的上下文中。) – 2011-06-07 14:04:27
這很可能是真的 – Massif 2011-06-07 14:06:22