FS0001:新增類型方程式時發生錯誤

當值判斷為具有未與預期型別統一的類型時,就會提供此訊息。

下列程式代碼示範錯誤的簡單版本:

let booleanBinding: bool = 10

此程式代碼會產生下列輸出:

error FS0001: This expression was expected to have type
    'bool'
but here has type
    'int'

在這裡,型別批注需要 booleanBinding 的型bool別。 不過,此值 10 會推斷為 int。 因為 int 與不同 bool,因此會報告此訊息。

此訊息可以在許多不同的情況下發出,而且它們全都遵循相同的模式。 類型推斷(或程式設計人員指定的型別註釋)會將函式或值的類型「修正」為特定類型,然後稍後使用該類型,就好像它的類型與 'fixed' 類型不同。 下列程式代碼示範較複雜的錯誤版本,其中跨函式的推斷會導致錯誤看起來遠離您預期的位置:

// this function has type `int -> int`.
// `+` takes the type of the arguments passed to it, and `1` is of type `int`, so
// `+` must be of type `int -> int`
let addOne i = i + 1

// this function has type `int -> int`, which may be surprising because no types are explicitly specified.
// the `printfn` call on the first line is of type `'a -> unit`, because `printfn "%A"` takes a value of any type and returns unit.
// this means that the type of the `i` parameter hasn't yet been decided based on how the parameter is used.
// the `addOne` call on the second line is of type `int -> int`, because `addOne` is of type `int -> int` (see above).
// this means that `i` _must_ be of type `int`, so the overall type signature of `printThenAdd` is inferred to be `int -> int`
let printThenAdd i =
    printfn "%A" i
    addOne i

// this line triggers the error
// > This expression was expected to have type
// >   'int'
// > but here has type
// >   'string'
// because `printThenAdd` has been inferred to have type `int -> int`, but a string was passed in as the `int` parameter
printThenAdd "a number"
|> ignore

部分應用和類型推斷

發生此錯誤的另一個常見情況涉及函數的部分應用。 當您使用繫結定義let具有多個參數的函式時,F# 會將它視為柯利函式。 這表示套用的引數少於函式預期的引數,會傳回預期剩餘引數的新函式,如下列範例所示:

// Define a function that takes two arguments and returns their sum
let Sum x y = x + y

// This works: RegisterFunction1 accepts a function with generic types 'A -> 'B
// When passed Sum (which is int -> int -> int), type inference maps:
// 'A to int (the first parameter type)
// 'B to int -> int (the remaining function after partial application)
let RegisterFunction1 (fn:'A->'B) = ()
let Test1 = RegisterFunction1 Sum

// This fails: RegisterFunction2 expects a function 'A -> int (returning int, not a function)
// When passed Sum (which is int -> int -> int), type inference maps:
// 'A to int (the first parameter type)
// But then expects the return type to be int, not int -> int (the partially applied function)
let RegisterFunction2 (fn:'A->int) = ()
// Uncommenting the next line would trigger the error:
// > This expression was expected to have type
// >   'int -> int'
// > but here has type
// >   'int -> int -> int'

在此範例中, Sum 是類型 int -> int -> int為 的函數。 當您將它傳遞給 RegisterFunction1時,類型推斷系統會對應 'Aint'Bint -> int 部分套用的函數)。 但是,當您嘗試將其傳遞給 RegisterFunction2時,該預期 'A -> int,類型系統會正確識別傳 Sumint -> int (函數),而不是 int (值),從而導致類型不匹配錯誤。

如需 F# 如何處理函式定義和部分應用程式的詳細資訊,請參閱 函式

如何修復此錯誤

若要解決此訊息,您必須變更系結的兩個部分之一:類型批注或值系結。

  • 如果值正確,請變更或移除類型批注。

  • 如果類型批注正確,請檢查系結的值,並確定尚未發生任何邏輯錯誤。