Outside of web development any ideas what I could use it for (I am on Linux so it should run on Mono)? I've done quite a lot of web development on the JVM with Clojure, Scala and Java and would like to try to do something totally different with F#.
In my own tests, F# will require about 1/20th of the type annotations of C#. It offers a near superset of functionality, so you don't lose anything (except a bit on the tooling side of things).
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.
>At the moment, MS seems to have sort of backed off on enhancing C#
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'.
Right, I'm referring to the fact that C# 3 added LINQ, but with the bare minimum of features for LINQ. Type inference, for example, is purely for anonymous types and the LINQ extension methods. They never went back to clean those up since V3, and it doesn't seem like they care.
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.
In another thread somewhere, it was said that with Roslyn they are holding off on adding new language features as every item they add is another step from completing Roslyn. Once it's out the door, there will be another flurry of features added.
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
F# is very un-functional in many ways. Immutable variables are the default but mutable variables are made with just the "mutable" keyword. There are also lots of imperative control structures, like while, and for. Those two combined means that imperative algorithims typically have two distinct translations into F#.
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#.
Un-functional might be a bit misleading for an ML-based, default immutable language. Impure might be slightly more accurate.
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.
Yeah, perhaps unfunctional wasn't the best word I could use. Either way, I'm a huge fan of F# and I think it's imperativeness is all-in-all a very good thing for adoption of the language.
The OOP and imperative capabilities also make it easier for people coming from this kind of programming style to learn F#, such as myself.
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.
I'm not sure I'd say un-functional, just multiparadigm. But having at least some support for imperative programming is the norm in functional languages - ML does it, most LISP dialects do it, etc. Even Scheme, originally notable for its lack of loops, still has set! and idioms for combining it with closures and tail recursion to produce constructs that behave like loops.
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.
I haven't used F# much but my impression is that it came from an OCaml background and thus perhaps sits halfway between C# and OCaml. Many of the useful type system features of Haskell are missing, but the module system of OCaml has been developed to be closer to the object system of C#.
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).
I've got little experience with Scala, but judging from your sample it looks like what's happening is that Scala follows more Java-y idioms for how code is structured.
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.
> So the List class mostly sticks to static methods in its public interface because that approach fits better with traditional functional idioms.
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.
> that approach fits better with traditional functional idioms
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?
> Doesn't this mean that either your methods won't be dynamically dispatched...
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.
Perhaps what the parent is saying is that if you implement an extension method to IList, you can't subsequently implement an extension method to Array and expect it to be called on an Array stored in an IList variable? Which is true for exactly the reason you state.
One of the big values is currying. Instance methods don't always interact well with partial application and design patterns that rely on it, because with instance methods one of the function's (logical) operands is a special snowflake that isn't curried.
But currying isn't even consistently supported, e. g. when calling C# APIs as far as I remember. Wouldn't it have been better to explore a way which either works for all code or, if that doesn't work out, just embrace instance methods?
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?
> Wouldn't it have been better to explore a way which either works for all code or, if that doesn't work out, just embrace instance methods?
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#.
It seems to be kind of insane having to choose between a "better functional" and a "better OOP" language.
Why not just combine the good parts into a single language.
That would probably be more consistent than the current 80%OCaml + 50%C# => F# mess.
> 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.
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?
Well, if the language was only meant to be an API consumer then eliding OO stuff would make more sense, but they designed it for bi-directional interop. And besides, F# was based on OCaml (as I'm sure you know), which itself was an existence proof that you could successfully bolt OO onto a functional language.
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.
There's an enormous difference. And it's a good thing F#'s designers chose the latter option; it's a huge win on the interoperability front. Libraries have a tendency to be write-once-use-often, so exporting object-oriented APIs from F# code is way better than consuming functional APIs from C# code.
I think there is a huge way between allowing developers consume F# code from C# and importing all the ugliness of stuff like static members into the language. I don't think it has to be that way.
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#?
`sum` does not accept a function as a parameter, the original example had an `foreach` instead of `sum`.
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:
That example is not quite equivalent, because now you are not passing `isEven` or `println` as arguments, you are passing anonymous functions that call `isEven` and `println`.
I guess it's all a matter of what you're used to, because coming from ML-family languages like F# and Haskell, the first thing you wrote doesn't really make any sense to me. In the ML family like F# is, you put the function (e.g. "filter isEven") before the argument ([1;2;3;4]).
The most common way to format code like that in F# would be something like
let evenSum =
[1;2;3;4]
|> List.filter isEven
|> List.Sum
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.
F# type inference runs left -> right, top -> bottom. In the first snippet, the lambda is encountered first, and the compiler has no knowledge of what the type of "d" is, so it can't assume d has a ".Hour" member. In the second snippet, the compiler has already seen the input list and knows it contains DateTimes, so when it encounters the lambda, "d" is known to be a DateTime and everything is groovy.
Ah, I see, thanks for that. So it's not running Hindley Milner (or at least, not unless it's quite heavily modified). That's not surprising, I guess, since it takes no small amount of effort to get HM to work in an OO/imperative setting.
Anybody managed to install F# on Ubuntu? There are recommended steps [0] but they've never worked for me even on a new 13.04 (& later) image on DigitalOcean.
I use F# on Windows and FreeBSD, but I've used it on Ubuntu a few times before for testing. Here's how I did installed it:
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.
Your steps are almost the same as the one I linked. But I tried them, just in case. And it still does not build. The fsharp build fails with some error about casting types. Do you have version details?
Try building the 'fsharp_30' branch instead. The master branch just switched over to F# 3.1, so its possible they haven't worked out all of the bugs for every possible system yet.
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
Azure will reset your VMs when you update their configuration. Normally this involves a rolling reset but as you only have one instance this was not possible.
Should be back up now. Mostly... If you get page not found, new DNS record didn't propogate yet. You can still use dotnetfiddle-prod.cloudapp.net or 191.234.40.