ARTISAN CODE

Software craftsmanship by design

Slightly confusing F# error messages

Posted by Tom Kuhn on October 2, 2014

Recently, I’ve been delving into F#. Not for any purpose other than blowing my mind with a new (functional) way of thinking. In order to facilitate my exploration, I’ve been using the Project Euler site as a way of focusing my learning on a finite and measurable set of problems. This also has the added benefit that I get to think and design fun little algorithms to solve the problem at hand. If you’re interested in checking out the F#, feel free to have a look at the code at my Git Hub repository. WARNING: I’m very much still learning F# and functional programming so I realise that there are probably much more idiomatic solution to the problems so please don’t and blindly use any snippets in any production code (not that I think you would anyway!). If there is anything that can be improved (i.e. you feel that you want to teach me some more idiomatic F#!) or you have any questions, then please don’t hesitate to get in touch with me in the comments.

Now onto the real meat of this post: F# has some mightily confusing (at least to a newbie) error messages. Take for example the following code:

let threshold x =
    if x >= 0.5 then
        1
    0

generates the following message (referencing line 3):

This expression was expected to have type
unit
but here has type
int

To my mind the threshold function should be analogous to the following C# function:

public int threshold(decimal x)
{
    if (x >= 0.5)
    {
        return 1;
    }

    return 0;
}

… except its not! I’m sure that there’s a reason for this that I haven’t been able to ferret out, but F# requires you to have the else clause specified. So the correct version of the F# is actually:

let threshold x =
    if x >= 0.5 then
        1
    else
        0

This is all fine and dandy, I can get on board with the necessity of specifying the else clause its not needed in C# but that’s fine. What I really struggle with is the fact that the error message is so unhelpful (at least to a self-confessed newbie). It took me more time then I’d like to admit in order to find the solution to this problem. Needless to say the action function I was debugging was a fair bit more complex than the simple example above, but the point still stands. What does not being able to convert a unit –> int have to do with a missing else clause? I’m aware that people are actually using F# in a production environment and if it works then great! But in order to help the wider spread adoption of the language, I can’t help but feel that some work needs to go into the error messages that get generated to help those who are new to the language and maybe new to functional programming. This isn’t me trying to throw stones (people living in glass houses and all), just trying to make a point! That said if I ever pluck up the courage to go and look at the F# repository (now that Microsoft has open sourced it) I’ll be sure to look at the F# contribution page and see if I can add anything to help improve the usability of the F# error messages.

Edits:

  1. [02-Oct-2014 @ 17:25] Thanks to Jeremy in the comments who correctly pointed out that ‘uint’ is not the same as ‘unit’. I’ve amended the post to remove my mistake and make the post make (more) sense