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.
"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:
let f : 'a -> 'a option =
let r = ref None
fun x ->
let old = !r
r := Some x
old
f 3 // r := Some 3; returns None : int option
f "t" // r := Some "t"; returns Some 3 : string option!!!
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:
let sum : int seq -> int = Seq.reduce (+)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With