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
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
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.
Getting Sidetracked
Last night at the DC ALT.NET meeting, Craig Andera and I discussed Lisp, F# and functional programming as a whole. His language of the year was Lisp and I thought that was an interesting choice of the language to learn, but when you think about it, most good things in programming lead back to SmallTalk and Lisp... I had been hearing a bit about IronScheme, the IronLisp rewrite, so of course I had to check it out. Maybe this will be one of my future languages to learn, but I had enough exposure during my college years to last a little bit, so it's on the plan anyways.
Basic Introduction
So, just in case you missed the idea of functional programming and what it means, I have a few posts on where you should start here:
The Joys of Currying
Where we left off last time was just dealing with the basics of functions and the fact that they are treated as values much like any other "variable". Now let's get into a popular topic among functional programming, a concept called Currying. The term was invented back in the earlier days of functional programming after the early logician Haskell Curry. He's so good in fact that he got not only a functional programming style named after him, but a language named after him with Haskell. If you listen to the DotNetRocks Episode 310 with Simon Peyton-Jones, you can learn more about that.
Anyhow, the basic idea of Currying is to take a function with multiple arguments and transform it into a function that passes in only one argument, with the other arguments specified in the Currying function itself. So you can think of it as a function that calls another function and returns a function. You can think of it also as being a partial function. So, let's actually get down to it and write some F# code to show how to do this:
#light
let n = 10
let multiply a b = a * b
let multiplyByFive = multiply 5
let result = multiplyByFive 4
printfn "result = %i" result
So, what I accomplished above is that I had a function called multiply that takes two arguments, a and b. Then I created a currying function called multiplyByFive which curries the multiply function by supplying a five value. Then I can call the multiplyByFive curried function with a 4 and sure enough the result is 20.
As always, I'm always curious on how it looks through .NET Reflector to see how F# does its magic. So, let's crack that open and take a look. First let's look at the tree of Reflector to see what it creates for us:
Now as you can see, it created the multiply function. Then we also have a multiplyByFive FastFunc function. The functions get stored in the namespace free area and yet the main function gets placed elsewhere. Now, let's look at the function implementation itself.
From what you can see, it created a SampleFile class because I created a SampleFile.fs to create the curried functions.
For those of you who are C# buffs, well, you can also do the same in C# with the new anonymous function type, System.Func in .NET 3.5. Mads Torgersen, the C# Program Manager, noted on his blog quite a while ago asking the question, "Is C# Becoming a Functional Language?". This post was pretty great and it's unfortunate that he doesn't blog as much as he does. Remember kids, this isn't as pretty as F# because it's not what C# is really good at, but slowly but surely, functional programming paradigms are slowly seeping into C#.
namespace CSharpCurriedFunctions
{
public static class CurriedFunctionExtensions
{
public static Func<A, Func<B, R>> Curry<A, B, R>(this Func<A, B, R> f)
{
return a => b => f(a, b);
}
}
class Program
{
static void Main(string[] args)
{
Func<int, int, int> multiply = (a, b)=> a* b;
Func<int, Func<int, int>> curriedMultiply = multiply.Curry();
Func<int, int> multiplyByFive = curriedMultiply(5);
Console.WriteLine("result = {0}", multiplyByFive(4));
}
}
}
If you're interested more in doing this with C#, I would suggest you head over to Dustin Campbell's blog and read the post about The Art of Currying. For those who want to learn more, well, Dustin should be at ALT.NET Open Spaces, Seattle and hopefully will submit an F# topic for us to get our heads around.
How useful is this in C#? Well, time will tell, but you could imagine having some search criteria for your repository using curried functions to "overload" with values. Anything is really possible, but as you can see, it's a lot cleaner in F# and that's where it really shines.
The Odd Tuple
When specifying arguments to any given function, you can specify them without parentheses much as you would in VB.NET should it be a subroutine. This is really helpful if you want to enable currying and such. But, you can also specify them as a tuple. For the math illiterate among you, that simply means a sequence of objects of a specified type. This you must put within parentheses. This makes you supply all arguments at once. A simple example of this would look like this:
#light
let add (a, b) = a + b
let result = add(3, 4)
printfn "result = %i" result
Pretty simple example and of course the result would be 7.
Where is the Returns Department?
As you may have noticed from the functions from above, I never really did specify any return type or return statement. Implicitly behind the scenes, F# does that for you. Basically when you define a function, you should indent with a tab and the last assignment becomes your return value. The return is implicit right after the indenting is ended. So, let's take a simplistic view of this:
#light
let addThings a b =
let c = a + b
sprintf "result = %i" c
let result = addThings 3 7
print_string result
As you may notice, when using the light syntax (#light), you cannot indent, instead just use two spaces and that should suffice. Anyhow, you may note, I was doing a simple addition and then my final assignment becomes my return value, which is using the sprintf function, which to you C buffs out there, should look familiar.
Scoping it Out
Scoping of variables is a common thing inside any programming language and really no different in F# at all. Remember that identifiers can be either values or functions themselves. The only thing to me that is interesting about F# is that you can redefine your identifiers. By default, your identifiers are immutable unless otherwise specified in functional programming languages. So, we're not going to change the value, but instead redefine. And what's more interesting, is that you can change the type on the fly as well with the redefine, so be careful!
#light
let message =
let temp = "Foo"
let temp = 1
let temp = "Bar"
temp
So, this one works and quite simply just by redefining what temp is. If we pop open Reflector, here's what it boils down to in C#:
public static void _main()
{
message@3 = "Bar";
}
As you can see from there, it refactored that code out that we didn't need at all. It was a pretty stupid example, but interesting nonetheless.
Recursion, Recursion, Recursion
Recursion is one of those computer science lessons that everyone should have learned back in their early CS days. This was taught in line with pointers, reference, hex/octal math, linked lists and so on. I certainly hope they still teach that stuff nowadays with Java and .NET now the mainstays in universities. Anyhow, if you didn't have that luxury, it's basically where you have a function that calls itself in order to return an answer. Some of the classic examples of this are computing factorials, Fibonacci sequences and so on. Of course recursive functions can have their downsides including blowing out the call stack if the recursion gets too deep or gets into an infinite loop, so it's always a good thing to test for these sorts of things.
F# treats recursive functions just a bit differently than regular functions. In fact, in order to make a function act recursive, you must mark it as such using the rec keyword. This allows you to call that function within that function, else it will give a syntax error. So, let's step through a few examples.
Let's start out with the classic Fibonacci sequence. To do this in traditional imperative programming, it looks something like this in C# 2.0:
static int Fib(int i)
{
if (i <= 1)
return 1;
return Fib(i - 1) + Fib(i - 2);
}
Ok, so that's old school to me. Instead, since I mentioned that C# is going more towards a functional programming style, let's go ahead and do that again using anonymous functions (System.Func) instead.
Func<int, int> fib = null;
fib = i => i > 1 ? fib(i - 1) + fib(i - 2) : 1;
Ah, much cleaner. But, let's take this to F# and use pattern matching instead of just the normal if/else control structure, just to be on the wild side.
#light
let rec fib n =
match n with
| 0 -> 1
| 1 -> 1
| n -> fib(n-2) + fib(n - 1)
let fib10 = fib 10
printfn "10th Fibonacci 10 %i" fib10
Ok, so let's throw a few more logs onto the fire with a couple more, one with recursing all files in a given directory (yes, I know you can do it with Directory.GetFiles, but this is more fun), and computing a factorial.
#light
open System.IO
let rec recurseDirectories x =
let fileList = new ResizeArray<string>()
fileList.AddRange(Directory.GetFiles(x))
let subDirs = Directory.GetDirectories(x)
subDirs |> Seq.iter(fun x -> fileList.AddRange(recurseDirectories x))
fileList
let directories = recurseDirectories @"E:\Work"
directories.ForEach(fun x -> printfn "%s" x)
let rec fac n =
match n with
| 0 -> 1
| n -> n * fac (n - 1)
let fac10 = fac 10
printfn "Factorial of 10 %i" fac10
In the recurseDirectories function, I was being a little tricky and using a mutable structure. The ResizeArray<T> is actually just a rename of the List<T> generic from the regular CLR. As you can note, I'm not using any control functions for doing so such as foreach loops, etc. Instead, I'm using the Seq collection inside of F# proper and I'm sure I'll get to that later. And yes, there are probably more ways of doing these, but these are pretty good nonetheless.
Staying Anonymous
As you saw from above, I used the keyword fun. What that is, is using an anonymous function. This is much like in C# using the System.Func structure but with different underlying base classes underneath. Some simple examples of creating anonymous functions are just that, for iterating over a block like above. We also can do something else like doing some simple examples such as below:
#light
let a = (fun b c -> b * c) 12 13
printfn "%i" a
We can also use tuples with this as well. This means that you must specify all parameters up front. You can only do pattern matching when using this style. If you need to supply multiple arguments to this, go ahead and use Currying, which we talked about last time. Below is a simple example of the above code:
#light
let a = (function (b, c) -> b * c) (12, 13)
let z = (function y -> function x -> y * x) 12 13
printfn "%i" z
printfn "%i" a
And this even can apply when using .NET classes such as the ResizeArray<T> such as this quick example:
#light
let stringList =
let temp = new ResizeArray<string>();
temp.AddRange([|"Hello"; " "; "Cleveland"|])
temp
stringList.ForEach(fun x -> print_string x)
A Little History Lesson
As you may know, functional programming itself is one of the older programming paradigms that dates back to the 1950s. In fact, as with most things, it can be traced back to Lisp in the late 1950s. Like I've said before, most good things in programming nowadays can trace their history to Lisp, or Smalltalk.
Anyhow, back in 2002, Don Syme and a team at Microsoft Research wanted an Metalanguage (ML) approach to language design on the .NET platform. While this project was going on, Don was also working on implementing generics in the .NET platform as well. These two projects worked there way into becoming F# which made its first appearance in 2005.
As you may note from looking at the F# libraries such as FSharp.Compatibility.dll and the namespace Microsoft.FSharp.Compatibility.OCaml, it shares a common base with Objective Caml (OCaml). OCaml itself, another language in the ML family and been around since 1996. It also borrowed for Haskell as well in regards to sequences and workflows. But, in the end, as you may know, F# splits from those languages quite a bit because it allows for imperative and object oriented programming. That's the really interesting piece of this puzzle is to be able to interoperate with other .NET languages as if they were first class citizens.
One thing that I found particularly interesting about F# is that it is very portable, unlike other .NET languages. What I mean by that is that they provide you with the source so that you could use this with Mono, Shared Source CLI or any other ECMA 335 implementation. I've been able to fire up a Linux box with Mono and sure enough it compiles and runs without fail. Now onto the technical details...
Operators
Operators are an interesting and compelling feature in F#. Most modern languages support this feature except for say Java to overload operators. I think it's a compelling feature in the way of dealing with DSLs and such. But anyways, F# supports two types of operators, the prefix and infix types. The prefix operator type is an operator that takes one operand. In order to be prefix, it means that it precedes its operand such as (-x). The infix operator type takes two or more arguments. An example of this kind of operator is (x + y).
There are many operators in the F# libraries quite frankly and I'll list just a few of them:
Arithmetic Operators
Operator
Meaning
+
Unchecked addition
-
Unchecked subtraction
*
Unchecked multiplication
/
Division
%
Modulus
-
Unary Negation
Bitwise Operators
Operator
Meaning
&&&
Bitwise and
|||
Bitwise or
^^^
Bitwise Exclusive Or
~~~
Bitwise Negation
<<<
Left shift
>>>
Right shift
Assignment and Others
Operator
Meaning
<-
Property Assignment
->
Lambda Operator
::
List Concatenation (cons)
|>
Forward Operator
[[ ]
Index Operator
:?
Pattern Match .NET Type
And many many more. It's a massive array of built-in operators...
Back to the subject at hand. As in C# and other .NET languages, the operators are overloaded. But unlike C# for example, both operands for the operator must be of the same type. But unlike C#, F# will allow you to not only define, but redefine operators as well. Below I'll show an example of using the common concat operator with strings and then redefine the division operator to do something really stupid and do multiplication instead. Aren't I crafty?
#light
let fooBar = "Foo" + "Bar"
print_string fooBar
let (/) a b = a * b
printfn "%i" (4 / 2)
So, as you can see it's rather powerful what we can do with existing operators. But, with F#, we can also define our own operators we wish to use. In fact we can use any of the below as our new operator.
! $ % & * / + - . < = > ? @ ^ | ~ as well as a :
As I did above, it should be no different for us to create our new operator. Let's walk through a simple operator that does raise to the power of two of the first operand and add the second.
#light
let ( *:/ ) a b = (a * a) + b
printfn "%i" (45 *:/ 42)
If you're curious like me what that actually looks like, let's look through .NET Reflector and see what it creates for us. I'll just copy and paste the results here:
public static int op_MultiplyColonDivide(int a, int b)
{
return ((a * a) + b);
}
But we can also define operators for our custom types as well. Let's go ahead and define a simple type called Point and then define the addition and subtraction operators. This syntax should look rather familiar and to me, it looks a little Ruby-esque.
#light
type Point(dx:float, dy:float) =
member x.DX = dx
member x.DY = dy
static member (+) (p1:Point, p2:Point) =
Point(p1.DX + p2.DX, p1.DY + p2.DY)
static member (-)(p1:Point, p2:Point) =
Point(p1.DX - p2.DX, p1.DY - p2.DY)
override x.ToString() =
sprintf "DX=%f, DY=%f" x.DX x.DY
let p1 = new Point(5.0, 6.0)
let p2 = new Point(7.0, 8.0)
let p3 = p2 - p1
let p4 = p2 + p1
printfn "p3 = %s" (p3.ToString())
printfn "p4 = %s" (p4.ToString())
Lists
Lists are one of the most fundamental pieces that is built right into the F# language itself. The language itself around the use of lists is a bit verbose, but I'll cover the basics through the use of code. Lists in F# are immutable, meaning that once they are created, they cannot be altered. Think of them like a .NET System.Array in a way, but a little bit more powerful. Do not get them confused though with F# Arrays which are entirely different and will be talked about later. Let's show the basics here below about lists:
#light
let empty = [] (* Empty List *)
let oneItemInList = 1 :: [] (* One Item *)
let twoItemsInList = 1 :: 2 :: [] (* Two Items *)
List.iter(fun x -> printfn "%i" x) twoItemsInList (* Iterate Over List *)
let threeItems = [1 ; 2 ; 3] (* Shorthand notation *)
let listOfList = [[1 ; 2 ; 3]; [4 ; 5; 6]; [7 ; 8 ; 9]]
List.iter(fun x -> print_any x) listOfList (* Iterate over list of list *)
As you can see from the example above there are a couple ways of declaring lists, including the verbose way which includes the empty list, or the classic style of putting inside of square brackets. What's more interesting is to have lists of lists as well.
Another interesting aspect of F# lists is List Comprehensions. Using this syntax, we can specify ranges to use in our lists. If you specify a double period (..) in your list, it fills in the rest of the values. I have three samples below which includes 0 to 100, lower-case a to z and upper-case A to Z.
You can also specify steps in the numbers as well which is much like a for loop with a step in there. Note that characters do not support the stepping capability. To use the stepping capability, the format is (lower bound, step value, upper bound). Below I have a sample which pulls all even numbers from 100 to 0 and stepping -2 each time.
For loops can also be used in which you can transform each item along the way. To use this one, use this for keyword and the lower end to upper end and then the lambda to modify the value. Below I have an example where I double each number from 1 to 20.
Another example of a for loop is to create a loop in which you specify a when guard. You can then only print out values that match your criteria. The example I have below is to print all odd numbers using the formula when x % 2 <> 0.
#light
let zeroToOneHundred = [0 .. 100] (* 0 to 100 *)
let lowerCaseAToZ = ['a' .. 'z'] (* Lower-case a-z *)
let upperCaseAToZ = ['A' .. 'Z'] (* Upper-case a-z *)
let evensFromOneHundred = [100 .. -2 .. 0] (* 100 to 0 skipping every 2 *)
let doubledValues =
{ for x in 1 .. 20 -> x + x } (* Double each value from 1 to 20 *)
let odds n =
{ for x in 1 .. n when x % 2 <> 0 -> x } (* Print all odd numbers *)
print_any (odds 20)
And I've only just begun to touch the basics of lists. Dustin Campell also covered lists recently on his Why I Love F# Series.
Conclusion
We still have plenty to go before I'd say we were done with a 101 level exercise with F#. We still have yet to cover pattern matching, lazy evaluation, exception management and even using F# with imperative and object oriented code. So, subscribe and stick around. Until next time...
Original Source: podwysocki
BlogSpot Tags: Adventures,links,Spec,Robert,Foundations,Syme,Expert,overview,language,world,Hello,Sample,Values,basics,Example,Reflector,framework,Project,classes,Source,File,extension,HelloWorld,text,examples,differences,topics,languages
No comments:
Post a Comment