Impressions of using F# (with a little bit of Xamarin.Forms)

In the last days I completed the first version of FFRAB-Mobile (see here). I used F# and Xamarin.Forms to gain more experience in a bigger project than a simple example app. You can find the sources here: https://github.com/SabotageAndi/ffrab-mobile

Here are my impressions:

.) Writing stateless could be hard, but it is worth the trouble

Coming from a C# background, now writing code that is near complete stateless is new and unusual. So the first code I wrote was a lot of object oriented stuff with too much access to shared state. Especially the access to the database connection was at the beginning a little bit painful.

But after some refactoring it got more and more in a functional style. At least I hope so.

Before refactoring:

https://github.com/SabotageAndi/ffrab-mobile/blob/0e72e26e83f5112e6c95cc99959baa9a55eb9882/ffrab.common/model.fs Line 52 – 140

After refactoring:

https://github.com/SabotageAndi/ffrab-mobile/blob/master/ffrab.common/database.fs
https://github.com/SabotageAndi/ffrab-mobile/blob/master/ffrab.common/queries.fs

At the end it was worth the trouble. It is more readable and simpler code.

.) If it looks ugly, make a function

When you have pure F# code and libraries, it is complete in your hands to write nice code. But when you are using C# libraries, i can quickly get ugly because of the library. This is because the parameters of the C# methods are represented as tuples. With them, you have a lot of brackets and can not use the forward pipe operator ‘|>’.

But simply wrap the C# method call in a small function and voila.

Here is an example when using NodaTime (the “let startTime”- line is the important one):
Direct call to C#:

let dateTimeFormat = OffsetDateTimePattern.CreateWithInvariantCulture("yyyy'-'MM'-'dd'T'HH':'mm':'sso<G>")
let startTime = common.Formatting.dateTimeFormat.Parse(dayNode.["day_start"].Value<string>()).Value

With F# wrapper function:

let parseNodaTime<'T> (pattern : NodaTime.Text.IPattern<'T>) rawValue =
        let result = pattern.Parse(rawValue)
        result.Value

let dateTimeFormat = OffsetDateTimePattern.CreateWithInvariantCulture("yyyy'-'MM'-'dd'T'HH':'mm':'sso<G>")
let startTime = (json.GetProperty "day_start").AsString() |> parseNodaTime common.Formatting.dateTimeFormat

For one usage it might be not that bad, but when you have multiple calls, it is more readable. Particularly you get the nice left- to- right readability back!

.) Left- to- right readability combined with railway oriented programming (ROP) rocks!

Look at this example:

let synchronizeData conference =
            match conference with
            | Some conference ->
                conference 
                |> checkForTimeout
                |> getDataLocation
                |> fetchJson 
                |> Parser.parseJson conference
                |> Synchronization.sync conference
            | _ ->
                ignore()
            conference

All parts of the synchronization are nice one after one step easy readable and extendable. So adding the additional timeout check was easy to add to this pipeline.

.) MVVM is more fun with FSharp.ViewModule than with C#

With FSharp.ViewModule and F# you have so much less boilerplate code in your viewmodels. Without the curly brackets of C# you can reduce the line count again.

So the 8 viewmodels are about 260 lines (with empty lines and boilder plate functions/type). In C# 3 of the viewmodels would have this code size.

.) Tooling? Enough, but some rough edges

When you code in Visual Studio, you need the Visual F# Power Tools. And the first thing you have to do is to enable Folder organization. You do not need the folders for your F# code, but to organize other files like images or json-Files. No idea why it is disabled by default.

On the Xamarin side there is sadly one bug, that prevents to use Xamarin.Forms on Android with F#. It looks like the F# CodeDom does not escape F# keywords.
For details is here the Bugzilla entry: https://bugzilla.xamarin.com/show_bug.cgi?id=24709
Hopefully the bug is fixed soon.

For the C# developers with Resharper: First you think you will miss it, but you do not need it. The Power Tools have a Rename function. Other refactoring features like extracting or adding namespaces I didn’t miss.

 

So for me is F# a really fun and productive language. Not everything is easy and clear when you are using it the first time, but the fog will lift with the time. When you are working some days concentrated with F#, you will learn and understand a lot. And it will be awesome. 😉

Using NodaTime in SQLite.Net

For a project I wanted to try out NodaTime, because of its nice handling with timezones.
In this project I have also to save the values into a SQLite database and for that I normally use SQLite.net for that.
Normally SQlite.net does not know how to handle the NodaTime types, but there are 2 places to add your own support for types.

1.) ExtraTypeMapping
You can specific for your types which SQLite type it should be. That could be INTEGER, REAL, TEXT or BLOB.
It’s a simply Dictionary<System.Type, String> you provide as constructor parameter, where you set the SQLite.net Type to BLOB.

2.) IBlobSerializer
When you save your values as Blob, you can use the BlobSerializerDelegate of SQLite.net and provide the appropriate delegates to serialize and deserialize your types.

When you combine both, you can simply save your own types as blob in your database.

The code for saving LocalDate, OffsetDateTime and Duration you can find here: https://gist.github.com/SabotageAndi/194aa01e1c78cb614c1b.

It is in F#, but it is understandable by C#-only developers. 😉