F# end to end

Introduction

Recently my colleague @simontcousins published an article comparing to similar projects one written in C# one written in F#. The conclusion is that for the two projects the F# one is about 4% of the size. You can read more about this here.

Now normally, a typical project comprises of several languages / technologies.

However the F# project in question here has a profile more like this,

Note the stack is 'almost' completely F# (we actually could have made this completely F# see below). Maybe I'm biased but I think that this is a huge benefit for maintainability I only need to have my F# brain switched on and I can change any part of the application. Sure I have to learn a few libraries, but the playfulness offered by the REPL here makes testing and experimenting easy; this is especially true when it comes writing build and deployment scripts, which I normally find quiet difficult to test.

Full stack F#

So is it possible to use F# for everything Build, Deployment, UI (Web/WPF), Documentation. The answer is simply YES!! There is just a few libraries we need to know about to achieve this. Lets look at each area of a typical application and see which libraries we can use.

Application Logic

Ok this might seem like an obvious one, just write F#, but I thought I'd use this as an opportunity to highlight some libraries that I find useful

Build and Deployment

To build and deploy application with F# we can use FAKE. FAKE allows you to write your build and deployment scripts in F#. A simple script might look something like this

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
// include Fake libs
open Fake

//Define Targets

Description "Cleans the last build"
Target "Clean" (fun () ->
    trace " --- Cleaning stuff --- "
)

Target "Build" (fun () ->
    trace " --- Building the app --- "
)

Target "Deploy" (fun () ->
    trace " --- Deploying app --- "
)

//Define Dependencies
"Clean"
  ==> "Build"
  ==> "Deploy"

//Start Build
RunParameterTargetOrDefault "target" "Deploy"

The really nice thing about this is you have the full .NET framework and the full power of F# available in your scripts. Additionally FAKE also has an accompanying website, which allows you to manage your deployment agents, so you can easily deploy, upgrade or rollback applications from a central place.

UI

How you tackle writing a UI in F# obviously depends on your choice of technologies. There are others obviously but the two I'm going to consider are WPF and HTML/CSS/Javascript.

WPF

If you choose to write your UI using WPF then things are fairly straight forward, Write XAML markup and then use code behind F#. However wiring up the code behind can be a pain because of the C# code gen involved, typically you have to load the view yourself using a XAML reader, or code the view layout in F# as in these series of examples from John Laio. If however you want to keep XAML markup then FSharpx has a XAML type provider that helps things along here.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
open System
open System.Windows
open System.Windows.Controls
open FSharpx

type MainWindow = XAML<"libs/MainWindow.xaml">

let loadWindow() =
    let window = MainWindow()
    window.myButton.Click.Add(fun _ ->
        MessageBox.Show("Hello world!")
        |> ignore)
    window.Root

[<STAThread>]
let main(args) = (new Application()).Run(loadWindow())

See Steffan Forkmann's post for more information about this. Lets also not forget about first class events and the asynchronous programming model in F# that makes writing responsive UI's that much easier.

HTML/CSS/Javascript

If you go webby then things get a little more interesting, we have several options available here.

Documentation

@thomaspetricek recently released FSharp.Formatting we can generate documentation from an F# script file, using a mix of markdown and F#, for an example see this link. This can then be integrated into your FAKE build script, using a build target something like the following example, Incidentally this is exactly the library that is used to create this blog.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
open System.IO
open FSharp.Literate

Target "Docs" (fun _ -> 
    let template = Path.Combine(currentDirectory, "template.html")
    let sources = Path.Combine(__SOURCE_DIRECTORY__, "samples")
    let output = "out_dir"
    
    Literate.ProcessDirectory(sources, template, output)
)

Conclusion

Ok I might of over stated that everything can be written in F#, certainly at the moment there is a lack of libraries for emitting XAML and HTML (with the exception of WebSharper of course). But HTML and XAML are really inconsequential when it comes the to the correctness of your application they do not contain any logic which needs to be tested they simply control layout. The important thing to take from the above is the fact that all of your logic whether it is for build, deployment, UI interaction, example documentation can be written in a type safe way using the various libraries and F# feature spoken about above.

namespace System
namespace System.Windows
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
namespace System.IO
tweet-share