Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This message is given when a value is determined to have a type that doesn't unify with a type that has been expected.
The following code demonstrates a simple version of the error:
let booleanBinding: bool = 10
This code results in the following output:
error FS0001: This expression was expected to have type
'bool'
but here has type
'int'
Here, the type of the booleanBinding is required to be bool by the type annotation. However the value 10 is inferred to be int. Because int is not the same as bool, this message is reported.
This message can be issued in many different circumstances, and they all follow this same pattern. Type inference (or programmer-given type annotations) 'fixes' the type of a function or value to a certain type, and then later that type is used as if it were of a different type than the 'fixed' type. The following code demonstrates a more complex version of the error, where inference across functions causes the error to appear far away from where you might expect:
// 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
Partial Application and Type Inference
Another common scenario where this error occurs involves partial application of functions. When you define a function with multiple parameters using let bindings, F# treats it as a curried function. This means that applying fewer arguments than the function expects returns a new function that expects the remaining arguments, as shown in the following example:
// 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'
In this example, Sum is a function with type int -> int -> int. When you pass it to RegisterFunction1, the type inference system maps 'A to int and 'B to int -> int (the partially applied function). However, when you try to pass it to RegisterFunction2, which expects 'A -> int, the type system correctly identifies that Sum returns int -> int (a function), not int (a value), causing the type mismatch error.
For more information about how F# handles function definitions and partial application, see Functions.
How to Fix This Error
To solve this message, you must change one of the two parts of the binding: the type annotation or the value binding.
If the value is correct, change or remove the type annotation.
If the type annotation is correct, check the value bound and ensure that no logic errors have been made.