robkuz
robkuz

Reputation: 9914

F# Type inference with curried functions

I have the following code

let bar foo baz = foo, baz 

let z = bar 3
let z1 = z 2

however If I comment out the last line let z1 = z 2 I get an error

let z = bar 3
----^

stdin(78,5): error FS0030: Value restriction. 
The value 'z' has been inferred to have generic type
val z : ('_a -> int * '_a)    
Either make the arguments to 'z' explicit or, if you do not intend for it to be generic, 
add a type annotation.

I am completely lost on how the annotate the function correctly.

Upvotes: 3

Views: 89

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243041

What you are facing here is an aspect of F# called value restriction. This essentially means that if you define a value that is not syntactically a function, then it cannot be generic.

let bar foo baz = foo, baz

... is syntactically a function (it obviously has two arguments) and so it is inferred as generic. However:

let z = bar 3

... is not syntactically a function - it is just a value z that happens to be a function (because that's what the type of bar indicates). So, this cannot be generic. In your snippet, the genericity was restricted by the next line:

let z1 = z 2

This fixes the type of z to be int -> int * int. If you don't have this line, you can fix the type yourself:

let z : int -> int * int = bar 3

Or, you can make this a syntactic function which can be inferred as generic:

let z a = bar 3 a

For more information, search the various other SO questions and answers that discuss value restriction.

Upvotes: 6

Related Questions