.NET Fiddle adds F#
dotnetfiddle.net
dotnetfiddle.net
One place some predict it will emerge is in the Web API arena, and I could totally see that happening.
That edge dulled quite a bit with C# 5.0 and async/await, though.
The lightweight syntax, easy handling of functional features, nesting of code - it ends up leaving you with far less code that has less bugs by default. MS describes F# as excelling at "programming in the small" - the line-by-line, char-by-char code is simply far superior to using C#. Just type inference alone is huge - C# is embarrassingly bad at type inference, and it's partially due to the complexity in their codebase in implementing it properly. At the moment, MS seems to have sort of backed off on enhancing C#.
There's so many tiny things in F# that just make the code easier and less bug prone. For instance, being able to nest code. Suppose I want to read an integer out of a querystring, and on failure provide a default. Idiomatically, in C#:
int age;
if (!int.TryParse(qs["age"], out age)) age = -1;
In F#: let age = try int qs.["age"] with _ -> -1
Or lets say I have some intermediate variables. In C#: int age;
var parts = String.Split(bla, ",");
if (parts.Length == 0) age = -1;
else age = int.Parse(parts[0]);
I've introduced a useless local var, parts, for no reason other than needing it in computing age. In F# (and avoiding pattern matching just to demonstrate): let age =
let parts = String.Split(bla, ",")
if parts.Length = 0 then -1 else int parts.[0]
The intermediate binding, is not available outside it's scope. That's far cleaner, and quite commonly useful.Top level functions are handy. Being able to make useful lambdas without specifying the types is super useful. Many of my functions have a nested helper function which makes things cleaner. Places where I don't want to add a full utility function, but I don't want to repeat code. You can do it in C#, but it's ugly. In F# it's natural.
Array/list comprehensions. In C#:
var res = new List<int>();
using(var reader = cmd.ExecuteReader()) {
while(reader.Read()){
res.Add(reader.GetInt32(0));
}
}
In F#: use reader = cmd.ExecuteReader()
let res = [ while reader.Read() do yield reader.GetInt32(0) ]
Pattern matching is well covered, and F# Active Patterns are just awesome, because you can customize your own destructuring for arbitrary objects. The list just goes on and on, lots of things in F# that are just so right, so easy, so trivial. Custom operators, tuple handling.I'm not even touching on the larger things, like Type Providers, records, sum types, or the fact that F# has monad syntax that's flexible, instead of C# building specific monads into the language. Heck, the F# compiler is far more advanced and produces faster code in many cases. And the fact that you can manually make it inline code is also a nice perf win you simply cannot get with C#.
I recently started working on a project that uses C#, and it's just such a pain. Death by a thousand cuts. There's no reason to use C# over F#. Even if you only use F# as a light-syntax-C#, you're better off.
The only real objection is hiring, in an enterprise scenario. For any serious project where the code is the product (versus the code being an artifact of just solving a business problem), I don't believe you can hire any good programmer that cannot deal with F#. (I think that hold for most languages, in general.) Unfortunately, people don't seem to believe that, and somehow think they're going to hire really smart people, but these people aren't going to be able to learn a different language.
I assume you are talking about enhancing C# itself, because Roslyn is the next big thing for C# (and VB.Net) with a compiler compiler rewrite that will allow anyone to build language services.
The C# compiler code base is old now. It was done in C++ and apparently has become very hard to maintain. The C# team has been working on Roslyn, a complete rewrite of the compiler in C#, to make adding new features to the language more easily. It will also allow improvements to tooling (anyone can use the same compiler service rather than create their own) and should certainly facilitate meta-programming, construction of DSLs, etc.
I agree with you about F# though. It's so much to-the-point than C#, which is already a big improvement on java and C++ in the terseness area.
I love C# but I wish I was at least as proficient in F#, I know I could be a lot more productive with a language that requires less 'ceremony'.
Maybe this magical Roslyn rewrite is going to enable all sorts of amazing things, and then C# will rapidly catch up. But from the outside, it feels like C#'s good enough (hey, it's better than Java), and MS is content to keep it that way.
Having said that, I already hear people complaining about the pace of new .Net frameworks and language features being too fast. I think that the community seems to be split on whether to add new language features or not
Like the union types, but not so much the list operations; seems more natural to:
[1;2;3;4] filter isEven sum
vs.
List.filter isEven [1;2;3;4] |> List.sum
in Scala it's: List(1,2,3,4) filter isEven sum
Of course I'm not familiar with F# so don't know all of the WIN within (Type Providers, for example, are very impressive, would love to see that on the Scala side of the fence one day).
[1; 2; 3; 4] |> List.filter isEven |> List.sum
That way you maintain the same operator order as you do in Scala, while maintaining some consistency with currying.
In addition, you can add other functions really simply while still maintaining the order.
[1; 2; 3; 4] |> List.filter isEven |> List.sum |> printfn "%i"
list filter isEven foreach println
Which is, IMO, quite elegant, but then again I'm used to Scala and not yet at all familiar with F# and the reasoning behind the syntax.
List(1,2,3,4) filter isEven sum println
error: type mismatch;
found : Unit
required: Numeric[?]
List(1,2,3,4) filter isEven sum println
^foreach takes a collection and applies some function (in this case println).
I've actually had a use case for what you're trying do, so created an extension method on Any, which means you can then do, on Any-thing:
(list filter isEven sum).echo
I also hate typing "println". "echo" I can bang out instantly, and can do so on any expression, before or after its definition.
list filter isEven foreach println
As a side note omitting that many commas and parenthesis is very rare at least based on the Scala projects I've worked on. The above example is equal to the one below: list.filter(isEven).foreach(println)If you wanted to be really explicit you could do:
list.filter(x=> isEven(x)).foreach(x=> println(x))
yuck ;-)Using |> is a win for two reasons - code flows more naturally, and the type inferencing works better. e.g. List.Map (fun d -> d.Hour) [DateTime.Now] does not compile, but [DateTime.Now] |> List.map (fun d -> d.Hour) does.
[1; 2; 3] |> List.filter (fun a -> a < 3) |> List.sum is the same as List.sum (List.filter (fun a -> a < 3) [1; 2; 3])
arg |> func is the same as func (arg)
Just getting started with Haskell and am having several, shall we say, WTF moments.
So in
List(1,2,3,4) filter isEven sum
it looks like filter and sum are instance methods on the List class, and I'm guessing isEven is a predicate that's being passed as an argument to the filter method.F# leans closer to its functional roots in this respect, so it's more idiomatic to keep object-oriented constructs at arm's reach in most your code. The language has full support for OOP, it's just that you're not expected to trot it out except when you're writing public interfaces that are meant to be consumed by code that might be written in C# or VB.NET. So the List class mostly sticks to static methods in its public interface because that approach fits better with traditional functional idioms.
That gets you as far as something like this:
List.sum (List.filter isEven [1;2;3;4])
The next step is the "pipeline" operator, which is defined as let inline (|>) x f = f x
So it's just letting you swap a function and its argument, which facilitates reorganizing the code so that the functions are listed in the order in which they execute. That's what gets you to the example you give - or better yet: [1;2;3;4]
|> List.filter isEven
|> List.sum
which I think captures some of the natural expression that you were talking about while still sticking with functional idioms instead of object-oriented ones.And also fits perfectly with the C# and VB.NET extension method syntactic sugar, which was used extensively for LINQ. They're really just static methods in the .NET VM and bytecode.
Just interested, what's the real value here? "Familiarity" alone seems to be a pretty poor reason.
> They're really just static methods in the .NET VM and bytecode.
Doesn't this mean that either your methods won't be dynamically dispatched or that you would need to rewrite your code if you ever change from e. g. List to Array?
Looks like a bad compromise to me.
The current API situation looks kind of weird. What's the point of having an API (like the collection one) which is meant to be chained together, but needs additional boilerplate (|>) to actually work that way?
Maybe it would have been better to do away with these inconsistencies and make the idiomatic way of writing code the default one, working without any additional effort of flipping stuff around?
I suppose the answer to that question ultimately depends on one's preferences. I like F#'s way of doing things because I like functional programming and idioms, but I also like being able to play nice with a rich pre-existing ecosystem, and don't want to have to do it through a (probably) leaky abstraction.
When I instead want a primarily object-oriented language with some extra support for functional programming slapped on top, I just use C#.
That would probably be more consistent than the current 80%OCaml + 50%C# => F# mess.
The MSIL (.NET bytecode) for calling an extension method and a static method are exactly the same. So yes, it will not be dynamically dispatched. Specifically, it emits a "call" and not a "callvirt" instruction.
However, the compiler will always prefer a class method over an extension method of the same signature. Meaning that extension methods can be specifically implemented by a class and the compiler will emit a "callvirt" instruction for that instance method instead.
> ... or that you would need to rewrite your code if you ever change from e. g. List to Array?
I'm not sure what you mean here. Arrays implement IList, so if you need random access, you would just write a method against IList. If you don't need random access, you should write it against IEnumerable, which all collections implement.
Wouldn't it have been better to keep such things out of the language instead of having a considerable amount of complexity in the language for stuff people are not even supposed to be doing in the first place?
Yes, I think that's a good description. It's not great, but it somehow works (although the whole F# community tends to tell people to stay away from OOP when not necessary).
Would have been interesting to explore better ways to support OOP so that it doesn't need to be considered a second class citizen, but I guess it's too late for that now.
What's the value of having a runtime with a language-independent intermediate representation if one just adds half of C#'s complexity into F#?
A: One's object-oriented jargon, the other's functional jargon. They both mean pretty much the same thing.
First you can translate it literally, where F# looks like a slightly more verbose version of Python. Second you can exploit all the functional features of F#, and using immutable variables, recursion and pattern matching.
F# also has extensive support for OOP, and uses it where OCaml-ers might use modules or functors.
In that way, F# can be a sort-of stepping stone between the imperative, OOP C# to more functional features of F#.
At first you write imperative F# to get used to the language and it's lack of verbose signs such as (, ; etc and hopefully you will be able to write more idiomatic/functional F# as your skill improves.
Having seen F# written by C# coders who've just learnt the syntax, and haskell programmers who are having to work in a .net environment, I'd say F# does a fairly good job of supporting both. It does make some trade offs to allow easy interop with the rest of the .net world (it's type system is much less powerful than Haskell, Scala or (especially) Idris) but depending on your environment that can be out weighed by the massive scale of the .net ecosystem, easy interop with your existing .net code and very, very good tooling.
And impure, of course. It's definitely an impure language. Personally, though, I'm not at all fond of conflating the terms "pure" and "functional". It's a terrible retcon that has more to do with the Haskell proselytism than with the development and history of functional programming or how its community has self-identified over the years. Note that the seminal book's title is "Purely Functional Data Structures", not something that's only three words long.
git clone git://github.com/mono/mono.git
cd mono
autogen.sh
sudo make install clean
cd ..
git clone git://github.com/fsharp/fsharp.git
cd fsharp
autogen.sh
sudo make install clean
It takes a while to build Mono from scratch, but this way has always worked for me.When I ran F# on Ubuntu before, it was on the x86 version of 12.04 LTS. I used whatever the latest version of Mono was; I don't remember specifically, but it was almost certainly one of the 3.2.x versions.
Would you mind posting the build output from your F# build that fails (e.g., to pastebin or Gist)? I can forward it along to the right people so it gets fixed. Or, post it as a Github issue: https://github.com/fsharp/fsharp/issues
Sorry for interruption. Lesson learned.