Why F#
davefancher.com
davefancher.com
It's like a parallel universe to the Scala/Java relationship.
1. Common ascendants
Scala is heavily influenced by OCaml and Haskel.
F# is descendant of OCaml, heavily influenced by Haskel.
2. Past
Don Syme designed generics for .NET.
Martin Odersky designed generics for JVM.
3. Erlang influence
Acca - heavily influenced by Erlang and OTP, MailboxProcessor looking quite similar to Erlang processes.
4. Multiple paradigms
Both languages combine FP and imperative. Scala is more OOP, F# is more FP.
And (in my opinion) F# is looking more "clean" than Scala.
Simple thing in F#:
let (|>) g f = f g
In Scala becames much more complicated. Also I think that discriminated unions are "prettier" than case-classes.That depends on your background. As far as FP goes, I wouldn't see myself working in a FP language that doesn't have type-classes or something similar. Clojure has protocols and multimethods, Scala has type-classes based on implicits, while F# doesn't have anything like that.
> F# is looking more "clean" than Scala.
I don't know about that, I got used to Scala code. As far as the languages are concerned, I hate for instance how F# imported some language features from C# that really needed to die a long time ago, like static class members and operator overloading based on said static class members. Scala on the other hand cleaned all that crap. My problem with F# is basically that it has 2 type systems in the same language. Same problem that Ocaml has really, except Ocaml can also do some pretty cool tricks with structural typing for OOP that F# cannot.
But anyway, these issues are actually irrelevant because the choice for developers will end up being the answer to ".NET or the JVM?"
I agree that F# is not pure as Haskel and limited in comparison with OCaml and Haskel.
But the things that works in F# are working fine. In comparison with Scala: curring (by design) and tail-calls optimization are looking "more FP" in my opinion.
Also Scala does optimize self-recursive tail-calls and it's pretty easy to work with trampolines. This is a platform limitation btw, as you can't optimize tail-calls without support from the VM. Mono, the open-source .NET implementation, also has problems with optimizing tail-calls (last time I checked) and I don't know about .NET 4.5, but .NET 4 was not optimizing tail-calls on 64-bits Windows. I remember reading a blog post about them fixing it on 64-bits OS in the latest version, but it wasn't the kind of feature you could rely on in the past.
I do have hopes that TCO will make it into the JVM at some point, as there are experiments for it available as part of OpenJDK. Unfortunately the JVM moves at a glacial pace in regards to such features. This is both a blessing and a curse.
I do agree with you. Not having full TCO in a functional language kind of sucks.
and I don't know about .NET 4.5, but .NET 4 was not
optimizing tail-calls on 64-bits Windows.
Actually there's a .tail CLI Opcode in .NET for tail call optimization which is not usually emitted, but the JIT does tail call optimization on 64 bits (not on 32 bits though). You can witness this when you have a C# getter calling itself. On 32 bits, you get a StackOverflowException, on 64 bits it keeps running happily forever. For the specifics: http://blogs.msdn.com/b/clrcodegeneration/archive/2009/05/11...It's lower level and more limited than full blown FP aware TCO and it may not catch every call pattern, but it's been there for a while.
In fact, F# is able to target previous version of the CLR (.NET 2.0, 3.0, and 3.5) and I know for a fact that they also support the 'tail.' opcode and perform some TCO (though it handles fewer edge-cases than .NET 4.0 and 4.5).
You see static String.Split and normal method Split of String objects.
First method does not belong to string objects, it belongs to String class.
String class is an object itself, so why not make this distinction more explicit?
It exactly so in Scala: classes are classes and all static members goes to companion objects. Companion objects by nature are singletones.
I think it's much more natural this way than in C++/Java/C#. Everything on its place, even singletones became elegant.
Those features [type classes,structural (sub)typing] you mention as being a problem simply aren't really missed due to other things on offer. While F# does not have type classes (non erasure has it's advantages to ease that lack) you don't really notice it as it turns out that kind of power is pivotal in a handful of cases and for that F# has these statically resolved type parameters which do a kind of static duck typing that is good enoughTM. The static overloading is not hit and the static methods are useful the way F# implements them (makes things simple, not as annoying or cumbersome as in C#).
Most of the time computation expressions and or simple abstract classes or interfaces with object expressions , occasionally coupled with active patterns are more than good enough for the kind of places type classes might otherwise be used. Personally, I try to make simple choices so that algebraic datatypes and records are all that is needed. I'm allergic to fancy code. I mentioned active patterns, they are really quite powerful - at the same level of power as multimethods (I have used them to solve an expression problem type thing). I believe that the use of Active Patterns and Quotations in F# is more common than in Scala due to choices in where power focus lie. I also find F#<->C# interop to be a bit easier than Scala<->Java interop for the same reason that C# -> F# objects are basically injective while Java -> Scala is only a subset.
I also think F# is more functional than Scala. Scala is supposed to be something different: a successful melding of OOP and functional. And it is the best at that I have seen. It succeeds on this better than the next biggest contender: F#. F# is more typically functional, using the usual Hindley Milner Inference and sharing a core with OCaml but with significant whitespace. So it can be very succinct. Typically functional idioms like algebraic data types, Piping, point free, currying and combinators is more natural to F# than Scala's more OOP way.
There are a number of things that Scala does naturally that are cumbersome in other languages because of how it manages to meld a powerful combination of orthogonal features. To use Scala as just another functional language is to miss its power. Those who criticize OOP have not used a language that does it right. Abstractly, in a simplified categoric setting, we can consider Abstract types (objects as an aproximation as coalgebras) and FP (algebraic data types) as duals of each other. A proper unification of the concepts gives something more flexible than either. I think Scala comes the closest. Sure you can be 100% functional in it, or replicate Java but to call it one or the other is to make the same mistake as to say that light is both a wave and a particle and think you understand what that means.
public class CircleMeasurement
{
public double Diameter { get; private set }
public double Area { get; private set }
public double Circumference { get; private set }
public CircleMeasurement(double diameter, double area, double circumference)
{
Diameter = diameter;
Area = area;
Circumference = circumference;
}
}
Arguably there's still a fair bit of repetition due to the constructor, compared to the F# code (and I'm not sure object initializers can be used with private-set properties), but a third of the repetitions have been skipped through implicit backing fields.I think C# is a fantastic language, but if the development of F# got to the point where I could swap out either language when building an ASP.NET website with no worries about compatibility or missing out on anything (ReSharper being a big one) I would happily use F# on a project, and I'm willing to bet that many other developers would.
What seems to be holding off many people, including myself, is a lack of knowledge and information about F# from the higher-ups.
Sometimes I like having the power to use a functional language for a certain task, but would rather not develop an entire project with one. C# does have functional abilities (Linq), but it's not quite the same.
I also feel that I wouldn't want to write the whole app in F#, because I don't feel like the OO/FP approach feels as natural for some parts of the app as plain old C#.
Having to explain the Visitor pattern though to someone else would be much more painful than that I imagine versus just writing and explaining it in F#. The code just reads much more naturally for it, since the language supports it without a quirky design pattern.
Yes. It's even possible in some cases to use F# source as some kind of pseudo-code with C#-programmers.
For curiosity, what in particular do you find to be unnatural in F#?
It is whole program optimized, strongly typed, polymorphic, ML like language without a default evaluation order that can interact effortlessly with C and C++ code and compiles down to C++, another differentiator is the presence of coroutines
I can point to two tutorials. One explains Felix by beginning from C++ [1], the other describes Felix the language [2].
[1] http://felix-lang.org/web/nutut/intro/intro_index.fdoc
[2] http://felix-lang.org/web/tutorial.fdoc
No analogies are correct, but roughly
Felix is to C++ what Scala is to JVM (or F# is to C#). Note however Felix predates all these languages.
@Ingaz the analogy is a little more literal because Felix compiles down to C++ (unlike OCaML)
But I always thought that OCaml to C++ is what F# to C#.
Even if I'm writing code that's not very functional, using F# as a better C# seems to work very well.
The main reasons to use C# are for legacy interop and perhaps if the code isn't a major focus and hiring someone capable of writing F# would actually be a limitation. Some folks also feel F# is clunky for imperative code; I haven't really felt that way.