Given the following expression to sum an IEnumerable of numbers:
let sum l = l |> Seq.reduce(+) //version a
is it possible to eliminate the argument--like so?
let sum = Seq.reduce(+) //version b
I get an error from the F# compiler (FS0030) and I seem to recall having seen something about an "eta conversion" being involved but unfortunately my knowledge of lambda calc is too limited to follow how eta conversion is involved.
Can the argument be eliminated as in version b?
Would someone please point me to literature that would explain an eta conversion and how it would come into play in this particular piece of code?
FS0030:
stdin(1,5): error FS0030: Value restriction. The value 'sum' has been inferred to have generic type val sum : ('_a -> int) when '_a :> seq Either make the arguments to 'sum' explicit or, if you do not intend for it to be generic, add a type annotation.
A point-free function is a value.
As other answers say, F# does not allow generic values. However, it perfectly allows generic functions. Let's convert
sum
into a function by adding a fakeunit
parameter:This works, although it is not yet generic. Marking the function
inline
does the trick:"Eta conversion" simply means adding or removing the argument. The problem you are hitting is called value restriction. In ML languages, a value declared as a value, ie. declared without explicit arguments, cannot have a generic type, even if it has a function type. Here is some relevant literature. The idea is to prevent a ref cell from holding values of different types. For example, without value restriction, the following program would be allowed:
As kvb said, if you do not intend the function to be generic, then you can add a type signature and use point-free style.
You can do it in point free style, but you need to add a (monomorphic) type annotation: