F# for fun...
So I'm learning F# in my spare time... I don't have much of that however.. so I kinda squeeze it in where I can, so I'm not progressing as fast I would like... None the less it's quite an easy language to get up to speed with, even as I stab at it blindly for half an hour a week... but some fundamentals can really trip you up when you're starting to learn and experiment without having developed a good mental model of whats going on... being a wannabe "expert" in the .Net framework and BCL doesn't necessarily give you much of edge when your moving from an imperative to functional programming language.
To that end this post is going to cover some really trivial observations, so for anyone that actually knows F# it's probably going to be pretty boring... and you might as well read something else ;o)
Anyway.. so, first off lets take evaluation order.
In C# I might write some code like so...
char[] characters = new char[] { 'A','B','C','D','E'} foreach (char c in characters) Console.WriteLine("character: " + c);
Now in F# I could write something similar...
let characters = [| 'A'..'E' |] for c in characters do print_endline "character: " + c.ToString()
But it wont compile... because it's evaluated/applied from left to right, so it equates to (print_endline "character:") + c.ToString() ... which can't compile because print_endline returns a result of type 'unit' (think void... though it is actually a return value)... thankfully it's a compiled language so these things are picked up immediately - but it can make for silly/confusing compilation errors when starting out.
Now, moving on from there.. past experience has also helped screw up my mental model... for example iteration related functions - if I was going to write an iteration function in C# the approach would generally be to do something like this:
public void ForEach(IEnumerable items, Action action) { foreach (T item in items) action(item); } string[] words = new string[] { "somewhere", "on", "earth", "little", "kids", "teach", "themselves", "a", "whistling", "sound", "to", "imitate", "bombs", "dropping" }; ForEach(words, delegate(string s) { Console.Write(s + " "); });
I had the expectation of finding replicas in the F# built-in functions like List.iter etc. - in fact I even wrote code like this to start with, assuming it would work in the same manor.
List.iter words (fun word -> print_string (word + " "))
After that didn't compile I just swapped the parameters... it worked... but I saw some unusual behavior when stepping through it with the debugger... and it required further inspection... looking at the signature for List.iter revealed that it was actually a function that returned a function ... ('a->unit) -> (list 'a -> unit)... hmmm..
So it turns out most of the built-in functions take a single function and return a function... so unlike the C# equivalent, the F# foreach would look something like the code below (though I suspect an F# guru might be able to write it in a more terse manor).
let words = [ "somewhere"; "on"; "earth"; "little"; "kids"; "teach"; "themselves"; "a"; "whistling"; "sound"; "to"; "imitate"; "bombs"; "dropping" ] let foreach f = let rec foreachInList l = match l with | head :: tail -> f head foreachInList tail | _ -> () foreachInList let n = foreach (fun word -> print_string (word + " ")) n words // or words |> foreach (fun word -> print_string (word + " ")) // or foreach (fun word -> print_string (word + " ")) words
It took me a minute or so of going hmmmm to absorb the beauty of that approach... obviously this is bread and butter of a functional programmer, but for a non-functional programmer like myself you tend to just see twice as much "work" going on (two function calls for starters).
Take a look at the second way of calling foreach... in this case |> applies the RHS as a filter on the LHS... because the function takes a single parameter we can do this easily.. but we can also chain them together... so we could alter our foreach function a smidgen:
let foreach f = let rec foreachOnList l = match l with | head :: tail -> f head head :: (foreachOnList tail) | _ -> [] foreachOnList
So it's signature is no longer ('a->unit) -> (list 'a -> unit) but is instead ('a->unit) -> ('a list -> 'a list) ... now I can chain calls to my foreach together...
words |> foreach (fun word -> print_string (word + " ")) |> foreach (fun wor -> print_string (word.ToUpper() + "_"))
I really enjoy the elegance and simplicity of the filter syntax... if you replace the anonymous functions with functions you've already declared it suddenly becomes pretty, I think it reads nicer then chained extension method calls / fluent interfaces in C#.
let capitalize (c: string) = c.ToUpper() let pad c = c + " " words |> List.iter (fun word -> word |> capitalize |> pad |> print_string)
At any rate, my half hour of F# exploration is up for the week.