I’ve been spending some time recently looking at F# - I have a specific task in mind to which F# seems very well suited, so the motivation is there! After many years doing C then C++ and now C#, it’s easy to fall into the trap of thinking some things work just the same in F#.
One example of this is functions. I was happily experimenting with some code, thinking I was getting the measure of F#, but one small detail kept catching my eye - the very strange types reported for functions.
It all starts off simple enough - when you assign an expression to a value in F# Interactive, it reports back with the type it has inferred:
>let myStr = "Hello World"
val myStr : string
Simple enough. Now what happens if we create a function:
>let toStr n = sprintf "%d" n;;
val toStr : int -> string
This makes perfect sense too, as we’ve created a function that takes an int and returns a string.
Now lets add a second argument:
>let makeTable n v = [| for i in 0..n -> v*i |];;
val makeTable : int -> int -> int array
Initially, I could not see why F# reported the function type in such an unusual way. The function takes two arguments and returns an array, but the reported type reads “a function that takes an int and returns a function that takes an int and returns an array“. Why so complex? If this was true, could we call the function with a single argument, and expect a new function back, like this…
>let partTable = makeTable 10;;
Yes! that works:
val partTable : (int -> int array)
When we call this function, its captured the first parameter, and completes as expected:
>partTable 9;;
val it : int array [|0; 9; 18; 27; 36; 45; 54; 63; 72; 81; 90|]
More on this to come.