共用方式為


類型推斷

本主題說明 F# 編譯器如何推斷值、變數、參數和傳回值的型別。

型別推斷概論

型別推斷的概念是讓您不需要指定 F# 建構的型別,但編譯器無法明確推斷型別時除外。 省略明確型別資訊並不表示 F# 是動態型別的語言,或 F# 的值是弱型別。 F# 是靜態型別語言,表示編譯器會在編譯期間推算每個建構的確切型別。 如果編譯器沒有足夠的資訊來推算每個建構的型別,您就必須提供其他型別資訊,方法通常是在程式碼中某個位置新增明確的型別註釋。

參數和傳回型別的推斷

在參數清單中,您不需要指定每個參數的型別。 然而,F# 是靜態型別語言,因此每個值和運算式在編譯階段都有明確的型別。 如果您未明確指定型別,編譯器會根據內容推斷型別。 如果未指定型別,編譯器會推斷為泛型。 如果程式碼使用值的方式不一致,沒有任何推斷的型別滿足所有值的使用,則編譯器會回報錯誤。

函式的傳回型別取決於函式中最後一個運算式的型別。

舉例來說,在下列程式碼中,參數型別 ab 及傳回型別全都推斷為 int,因為常值 100 的型別為 int

let f a b = a + b + 100

您可以變更常值來影響型別推斷。 如果您附加尾碼 u,使得 100 成為 uint32,則 ab 的型別和傳回的值會推斷為 uint32

您也可以使用其他會對型別暗示限制的建構來影響型別推斷,例如僅會使用特定型別的函式和方法。

此外,您可以將明確的型別註釋套用至函式或方法參數,或套用至運算式中的變數,如下列範例所示。 如果不同條件約束之間發生衝突,就會產生錯誤。

// Type annotations on a parameter.
let addu1 (x : uint32) y =
    x + y

// Type annotations on an expression.
let addu2 x y =
    (x : uint32) + y

您也可以在所有參數之後提供型別註釋,明確指定函式的傳回值。

let addu1 x y : uint32 =
   x + y

型別註釋對參數產生作用的常見案例是,參數是物件類型,而您想要使用成員。

let replace(str: string) =
    str.Replace("A", "a")

自動一般化

如果函式程式碼不需依賴參數的型別,編譯器會將參數視為泛型。 這稱為「自動一般化」,如果想在撰寫泛型程式碼時不要增加複雜度,這種特性非常有幫助。

舉例來說,下列函式會將任何型別的兩個參數合併成 Tuple。

let makeTuple a b = (a, b)

型別推斷為

'a -> 'b -> 'a * 'b

其他資訊

F# 語言規格會更詳細說明型別推斷。

另請參閱