In what areas might the use of F# be more appropriate than C#?

c# f#
23,670

Solution 1

I have written an application to balance the national power generation schedule for a portfolio of power stations to a trading position for an energy company. The client and server components were in C# but the calculation engine was written in F#.

The use of F# to address the complexity at the heart of this application clearly demonstrates a sweet spot for the language within enterprise software, namely algorithmically complex analysis of large data sets. My experience has been a very positive one. In particular:

Units of measure The industry I work in is littered with units. The equations I implemented (often of a geometric nature) dealt with units of time, power and energy. Having the type system verify the correctness of the units of the inputs and outputs of functions is a huge time saver, both in terms of testing and reading/understanding the code. It eradicates a whole class of errors that previous systems were prone to.

Exploratory programming Working with script files and the REPL (F# Interactive) allowed me to explore the solution space more effectively before committing to an implementation than the more traditional edit/compile/run/test loop. It is a very natural way for a programmer to build their understanding of the problem and the design tensions in play.

Unit testing Code written using non-side effecting functions and immutable data structures is a joy to test. There are no complex time-dependent interactions to screw things up or large sets of dependencies to be mocked.

Interoperation I defined the interface to the calculation engine in C# and implemented the calculation in F#. The calculation engine could then be injected into any C# module that needed to use it without any concerns at all about interoperability. Seamless. The C# programmer need never know.

Code reduction Much of the data fed into the calculation engine was in the form of vectors and matrices. Higher order functions eat these for breakfast with minimal fuss, minimal code. Beautiful.

Lack of bugs Functional programming can feel strange. I can be working on an algorithm, trying hard to get the code to pass the type checker but once the type checker is satisfied thats it, it works. Its almost binary, either it wont compile or its correct. Weird edge case errors are minimised, recursion and higher order functions remove a lot of book-keeping code that introduces edge case errors.

Parallelism The functional purity of the resulting implementation makes it ripe for exploiting the inherent parallelism in processing vectors of data. Maybe this is where I will go next now that .NET 4 is out.

Solution 2

During my internship at Microsoft Research, I worked on some parts of Visual Studio IntelliSense for F# (which is itself written in F#). I already had some experience with IntelliSense from earlier C# projects, so I think I can compare the two.

  • Visual Studio Extensibility is still based on COM, so you need to deal with objects that are not very nice .NET objects (and definitely not functional), but I don't feel there is any major difference between C# and F# (it works smoothly from F#)

  • The data structures used to represent program code in F# are mostly discriminated unions (which are not supported in C# in any reasonable way) and this makes a huge difference for this kind of application (where you need to process tree structures, such as program code). Discriminated unions and pattern matching allows you to structure the code better (keep related functionality in one place rather than having it all over the place in virtual methods)

Earlier, I also worked on CodeDOM provider for F# (also written in F#). I actually did first experiments in C#, but then converted the code to F#.

  • CodeDOM provider needs to traverse some structure represented using .NET objects, so there isn't much space for inventing your own representations of data (which is the area where F# can offer nice benefits).

  • However, there were many small F# features that made the task easier. Since you need to produce a string, I defined custom operators for building strings (using StringBuilder) and implemented the code using them and higher-order functions (e.g. to format list of objects separated using the specified string etc.), which removed a lot of repetition (and tedious foreach loops).

These are two relatively specific examples, but both of them are related to working with representations of programs, or expressions, or more generally, complex tree-like data structures. I think that in this area, F# is definitely a good choice (regardless of the functional features in C#).

Solution 3

We shipped the world's first commercial product written in F# (F# for Visualization) and the second (F# for Numerics) as well as the first commercial literature on F# (The F#.NET Journal) and wrote and publish the only book about the current version of F# (Visual F# 2010 for Technical Computing).

We had been shipping products along similar lines written in C# (e.g. this) but we also had a strong background in the commercial use of OCaml. We were enthusiastic early adopters of F# when it was still a research prototype back in 2006 because we recognised the potential of having a decent modern OCaml-like language on the industrial-strength .NET platform and, consequently, we pushed to have it productized. The result has been an incredible success and F# has far exceeded our lofty expectations.

For us, F# has many different advantages and we use it for a wide variety of applications. We have hundreds of thousands of lines of F# code in production. We now use F# for all of our LOB apps: our credit card transactions are processed using F# code, our product notifications are sent using F# code, our subscriptions are handled using F# code, our accounts are done using F# code and so on. Perhaps the main language feature that pays dividends here is pattern matching. We even used F# to color syntax highlight our latest book...

Our visualization library is a big seller and its functionality centers on F# interactive running in Visual Studio. Our library augments this with the ability to spawn interactive 2D and 3D visualizations with minimal effort (e.g. just Plot([Function sin], (-6., 6.)) to plot a sine wave). In particular, all threading issues are completely automated so users do not have to worry about UI threads and dispatch. First-class functions and laziness were extremely valuable when writing this part of the library and algebraic datatypes were used extensively elsewhere. Predictable performance also proved to be valuable here when our customers hit performance bugs in WPF's hit testing and were easily able to reimplement the relevant code in F# for a 10,000× performance improvement. Due to the free-form nature of this product's GUI, the GUI designer and C# would not have been beneficial.

Much of our work revolves around numerical methods, including both our commercial libraries and books. F# is much stronger in this area than C# because it offers high-level abstractions (e.g. higher-order functions) with minimal performance penalties. Our most compelling result in this context was the creation of a simple but generalized implementation of QR decomposition from linear algebra that was 20× shorter than the Fortran code from the reference implementation of LAPACK, up to 3× faster than the vendor-tuned Intel Math Kernel Library and more generic because our code can handle matrices of any type, even symbolic matrices!

We are currently developing WPF/Silverlight components in a mix of F# (for the guts) and C# (for the shim), building WPF apps to act as interactive manuals for our software products and I am writing a new book, Multicore F#, that will be the definitive guide to shared-memory parallel programming on .NET.

Solution 4

Over the last 6 or so months, I've been working on a Vim emulation layer for Visual Studio 2010. It's a free product with all of the source it's freely available on github

The project is divide into 3 DLL's representing a distinct layer. Each layer has a corresponding unit test dll.

  1. Vim Engine: F#
  2. WPF layer for adornments and editor integration: C#
  3. Visual Studio Integration layer: C#

This is the first major project I've ever done with F# and I have to say I love the language. In many ways I used this project as a method of learning F# (and this learning curve is very much evident if you look through the history of the project).

What I find the most amazing about F# is just how concise of a language it is. The Vim engine comprises the bulk of the logic yet it only comprises 30% of the overall code base.

Solution 5

A lot of the unit tests for the F# Visual Studio components are written in F#. They run outside VS, mocking the various Visual Studio bits. The ability to cons up anonymous objects that implement interfaces is useful in place of a mocking framework/tool. I can just write

let owpe : string list ref = ref []
let vsOutputWindowPane = 
    { new IVsOutputWindowPane with
        member this.Activate () = err(__LINE__)
        member this.Clear () = owpe := []; 0
        member this.FlushToTaskList () = VSConstants.S_OK
        member this.GetName(pbstrPaneName) = err(__LINE__)
        member this.Hide () = err(__LINE__)
        member this.OutputString(pszOutputString) = owpe := pszOutputString :: !owpe ; 0
        member this.OutputStringThreadSafe(pszOutputString) = owpe := pszOutputString :: !owpe ; 0
        member this.OutputTaskItemString(pszOutputString, nPriority, nCategory, pszSubcategory, nBitmap, pszFilename, nLineNum, pszTaskItemText) = err(__LINE__)
        member this.OutputTaskItemStringEx(pszOutputString, nPriority, nCategory, pszSubcategory, nBitmap, pszFilename, nLineNum, pszTaskItemText, pszLookupKwd) = err(__LINE__)
        member this.SetName(pszPaneName) = err(__LINE__)
    }            
DoSomethingThatNeedsA(vsOutputWindowPane)
assert( !owpe = expectedOutputStringList )

when I need an instance of e.g. an IVsOutputWindowPane to pass to some other component that will eventually be calling OutputString and Clear, and then inspect the string list ref object at the end of the test to see if the expected output was written.

Share:
23,670

Related videos on Youtube

Peter McG
Author by

Peter McG

Updated on August 15, 2020

Comments

  • Peter McG
    Peter McG over 3 years

    Over the last few years F# has evolved into one of Microsoft's fully supported languages employing many ideas incubated in OCaml, ML and Haskell.

    Over the last several years C# has extended its general purpose features by introducing more and more functional language features: LINQ (list comprehension), Lambdas, Closures, Anonymous Delegates and more...

    Given C#'s adoption of these functional features and F#'s taxonomy as an impure functional language (it allows YOU to access framework libraries or change shared state when a function is called if you want to) there is a strong similarity between the two languages although each has its own polar opposite primary emphasis.

    I'm interested in any successful models employing these two languages in your production polyglot programs and also the areas within production software (web apps, client apps, server apps) you have written in F# in the past year or so that you would previously have written in C#.

  • Peter McG
    Peter McG almost 14 years
    Interesting, more evidence that the uptake of F# within Microsoft is certainly high. I didn't know you could create anonymous objects that implement interfaces in F#
  • Peter McG
    Peter McG almost 14 years
    Fascinating: F# running on the compact framework on XBox. Doesn't FSharp.Core.dll along with FSharp.Core.optdata FSharp.Core.sigdata reference non-CF assemblies?
  • Peter McG
    Peter McG almost 14 years
    Very interesting, more evidence that the uptake of F# within Microsoft is certainly high, what a great internship that must have been!
  • Prakash
    Prakash almost 14 years
    The CTP ships with a separate FSharp.Core that's build for .NETCF. (There's also a separate FSharp.Core for Silverlight.)
  • Peter McG
    Peter McG almost 14 years
    +1 You would have previously written this in C# was it unsuitable or slower for a certain reason?
  • johnc
    johnc almost 14 years
    @Peter McGrattan At least at the time of writing (the software), there was no lex/yacc implementation in C#. It would have been possible, but a downright pain to build the parsing ourselves. stackoverflow.com/questions/540593/lex-yacc-for-c shows some other suggestions, but our lead architect is an old hand at functional languages, so the choice to use F# was a no-brainer
  • Ben Voigt
    Ben Voigt almost 14 years
    Editor ... functional language ... vi emulation ... you've re-invented emacs. NOOOOOOOOOOOOOOOOOOOOOOO!
  • Rune FS
    Rune FS almost 14 years
    if you thought there was no lex/yacc for C# I'm affraid you simply didn't look hard enough for it (There is one older than F#) that said if you need lex/yacc F# is in my opinion a much better suited hammer for that nail than c#
  • cfern
    cfern almost 14 years
    +1 for explaining why F# is very suited for number crunching engines. Another (virtual) +1 for mentioning units of measure. That part of the language deserves getting mentioned more often.
  • Pavel Minaev
    Pavel Minaev almost 14 years
    Except that it's "Certified 100% parentheses-free" :)
  • Pavel Minaev
    Pavel Minaev almost 14 years
    I used F# with fslex/fxyacc myself, though not in a "production" project (not released yet, anyway) - MSIL syntax highlighting and code completion extension for VS. The major benefit of using F# there is that you get ADTs, which are very convenient to represent parse trees. Also, using zippers (en.wikipedia.org/wiki/Zipper_(data_structure)) makes it easy to do incremental lexing - and zippers, being functional, are easier to concisely manipulate in F#.
  • Peter McG
    Peter McG almost 14 years
    Great answer, relevant, contemporary and outlines F# suitability for dealing with complexity, I learnt a lot from reading it, thanks
  • JaredPar
    JaredPar almost 14 years
    @Pavel, except for tuples of course, and .net method calls
  • Pavel Minaev
    Pavel Minaev almost 14 years
    Two things of note here. First of all, tuples don't need () in F# - the , operator is what creates them, so let x = 1,2 is a valid tuple already without any parens. Second, any pair parens in F# can be replaced by pairs of begin..end (this is inherited from ML) - so, for example, "foo".IndexOf begin 'a', 1 end is a valid .NET method call. So if you ever wanted to be parens-free, F# is one language that enables you to do just that :)
  • Dan Fitch
    Dan Fitch almost 14 years
    Funny comment Pavel! Didn't know that. I think that in some cases with large grouping blocks, I might actually prefer begin..end. ALSO: VsVim RULES!
  • Chris Ballard
    Chris Ballard almost 14 years
    Great answer Simon, and as Don mentioned last night, quoted in his recent slides. Time to add an "add to cart" link?
  • Andre Artus
    Andre Artus about 13 years
    Are you the same Jon Harrop that wrote "F# for Scientists"?
  • Totti
    Totti about 13 years
    Yes. I wrote F# for Scientists 5 years ago.
  • Samik R
    Samik R over 12 years
    Do you have a reference of some sorts for the QR decomposition code in F# that you mention in your penultimate paragraph? Thanks.
  • Totti
    Totti over 12 years
    @SamikR: No, sorry. That is commercial code. It was easy to write though.
  • Nikos
    Nikos over 11 years
    hi, are you allowed to tell us more about your apps architecture?
  • Jwosty
    Jwosty over 11 years
    What is this CTP you speak of?
  • professor bigglesworth
    professor bigglesworth over 7 years
    @Jon any word on Multicore F#?