Before I joined Compositional IT I spent 7 years as a mobile app developer using Xamarin, and most of the projects I worked on used C#.
Now I have the opportunity to use F# everywhere which, as anyone in the community will testify, is a dream come true. As such, I have finally found the time to take a proper look at a project which has been high on my list for quite a while, Fabulous.
The Xamarin team have always been very supportive of F# and have encouraged its use since the early days of the project. I am the proud bearer of both C# and F# t-shirts from their original mobile store demo in 2014 (plus two monkeys!).
Until fairly recently, if you wanted to make F# applications using Xamarin then you really needed to use an object oriented approach for the front-end.
Now however we have the option to use Fabulous, which provides a functional-first abstraction over Xamarin Forms. This lets us really harness the power of F# to build great cross platform, native mobile apps.
In part one of this blog I'll provide a bit of background on Xamarin and explain how Fabulous fits in to the overall picture.
Cross-platform and Native?
It may seem like a contradictory idea but Xamarin does in fact allow you to write .NET code which results in native iOS and Android applications (as well as other platforms).
It achieves this feat by binding to the native runtimes. You are provided with a .NET version of just about every class in the native framework. For every instance of that object you create, a matching object is created in the native runtime. Every time you execute a method on the .NET object, the same method is called on the native object.
This is all pretty invisible to the developer in most cases, and it just feels like writing a native app, but using C# or F# rather than Swift / Objective C or Kotlin / Java. If you have experience writing apps using one of those languages, you would be able to pick up Xamarin Native and get to work straight away with all the same tools and processes that you are familiar with, including the Android Designer and XCode Storyboards.
You also have access to the entire .NET ecosystem of libraries and tooling which is hugely valuable, plus they provide you with a comprehensive set of plugins known as Xamarin Essentials which bridges the gap between the platform APIs to allow you do do things such as get the device location, launch a browser or detect connectivity as well as many other functions from a single codebase.
This approach drastically reduces development time and maintenance costs of an app, which in a world that moves as quickly as mobile soon pays dividends.
Whilst the degree of usability provided by Xamarin Native is already pretty extensive, you are still required to code the user interface separately for each platform.
Xamarin Forms takes this a step further, providing an abstraction over the native UI frameworks. You define your layouts using a form of XAML which is very similar to that seen in WPF or UWP applications.
There is an effort underway to unify these various UI frameworks under the name MAUI, or Muliti-platform App UI.
This is then converted to a native layout when you compile the application. If you have added a button to the page, an Android button is created in your Android app and an iOS button in your iOS app.
If you need something that isn't provided out of the box, you can create your own Forms component by defining a UI object interface and then implementing it on each platform.
This usually involves creating some mutable object which serves to hold the current state of the UI. The object is then connected, or bound, to the UI in some way. Changes in the UI cause changes in the state object and vice versa.
Whilst this approach certainly works and has its benefits, it is not very idiomatic to F# or to functional programming in general. Here, we favour immutability and pure functions (i.e. those which produce a consistent output for a given input, without side effects).
A pattern which allows us to achieve these goals is known as Model-View-Update, or MVU. As the name implies, it has three major components.
- Model - An immutable object representing the current state of the application.
- View - A function that given a model, generates a UI layout.
- Update - A function that given a model and a command, can produce a new model.
Take your model and generate a UI. Issue a command which generates a new model. Re-render the UI using the new model. It sounds deceptively simple, but just like most things in functional programming the key is in the composability of the pattern. You can build rich applications using these basic building blocks.
What we get is a predictable, repeatable output for a given input. We also have an easy way to snapshot and replay application states simply by dehydrating and rehydrating the model, which again is particularly important in the world of mobiles apps with their strict power and memory management requirements.
Fabulous brings the MVU pattern to Xamarin Forms.
Instead of writing XAML to define our layouts, we use a much more suitable language - F#! If you think about it, it's quite odd that we often try to define dynamic UIs using a static language such as XML.
If you want to conditionally show a thing - use an
if statement! If you want to invert a property - use the
not function! No need for an IBoolInverterConverter patched into INotifyPropertyChanged event handlers. Just some basic F#.
If you have used Razor pages or components in ASP.NET you may be familiar with this idea already.
You write a function that takes in a model, and emits a nested list of UI components and their layout properties. You can lay out your code on the page just like you might with XAML, but it has all the power of F#.
Fabulous provides view elements for all of the Xamarin Forms components you may be familiar with, and will render the UI in an efficient way once you have generated it.
For those it doesn't provide or that you have created yourself, you can write a simple binding class (see part two of the Xamarin Show links below). I am sure the team would appreciate any contributions over at their GitHub, including third party component bindings and any nice examples of apps you have made.
I made a fun little app after a work hack day recently which will probably be the basis for a more technical deep dive in part two of this blog, so watch this space.
For a fantastic primer on MVU and Fabulous, check out Don Syme's talk from NDC last year.
Don and Tim also recently did a couple of great episodes demonstrating Fabulous on the Xamarin Show :
If you would like to know more about mobile app development with Xamarin and F#, whether for a bit of technical help or to enquire about training and consultancy services, ping me a message at firstname.lastname@example.org for a chat.