Reputation: 2246
This code
let rec readNLines n list =
if n = 0 then
list
else
readNLines(n-1,readInt()::list)
ends with
Type mismatch. Expecting a 'a but given a 'a -> 'a
The resulting type would be infinite when unifying ''a' and
''a -> 'a' (using built-in F# compiler)
but runs ok when last line is changed to
readNLines(n-1,(readInt()::list))
or
readNLines(n-1)(readInt()::list)
Question is: Why? :|
Upvotes: 0
Views: 472
Reputation: 13577
Take a look at these two functions:
> let f1 a b = a + b
val f1 : a:int -> b:int -> int
> let f2 (a, b) = a + b
val f2 : a:int * b:int -> int
As you can see, they have slightly different types. In function f1
you partially apply the arguments (you'll see the term 'curried function' used here), in function f2
you pass in a tuple of arguments in one "go", or you can think of it as only ever having a single argument (an 'uncurried' function).
What you're doing is defining a function f1
style, but later calling it f2
style, which confuses the compiler.
Upvotes: 2
Reputation: 6629
Only the last version can work, because readNLines
takes two arguments, but
readNLines (n - 1, readInt() :: list)
passes only one argument (which is a tuple consisting of an int
and the list
).
readNLines (n - 1) (readInt() :: list)
passes them as two separate arguments - the difference here is using the comma (tuple) and space (two arguments).
By the way, that becomes much clearer when you use more whitespace (as I did), because the individual elements are easier to identify.
Upvotes: 8