XUtils

Fabulous

F# Functional App Development, using declarative dynamic UI


About Fabulous

We believe declarative UI, functional programming, and the MVU state management are a perfect fit for app development.

Fabulous will help you create mobile and desktop apps quickly and with confidence thanks to declarative UI and the MVU architecture, all in one single language: F# - a functional programing language.

Fabulous also aims to be performant by having low memory consumption and efficient view diffing mechanisms.

Note that Fabulous itself does not provide any UI rendering. You’ll need to combine it with another framework like:

Declarative UI

Typical UI development can be a nightmare if not done properly.
It is generally created in one place, then mutated here and there based on the need and what the user is doing. Related UI pieces end up in several places, making it hard to mentally think of all the possibilities; until the inevitable race condition or bug due to an unintended user flow.

Fabulous makes it easier to reason about UI thanks to its declarative UI inspired by SwiftUI.
The UI of a component is defined in a single place and Fabulous will call it everytime the state of that component is changed.

You don’t need to think about how to mutate the UI, Fabulous will handle it for you to always match the latest UI you need.

/// A simple Counter app made with Fabulous.MauiControls
type Model =
    { Count: int }

type Msg =
    | Increment
    | Decrement

let view model =
    Application(
        ContentPage(
            "Counter app",
            VStack(spacing = 16.) {
                Image(Aspect.AspectFit, "fabulous.png")

                Label($"Count is {model.Count}")

                Button("Increment", Increment)
                Button("Decrement", Decrement)
            }
        )
    )

MVU architecture

MVU makes every state and transition between those states explicit.
You don’t need to worry about unintended actions that could lead to an invalid state which would crash the app.

Instead, you can very easily model the state of your app or component and transitions between them using F# records and discriminated unions types.
When starting, Fabulous will initialize the state. Then, when messages are being dispatched, Fabulous will let you transition from one state to the other given a specific message.

If several messages are received at the same time, Fabulous will queue them to let you update the state properly.

let init () =
    { Count = 0 }

let update msg model =
    match msg with
    | Increment -> { model with Count = model.Count + 1 }
    | Decrement -> { model with Count = model.Count - 1 }

And finally, given the functional nature of MVU, it is extremely simple to unit test each and every possible state of your application.

[<Test>]
let ``When clicking the Increment button, increment the count by one``() =
    let previousState = { Count = 10 }
    let expectedState = { Count = 11 }

    let actualState = App.update Increment previousState

    actualState |> should equal expectedState

Articles

  • coming soon...