It compares and contrasts C# and equivalent F# code for relatively simple, but common-in-the-real-world examples, while introducing some functional constructs. I'd also recommending reading the "Thinking Functionally" series.
After that I'd recommend skimming some of the topics on the F# wikibook:
It's the product of a little over 20 hours of development across two people new to the language (and thus has some warts...), so take it as a grain of sand. Uses MS Unit Testing framework for F# (available via NuGet).
F# will almost definitively help any C# code. Even if you use F# as a "better C#" you'll see improvements. Just removing excessive type annotations is a nice step up in clarity.
F#'s benefit will come as a bunch of tiny improvements, "programming in the small" as they call it. For instance:
let xs = [ while r.Read() do yield r.GetInt 0 ]
In C#, it's:
var xs = new List<int>();
while (r.Read()) { xs.Add(r.GetInt(0)); }
Or:
let f x =
let x = try int s with _ -> -1
x * 3
In C#, it's uglier. First because try... isn't an expression. Second, because you cannot shadow variables by rebinding them, so you always have to keep "old" vars around and in scope, and cannot reuse handy variable names:
SomeType x;
using(var db = new DB()) {
x = db.GetX()
}
Which is more annoying than it might seem. How much nicer is it to be able to create a new scope at any point in a function, and return a value out of it cleanly?
These are by no means a complete or even important showcase of C#'s lacking. Just a few quick thoughts off the top of my head. In general, every time I'm writing C# code, I keep realising how things would be much more concise if I was in F#.
None of them are killer features. Nor is pattern matching, assorted comprehensions, array slicing, binary literals, bytestrings, tuples, active patterns, records, type inference, immutability, shadowing, nested functions, custom operators, typechecked printf, type providers, workflows[1], sum types, agents, etc. etc.
But it sure all adds up.
Switching for a codebase might not be a wise move for many reasons. But writing new code doesn't have those excuses.
Actually workflows are the closest to a "killer" feature but C# took the most popular, async, and hard-coded it in.
All those words surely do sound impressive when you list them all together just like that. But you can remove at least pattern matching and records, as they are coming to C#. At least some of them is a matter of taste (e.g. nested functions , global inference and custom operators - the latter two can reduce readability IMHO) etc. For me however the killer feature of C# is ReSharper and other tooling. There is no point to argue, F# is a great language, but C# is a great one as well, no need to write code samples to misuse the language and make it look bad. I considered using F# for physics computations (to leverage the units of measure) but unfortunately it provides no solution for marking external types with them (which means I cannot integrate it with e.g. MonoGame). I still have a hope for finding a good use case for F#.
Pattern matching in C# would be a rather big departure and change. And then to match F#'s level of deconstruction, that'd be neat. C# can become F# if it wants, they just have to add in features. They've been hesitant to do so based on limitations of the compiler codebase, as well as fears that C# might get too difficult for mediocre programmers.
I'm not sure how new List<string> { "a", "b" } is more readable than new List<_> {"a", "b"), but hey, sure, if you want to argue type inference is bad, go for it. F# also lacks loop constructs like break/continue.
I don't feel I've misrepresented C# at all to make it look bad. I've written a lot of C# code and a fair amount of F# code. Line by line, char-by-char, expression-by-expression, F# is simply much less code. Those examples are just things off the top of my head, from real codebases.
C#'s alright, because the competition (like Java) is laughable. So in that sense, it's "great". In absolute terms, it doesn't measure up (and this isn't a secret, bit-by-bit C# adopts features F# proved out.)
Units-of-measurements are implemented via erasure, yes. How would you represent float<m> externally to make it available to common types, but without losing performance? The compiler consuming them would need to be aware of it. And at runtime, you certainly don't want extra overhead, and I don't think the CLR has any efficient way of exposing primitives with additional type info. It's an unfortunate tradeoff.
I've got a safaribooks online account, and found "Real World Functional Programming with examples in F# and C#" the most useful of the f# books I've read. The author has a blog, http://tomasp.net/ But I got something out of all of the books.
http://fsharpforfunandprofit.com/series/why-use-fsharp.html
It compares and contrasts C# and equivalent F# code for relatively simple, but common-in-the-real-world examples, while introducing some functional constructs. I'd also recommending reading the "Thinking Functionally" series.
After that I'd recommend skimming some of the topics on the F# wikibook:
http://en.wikibooks.org/wiki/F_Sharp_Programming
And then I'd begin with rewriting some components in your existing project while continuing reading through that book and other online resources.
Me and a coworker also rewrote ~600 line C# module into a working module in F#, along with some interop POC here: https://github.com/cartermp/CSharpToFSharp
It's the product of a little over 20 hours of development across two people new to the language (and thus has some warts...), so take it as a grain of sand. Uses MS Unit Testing framework for F# (available via NuGet).