Tuesday, December 11, 2012

Neat F#: Inferred Return Types

What is the return type of this F# function?
let hello name = sprintf "Hello %s" name
If you guessed string, you're correct! I know this syntax can be confusing at first glance, so here it is one element at a time:
  • let hello name =
    let: the "let binding's" job is to associate a variable name with a value or function.  It BINDS things to names
    hello: hello is the name of the function
    name: hello takes one parameter, and it called name, and it's type will be inferred
  • sprintf "Hello %s" name
    sprintf: basically F#'s version of .net's String.Format, it's a function that takes a format string with placeholders and values as arguments and returns a string.  In fact, this function is so neat it deserves it's own post.
    "Hello %s": the format string, %s tells the compiler a string parameter is required
    name: argument to sprintf
sprintf returns a string, therefore the hello function returns a string.  Notice there's no explicit return statement, whatever the last statement returns the function returns.  However, this is made more interesting by the fact that just about everything in F# is a statement that returns a value, including if statements:
let hello name =
    if name = "kwb" then
        "'sup KBizzle!"
        sprintf "hello %s" name
This function still returns a string, because the if statement returns a string. Note this means in F# the if and the else must return the same type!

Also note, there's nothing wrong with that last code sample, but it's my impression that if statements are generally frowned upon in F# in favor of pattern matching. A true F# dev would probably have written that last using the pattern matching function syntax like this:
let hello =
        | "kwb" -> "'sup KBizzle!"
        | _ as name -> sprintf "hello %s" name
That's really outside the scope of this post, but it makes me happy!

So this brings us to the _really_ neat part: functions with changing return types.  All the functions we've seen so far have had a single static return type.  But what about this function?
let crazy f =
    f 4
What is it's return type? Maybe this will help?
let somestring x = sprintf "the number %d" x
let someint x = x

crazy somestring
crazy someint
Crazy's return type is different depending on what function we pass to it!
mind blown