Give the following definition
let fn (id: int) (_:string) = id
I can create a partially applied function
let fnPartial = fn 1
However changing the type of _
to a non sealed type like IEnumerable
let fn (id: int) (_:IEnumerable) = id
Causes a compilation error
Value restriction. The value 'fnPartial' has been inferred to have generic type val fnPartial : ('_a -> int) when '_a :> IEnumerable Either make the arguments to 'fnPartial' explicit or, if you do not intend for it to be generic, add a type annotation. (using built-in F# compiler)
A bug was raised but closed with the following response
Yes this is by design - IEnumerable is not sealed where string is, and this causes the value restriction to trigger
The work around is to add a type annotation
let fn (id: int) (_:IEnumerable ) = id
let fnPartial<'a> = fn 1
Can someone explain
The key is that values are not allowed to be generic in F#. When you partially apply a function the result is a value.
In order to make the left hand side of a binding (or assignment) a function, you must define a parameter on the left hand side.
The error you're getting is a result of IEnumerable
not being specific enough for the value to be completely defined. Given IEnumerable
you do not know what you're iterating over, and therefore the compiler cannot determine a proper type for the value.
The answers to your question then are as follows:
Here is the relevant MSDN Docs: https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/dd233183(v=vs.100)#value-restriction