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совпадает с данным сообщением.

Это сообщение может быть выдано во многих различных обстоятельствах, и все они следуют этому же шаблону. Вывод типа (или заметки с заданным программистом типа) "исправляет" тип функции или значения определенного типа, а затем затем этот тип используется так, как если бы он был другим типом, чем "фиксированный". Следующий код демонстрирует более сложную версию ошибки, где вывод между функциями приводит к возникновению ошибки далеко от места ожидания:

// 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, система типов правильно определяет, что Sum возвращает int -> int (функция), а не int (значение), что приводит к ошибке несоответствия типов.

Дополнительные сведения о том, как F# обрабатывает определения функций и частичное приложение, см. в разделе "Функции".

Как исправить эту ошибку

Чтобы решить это сообщение, необходимо изменить одну из двух частей привязки: заметку типа или привязку значения.

  • Если значение правильно, измените или удалите заметку типа.

  • Если заметка типа правильна, проверьте привязку значения и убедитесь, что ошибки логики не были сделаны.