views:

1000

answers:

5

Many times I hear that F# is not suited to particular tasks, such as UI. "Use the right tool" is a common phrase.

Apart from missing tools such as a WinForms/WPF/ORM designer, I'm not sure what exactly is missing in F# -- honestly! Yet, particularly with UI, I'm told that C# just does it better. So, what are the actual differences and omissions in F# when using it imperatively?

Here is a list I came up with:

  • Lots of missing tool support

  • F# is still beta

  • Your developers don't know F#

    • I'd like to not consider those points, as they aren't really intrinsic to F#
  • Mutables need "mutable" or need to be ref, ref needs ! to dereference

  • Mutables assign with <- and ref uses := ( they're both 1 more character than just = )

  • val needs DefaultValueAttribute to get a default value

  • F# doesn't emit implicit interfaces

  • Protected members are more difficult to deal with

  • No automatic properties

  • Implemented virtual members on abstract classes require two definitions

  • Quotations-to-LINQ-Expression-Trees produces trees slightly different than C#/VB (annoying for APIs that expect their Expressions in a specific format)

  • No stackalloc

  • F# doesn't have the ?: conditional operator

  • Pointers might be considered more cumbersome in F#

  • Delegates/events might possibly be considered more cumbersome (I'd argue they're easier, but at a minimum they're different)

  • No automatic type conversions (like int to float, or implicit casts)

  • No special syntax support for Nullable (C#'s ? type annotation and ?? operator, as well as using operators on nullables.)

  • No automatic upcasting to common base class or boxing (ex: let x : obj = if true then 1 else "hi" // this won't typecheck)

  • Values can't be discarded without a warning ("ignore" to get around it)

  • Doesn't have C-style syntax :)

To the question: Which of these are a hindrance to writing imperative or OO code? Why (short examples)? Which ones did I miss? What are the best workarounds, and why are they not enough?

Please note, I'm not talking about writing so-called idiomatic F#, and I'm certainly not talking about functional programming. I'm more interested along the lines of "If I were to force myself to write UI or imperative/OO code in F#, using F# OO/imperative features and class types, what hurts the most?"

Bonus If you don't know F# but use C# or VB.NET and think it's a better tool for some situations, please indicate the specific language features and syntax you find appealing.

+4  A: 

With regards to OO stuff, my list might be

  • You mentioned some things about interfaces and virtuals that can be annoyances or hindrances; lack of auto-props you mentioned is also a shame
  • OO frameworks sometimes require many mutually recursive classes, which F# currently forces you to put in one file (in a 'type ... and ... and ...' block)
  • If you need to call two different base constructors in a derived class, you have to use the 'explicit' class syntax (as mentioned here)

That said, F# has strengths in the OO department too, like type inference, local functions, succinct syntax, ... so overall I might call it a wash in the 'heavily OO' department.

(I have done almost no UI programming of any kind, so am not qualified to weigh in there.)

(EDIT: I also want to interject that, even though you're explicitly choosing to exclude 'tooling' from the question, I think tooling matters a bit, and in this respect the other managed VS languages excel.)

Brian
Oh yea, the whole recursive type thing can be a pain. But... you guys are fixing that, right? :)
MichaelGG
Your OO reference is way off. Do you mean static typing? Or imperative?
leppie
@MichaelGG: Eventually it will get fixed, but it's unclear if this will make the VS2010 first release. IMO this limitation is the only thing in principle that would prevent you from authoring e.g. a 100,000-line OO framework in F#.
Brian
@leppie: I meant OO. Like, authoring a small class is often simpler/easier in F# than C# (thanks to type inference and simple syntax).
Brian
What about protected members? Seems like a big OO framework would get hurt on that too.
MichaelGG
My personal opinion is that "protected is bunk"; I don't miss it for a second. But I can easily imagine that others may find that objectionable, so sure, add it to the list. :)
Brian
Yea, I'll second that small classes are easier. This NHibernate helper class: http://stackoverflow.com/questions/729687/how-do-i-select-a-random-row-using-nhibernates-icriteria-api/732250#732250 can be a 1 line object expression in F# :P.
MichaelGG
Tooling is huge. No doubt about it. But what about the other languages makes them excel at it?
MichaelGG
+1  A: 

My biggest pain with statically typed functional languages is inability to have variable arguments on a method that needs to be inferred. Like the map function. In F# you need map2 map3, etc.

On the other hand C# lacks this too, unless you want to go via reflection.

Take Scheme for example, that is not statically typed. You do not have an issue to define a single function that can handle all the cases of map_1 ... map_n. Sure you loose static type safeness, but it pales in comparison to the additional convenience of writing concise code.

leppie
For the PHP haters try not to gag but I still use PHP to create scripts because of its dynamic types and accompanying horde of functions.
gradbot
Hmm I don't think I've run into too many times where I need to abstract over the number of parameters. But, again, F# and C# both allow you to mix in dynamic if you feel inclined to do so for some reason. If you want to pass object arrays and dynamically invoke delegates, there shouldn't be a problem. I just wouldn't want to give up type safety for that in most cases.
MichaelGG
+5  A: 

Imperative programming in F# is much better than people would lead you to believe. F#'s match statement is awesome. Why other languages have not implemented it I don't know. As far as things like syntax (mutable, ref, etc) they are easy to work with. You get spoiled by F#'s sparseness and it's easy to complain when the syntax is bigger than normal. Tuples are also great. They will be in C# 4.0 too. Currying is another bonus for Imperative.

Concerning OO I find I rarely use inheritance in pure F# projects and favor composition and interfaces instead. This is mainly due to using the primary contructor that allows you to use it's parameters as private properties in your methods (not sure if I worded that correctly). Other language constructs such as pattern matching pull you away from inheritance too. I've not done any mixed projects C#/F# so I can't comment on that.

F# isn't all roses.

My biggest issue with F# and game programming is performance. Implementing in F# is really fast and I often get a prototype up and running for what I want to do the same day I think of it however I find myself rewriting code for performance reasons way more often than in C#.

Part of the problem is my inexperience with functional programming style that is to use Seq, List, Map and all their accompanying methods such as map, iter, fold, scan. My first functional solution is almost never the fastest while my first procedural solution is almost always close to the best possible. I want to say part of this isn't me. That functional programming doesn't lend its self to performance in some situations.

I use less of the functional data types in F# now than when I started.

EDIT:

Many months have gone by since I've posted this and I no longer have issues with performance. My first functional solutions are often simpler and nearly optimal now and immutable data structures are simple. The only performance issues I have now are with the CLI and I can always do c++/cli if I need to. I do use some inheritance besides interfaces now but it's only for anonymous objects.

gradbot
complex f# on XNA will always be more painful until the JIT does escape analysis reliably or adds a generational GC. The allocations inherent in it's current (and likely fixed) implementations of many of it's useful aspects such as FastFunc, Tuples and closures. c# has the same issue on delegates,closures (and from 4.0 Tuples) but it doesn't push their use quite so much. Avoiding allocations in tight game loops is important design consideration for XNA performance.
ShuggyCoUk
F# should be at least as fast as C# and often a *lot* faster. If you're having to rewrite your F# in C# to get adequate performance then you're doing something seriously wrong and need to learn how to optimize F# code.
Jon Harrop
@Jon Harrop, indeed I was. Being new to functional programming it takes a while before you start approaching problems differently.
gradbot
Agree with your EDIT. The performance of my F# program is also close to that of C#, and I also like C++/CLI a lot for a last resort :) I also use PInvoke sometimes as there are code use machine independent optimization, e.g. BLAS/ATLAS.
Yin Zhu
+8  A: 

I'm not a huge fan of this question as it complains about F# not supporting idiomatic C#. For example, I don't think it's fair to criticize F# for using <- and := for variable assignment because the language makes things immutable by default.

Regardless, there are several imperative / object-oriented things you can do in C# that you simply cannot in F#.

  • F# doesn't not support nested classes. In C# you can declare a class within the body of another class as a mechanism for scoping types. F# does not support this.

  • F# doesn't allow you to implement the same generic interface twice. For example, in C# you can implement IComparable and IComparable on the same type.

  • In F# you must have architectural layering. Due to F#'s type inference you can only use classes that have been declared 'before' or in the same 'block' of type declarations. In C# however you can have any class reference any other. (This actually enforces some good programming practices.)

  • F# doesn't have 'native' support for LINQ, as in no from keyword. However, you can use LINQ APIs and lambda expressions to achieve the same result.

Things that F# can do that C# can't:

  • Discriminated unions. This makes it trivial to create tree-like data structures in F#, where in C# you'd have to resort to a complex type hierarchy.

  • Asynchronous workflows. This feature of the F# library makes asynchronous and parallel programming much more paletable by abstracting away all the pain associated with the APM.

  • Pattern matching and active patterns.

  • Units of measure for eliminating bugs associated with using the wrong units. (E.g., adding 'feet' to 'meters'.)

  • etc.

You shouldn't focus on what F# 'can't do like C#' because the whole point of learning F# is to be presented with a new way to think about problem solving. If you write idiomatic C# code in F# you aren't actually gaining anything.

AFAIK F# isn't missing any 'must haves' for .NET / COM interop. In F# you can do things like have out and byref parameters, declare string literals, and support putting attributes on just just about anything.

Chris Smith
Yes I am afraid I didn't make my viewpoint very clear. I'm not complaining about F# or criticising it - just pointing out the differences. My real question is "why is C# more suited for UI than F#", or something to that effect. I definately don't believe it's the case that C# is often or ever the "right tool". I just wanted to see if someone could back that up. (I feel sick when I have to write in C#. Even if I'm going to write "C#", I'd rather do it in F# and have inference, pattern matching, etc.)
MichaelGG
"For example, in C# you can implement IComparable and IComparable on the same type." - doesn't make much sense!
Casebash
A: 

Just for the record: F# has stack allocation - try an infinite recursion that's not tail recursive and you'll get a stack overflow. It's really no different to stack allocation in C#, aside from you knowing that you can use tail recursion safely F# (in C# it depends).

Also, I'd point out that when you get to really heavy event oriented code, F# scales better than C# in terms of allowing you to build up a framework to do the "plumbing" of dispatching events to handlers, etc without the plumbing becoming the majority of your code. For a simple UI, C# or VB may suit more people. For complicated situations, F# pulls ahead, and personally I need help with the complicated situations more than the simple ones.

RD1
Oh, and I think exactly opposite about "Sure you loose static type safeness, but it pales in comparison to the additional convenience of writing concise code." You may save 10% of your typing, but you'll spend an awful lot longer doing run-time debugging. If you want a variable number of arguments, just use a list! You can implement the same universal mono-type that scheme uses in F# very easily in fact - but you can do better and choose static typing exactly where you want it.
RD1
I meant direct "stackalloc" to get a pointer to a block of memory you own on the stack. In F# I suppose you'd have to create a large structure and take its address. But overall it sounds like you're saying that C# doesn't have much advantage, which was my point.
MichaelGG