Write Flutter App purely in F#

Marko Novakovic
5 min readJan 24, 2023


In my previous blog post I told you why I don’t like Flutter that much and that that was mostly because of Dart. I also shared my love for F# and showed you some really basic examples from compiling F# to Dart.

Now I will keep my promise and show you how to write Flutter app purely in F#.

Flutter, Google’s open-source framework for building mobile apps, is quickly gaining popularity among developers. Its ability to build high-performance, visually appealing apps for both iOS and Android has made it a go-to choice for many developers. But what if we could take the power of Flutter and combine it with the elegance and robustness of a functional-first programming language? This is where F# and the Elm architecture come in.

F# is a powerful functional-first programming language that has been gaining popularity in recent years. Its strong type inference, pattern matching, and immutability features make it an excellent choice for building robust and maintainable apps.

Together, they can be a powerful combination for building robust and performant mobile apps. One way to bring these two technologies together is by using the Elm architecture, a design pattern that is based on functional programming principles and can be implemented in F#.

Why use the Elm architecture for building Flutter apps?

The Elm architecture is a great choice for building Flutter apps because it promotes a functional programming style, which is well-suited to building performant and maintainable apps. Additionally, the Elm architecture is designed to make it easy to reason about the state and behaviour of your app, which can help to catch errors early in the development process.

The Elm architecture is based on three core principles:

  1. Model: This represents the state of your app.
  2. View: This defines how the state of your app should be presented to the user.
  3. Update: This defines how the state of your app should change in response to user interactions.

By following these principles, the Elm architecture makes it easy to reason about the state and behaviour of your app, which can help to catch errors early in the development process.

Sounds familiar? Redux and BLOC are just derivatives of Elm architecture.

But as we already know language for writing Flutter apps is Dart. How will we use F# for this? Fable, a F# to JavaScript compiler that allows developers to use F# to build Flutter apps. From its upcoming (in the time of writing this post) 4.0 version it will support F# to Dart compilation. That’s what we’re going to use.

Getting started with F#, Elm architecture and Flutter

Before getting started, you will need to have the Flutter SDK and F# installed on your machine. You can follow the official Flutter installation guide and F# installation guide to set up your development environment.

To create a new Flutter app with the Elm architecture, you can use the Elmish library, which is an implementation of the Elm architecture for F#.

Initial steps

  1. Create new Flutter project. You can do this from IDE with Flutter plugin, my choice will always be Android Studio, or you can do it from terminal with command: flutter create <YOUR_PROJECT_NAME>.
  2. Create new F# project inside Flutter projects that you just created. I like to call it fsharp
  3. Use NuGet to add packages: Fable.Flutter and Elmish.Flutter

You’re all set up, let’s build the app.


What will we build? We will rebuild Flutter’s Hello World counter example just to get or feet wet with Flutter, F# and Fable. In next post I will show you how to build real app, with API calls and local database etc. so stay tuned for that one.

Let’s begin!

  1. We will define our Model/State:
    type Model = { count: int }
    This is record type definition. You can look at this as a data class.
  2. Than we need our Msg/Message/Action:
    type Msg = | Increment | Decrement
    This is discriminating union type. It's sealed class hierarchy, if you will. Those are actions that we allow/support.
  3. And now we need to bridge those two, sending a Msg should update

4. { model with count = model.count + }is how you do copy of record types. Cmd.none comes from Elmish and as you see we are using none so it's nothing to be concerned with at the moment.

5. Now we only miss our View

This code is similar to what you would have in Dart and you can easily understand it but there are couple of things that need explanation of course.

  1. [| |] is Array definition and you are pitting elements in there.
  2. fun () -> Increment |> dispatch. This has two parts to it. fun () -> defines anonymous function, Increment |> despatch is the function body. |>, pipe operator, is the operator that sends thing from it's left to the whatever is on it's right, equivalent code would be fun () -> dispatch Increment
  3. dispatch comes from Elmish and will be provided for you.
  4. We have all the peaces, we just need to bridge the gap with Flutter:

That’s it! You can get full code here

Let’s run it and see what we’ve done. Open the terminal and run those two commands one after another.

  1. dotnet tool restore
  2. dotnet fable watch fsharp -o lib --lang dart

Wait couple of seconds and run the app from your Flutter IDE.

We will stop here. Our feet are wet and we are ready to build more complex app. Upcoming…

Beauty of F# will be apparent when writing business logic so stay tuned.

“Begin at once to live, and count each separate day as a separate life.” Lucius Annaeus Seneca the Younger

Consistency is a crucial element in achieving anything in life. Whether it’s a personal goal, a professional goal, or a habit you’re trying to form, consistency is key to making progress and achieving success.

When you are consistent, you are regularly taking small steps towards your goal, which over time adds up to significant progress. It also helps to establish a routine and make the task at hand a part of your daily life. When something becomes a habit, it requires less mental effort and willpower to continue doing it, making it more likely to stick.

Decide what you want to achieve and start right now. There is o better time to start than now. Stay consistent and track your momentum with best and simplest habit tracker app -> Win the Day, Win the Life.
Stack up those wins and watch your life change in front of your eyes.