Adventures in F# - F# 101 Part 1

Update:  Added more topics
In some previous posts, I pointed you to a bunch of links to help get me started.  I'm still working on some more thorough examples, but this time around I'm going to walk you through the F# 101 much like I did with Spec#.  What we first need to understand is the key differences between imperative and functional programming. 

I've really enjoyed Robert Pickering's book Foundations of F# and Don Syme's Expert F# book as they both give a good overview of not only the language, but the uses.  It's a lot for some stuck in the imperative world to think about functional programming, but these books do their job well.

So, today I'd like to cover the following topics:
  • Hello World Sample
  • #light
  • Functions == Values basics
Hello World Example

As I like to do with most languages, I know it sounds trite, but Hello World, especially in .NET languages is interesting, especially how they translate in IL through Reflector.  F# is especially interesting in this case as it is a functional language built on top of a imperative framework such as the CLI and C#. 

So, let's walk through a simple example.  First, of course you need to have F# installed which can be found here.  Then go ahead and create a new F# project, which should be under the Other Project types.  By default, it will not give you any classes as part of your project.  So, go ahead and add an F# Source File.  It will give you the extension of .fs by default.  I went ahead and created a class called HelloWorld.fs.  Get rid of the default text that is in there, and it is plenty, and just put in the following code:

#light

print_endline "Hello World"

As you can see from the simple example above, we've put in the #light directive.  I'll cover what that means shortly.  But anyways as you can notice it calls a default global function called print_endline.  I always like to look at what the code compiles to in Reflector to IL, so let's take a look at that.



What's really interesting to see from the above, by default, it created the main function for us without us explicitly doing so.  Also, it notes that we are calling an OCaml function.  If you look through Reflector and the FSharp.Compatibility.dll, you'll notice it takes a few things from OCaml as its base.

Where to Turn

As always, if you have problems, the specification and the books help out well with this.  If you should get lost, the information F# specification is very good at defining the language and can be found here.

Stay in the #light


From the above example and many other examples you will see from me, you'll notice the #light directive at the top of every source file.  What this does is that it makes all whitespace significant.  This directive allows you to omit such things as begin, end, in and the semi-colon.  When defining functions and so on, you indent your code to make it fall under that scope implicitly by using that directive.

Identifiers, Keywords and Literals

In F#, it's important to realize that variables, aren't really variables, more like identifiers.  In pure functional programming, it's fundamental to understand that once a "variable" is assigned, it is immutable.  However, if using F# an imperative way of thinking, then it can be.

To make a simple assignment, just use the simple let keyword such as this:

#light

let message =  "Hello World"
printfn "%s" message

One of these identifiers can be either either just a simple value, or even a function, since these functions are values as well.  I'll cover that more shortly in the next section. 
#light

let rec fib n = if n < 2 then 1 else fib (n-2) + fib(n-1)
printfn "%i" (fib 10)

I think this example went a little too far with adding recursion, but you get the point that it's pretty easy to define a function much as you would with any old "variable".  Also, you may note, I'm not returning anything from this function, but in fact I am returning the Fibonacci sequence that I asked for.

If you also note the keywords, there are a lot of direct mappings from C# to F#, but it's also interesting that it has a list of reserved keywords for future use such as mixin.  Now, if we finally brought mixins to .NET, well, then I'm all for it.

Of the types that exist in F#, the only ones to note that are completely different are:
  • bigint - Microsoft.FSharp.Math.BigInt
  • bignum - Microsoft.FSharp.Math.BigNum
It's interesting to know that the .NET framework's BigInteger class is internal, yet these are publicly available.  Both of these are rational large integers just in case you need that kind of thing.

Functions == Values?

Once again, like I said above, functions and values are one in the same in the pure functional programming stance.  You noticed that in my functions, I'm not returning anything, nor is it imperative that you do so explicitly.  This boggles many of OO mindsets, I'm sure and there are a lot of things in FP that an OO person may have problems with.

Let's walk through another simple function, but this time, we'll implement that main function and look at the results through Reflector.

#light

let rec fib n = if n < 2 then 1 else fib (n-2) + fib(n-1)
let print x = printfn "%i" x

let x1 = fib(10)
let x2 = fib(20)

let main() =
  print x1;
  print x2

main()

From the above sample, I created two functions, a recursive Fibonacci sequence function from above, and I also created a print function which calls the native printfn function which is a variation of the printf function with a newline at the end.  For those who are curious about what it looks like in Reflector, let's take a look, and this time in C#.  Instead of pasting a bunch of screenshots, it's much easier to paste it below the pieces we're interested in.

fib function:
public static int fib(int n)
{
    if (n < 2)
    {
        return 1;
    }
    return (fib(n - 2) + fib(n - 1));
}

print function:
public static void print(int x)
{
    Pervasives.printfn<FastFunc<int, Unit>>(new Format<FastFunc<int, Unit>, TextWriter, Unit, Unit>("%i")).Invoke(x);
}

main function:
public static void main()
{
    print(get_x1());
    print(get_x2());
}

So, as you can see, it's doing much like we think it would be, as it fit everything into our HelloWorld class.  The more interesting pieces are how C# and F# functions differ.  It's just interesting to see how FP fits on top of an imperative programming framework.

Next time, I'll cover more with functions such as Currying, Tuples, Recursion, Scopes and so on.  Plus I need to talk about the interop story here which is strong between F# and C# as well.  There's a lot to cover and quite frankly, it's making me stronger as well to go over this time and time again.

Conclusion

This is the first post in the series.  As you can see, I have plenty to cover in the next installment.  If you like the series and so on, subscribe and keep coming back.  Until next time...

kick it on DotNetKicks.com

3 Comments

Comments have been disabled for this content.