# F# for Elm developers

**URL:** <https://discourse.elm-lang.org/t/f-for-elm-developers/9495>\
**Category:** Show and Tell\
**Created:** [November 30, 2023, 11:45am UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495 "2023-11-30T11:45:35Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Laurent](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/laurent/32/5725_2.png) [@Laurent](https://discourse.elm-lang.org/u/Laurent)\
**Post date:** [November 30, 2023, 11:45am UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/1 "2023-11-30T11:45:36Z")

</div>

The [F# syntax](https://learnxinyminutes.com/docs/fsharp/) is very close to the Elm one. Some people actually [moved from Elm to F#](https://dev.to/kspeakman/life-after-elm-what-we-did-4hkp) after Elm v0.19. So I gave F# a try and was surprised by how close you can get to the Elm experience.

I created a little example GitHub repo with typical Elm features:

> **[GitHub - laurentpayot/fsharp-fable-elmish-example: F# Fable Elmish example, with Preact and Vite.](https://github.com/laurentpayot/fsharp-fable-elmish-example#readme)**
>
> F# Fable Elmish example, with Preact and Vite.

The goal of this example is to show how to get typical Elm features (see below) in [F#](https://fsharp.org/). It uses [Fable](https://fable.io/) to transpile F# to JavaScript and [Elmish](https://elmish.github.io/elmish/) to get [The Elm Architecture](https://guide.elm-lang.org/architecture/) (TEA), also known as the Model View Update (MVU) pattern.

Elmish normally uses [React](https://react.dev/) under the hood, but in this example React was seamlessly replaced by [Preact](https://preactjs.com/) to get performances [similar to Elm](https://krausest.github.io/js-framework-benchmark/2022/table_chrome_102.0.5005.61.html), both in term of speed and bundle size.

## Featuring

- Startup flags
- Getting a random number (easy!)
- Routing
- Subscription via a JavaScript custom event
- Foreign Function Interface (FFI) using synchronous and asynchronous functions imported from JavaScript
- JSON decoding
- Keyed list
- Unit tests
- Hot Module Replacement (HMR)
- Debugger (via Redux DevTools)

Note that F# is backed by Microsoft since 2005 and is [updated regularly](https://devblogs.microsoft.com/dotnet/announcing-fsharp-8/), unlike ahem, well some other languages 😏

---

<div class="post-metadata">

**Author:** ![ymtszw](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/ymtszw/32/2360_2.png) [@ymtszw](https://discourse.elm-lang.org/u/ymtszw)\
**Post date:** [November 30, 2023, 12:07pm UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/2 "2023-11-30T12:07:25Z")

</div>

I always tell people to look up [F# for Fun and Profit](https://fsharpforfunandprofit.com/) as a solid knowledge base of statically-typed functional programming. My go-to recommendation.

And yes I’m looking for opportunity to use F# in an actual projects but got too much comfortable in Elm lol

---

<div class="post-metadata">

**Author:** ![Laurent](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/laurent/32/5725_2.png) [@Laurent](https://discourse.elm-lang.org/u/Laurent)\
**Post date:** [November 30, 2023, 8:56pm UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/3 "2023-11-30T20:56:39Z")

</div>

[Essential F#](https://leanpub.com/essential-fsharp) is also very good. For TEA/MVU based apps there is [The Elmish Book](https://zaid-ajaj.github.io/the-elmish-book/#/).

Disclaimer: I didn’t read them 😉

---

<div class="post-metadata">

**Author:** ![perty](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/perty/32/4459_2.png) [@perty](https://discourse.elm-lang.org/u/perty)\
**Post date:** [December 2, 2023, 9:04am UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/4 "2023-12-02T09:04:58Z")

</div>

I have used F# professionally and I liked the book “for fun and profit” plus that F# is the nicest .Net language,

There are however things I didn’t appreciate:

- interop with .Net means you can get null pointers in your code despite the language has no null concept.
- single pass compiler (!) You need to declare things before using them. Haven’t seen a single pass compiler since the 80’s.
- it has not this nice sense of simple and yet complete that Elm has. You sometimes need to reach for something written in C# and the impedance is significant.
- it has this aurora of "designed by Microsoft " over it, hard to describe, the best I can is “paper cuts”. Overall nice idea but annoying things here and there.

Your experience may be different, of course. This is just me.

---

<div class="post-metadata">

**Author:** ![Laurent](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/laurent/32/5725_2.png) [@Laurent](https://discourse.elm-lang.org/u/Laurent)\
**Post date:** [December 4, 2023, 10:45am UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/5 "2023-12-04T10:45:27Z")

</div>

EDIT: The debugger (via Redux DevTools) is now working and it is even better than the Elm one.

---

<div class="post-metadata">

**Author:** ![Laurent](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/laurent/32/5725_2.png) [@Laurent](https://discourse.elm-lang.org/u/Laurent)\
**Post date:** [December 9, 2023, 11:36pm UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/6 "2023-12-09T23:36:16Z")

</div>

> [@perty](#):
>
> You need to declare things before using them.

I think you can fix this with the [`module rec`](https://devblogs.microsoft.com/dotnet/a-peek-into-f-4-1/#mutually-referential-types-and-modules-within-the-same-file) syntax.

---

<div class="post-metadata">

**Author:** ![benjamin-thomas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/benjamin-thomas/32/3869_2.png) [@benjamin-thomas](https://discourse.elm-lang.org/u/benjamin-thomas)\
**Post date:** [December 10, 2023, 3:17pm UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/7 "2023-12-10T15:17:38Z")

</div>

I find having the order of declarations enforced at compile time quite refreshing actually. I find that it makes reading code more predictable/enjoyable.

F# is an interesting language, but I find myself more interested by its ancestor OCaml 🙂

I’ve been playing with an interesting OCaml library, “fmlib\_browser”, that implements TEA. You can find an example here: [tea-playground/ocaml/fmlib/combine-http-requests-parallel/main.ml at e9b893fbdcaf3d08ea05f36f4476c9bbbba59b91 · benjamin-thomas/tea-playground · GitHub](https://github.com/benjamin-thomas/tea-playground/blob/e9b893fbdcaf3d08ea05f36f4476c9bbbba59b91/ocaml/fmlib/combine-http-requests-parallel/main.ml)

It’s not Elm, but feels very close (closer than Elmish IMO).

Regarding Elmish, I find its heavy use of exceptions in `Cmd Msg` a little bit off-putting.

Have you found a good justification for doing so vs returning a Result in an Async wrapper type?

---

<div class="post-metadata">

**Author:** ![Laurent](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/laurent/32/5725_2.png) [@Laurent](https://discourse.elm-lang.org/u/Laurent)\
**Post date:** [December 12, 2023, 1:12pm UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/8 "2023-12-12T13:12:42Z")

</div>

> [@benjamin-thomas](#):
>
> Regarding Elmish, I find its heavy use of exceptions in `Cmd Msg` a little bit off-putting.
> 
> Have you found a good justification for doing so vs returning a Result in an Async wrapper type?

Is [`Cmd.ofAsync`](https://medium.com/@MangelMaxime/my-tips-for-working-with-elmish-ab8d193d52fd#8615) an example of what you mean?

---

<div class="post-metadata">

**Author:** ![benjamin-thomas](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/benjamin-thomas/32/3869_2.png) [@benjamin-thomas](https://discourse.elm-lang.org/u/benjamin-thomas)\
**Post date:** [December 16, 2023, 8:25am UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/9 "2023-12-16T08:25:51Z")

</div>

> [@Laurent](#):
>
> Is [`Cmd.ofAsync`](https://medium.com/@MangelMaxime/my-tips-for-working-with-elmish-ab8d193d52fd#8615) an example of what you mean?

Yes that’s it.

It seems like the framework encourages you to throw exceptions to signal errors. This design decision seems pretty baked-in.

---

<div class="post-metadata">

**Author:** ![Laurent](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/laurent/32/5725_2.png) [@Laurent](https://discourse.elm-lang.org/u/Laurent)\
**Post date:** [December 19, 2023, 9:59am UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/10 "2023-12-19T09:59:34Z")

</div>

There is a [section about this choice in FSFFAP](https://fsharpforfunandprofit.com/posts/exceptions/#should-functions-throw-exceptions-or-return-error-structures). F# handles exceptions because it allows FFI. Elm evacuates the problem by using ports and custom elements. I would need to implement a non-trivial app in F# to be more assertive, but I think you can do the same in F# if you handle JS exceptions on the JS side before sending proper “Result” records to F#. I agree we are spoiled by Elm design choices that enforces cleanliness for us!

---

<div class="post-metadata">

**Author:** ![davedawkins](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/davedawkins/32/5099_2.png) [@davedawkins](https://discourse.elm-lang.org/u/davedawkins)\
**Post date:** [December 22, 2023, 12:44pm UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/11 "2023-12-22T12:44:17Z")

</div>

You’re right that it’s baked-in, and this does steer you into a pattern. I don’t think it would be hard to create say “Cmd.Result.ofAsync” , “Cmd.Either.ofAsync” etc. I hadn’t thought about this before, and may add it into my own project.

---

<div class="post-metadata">

**Author:** ![Laurent](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/laurent/32/5725_2.png) [@Laurent](https://discourse.elm-lang.org/u/Laurent)\
**Post date:** [December 31, 2023, 10:02pm UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/12 "2023-12-31T22:02:30Z")

</div>

By the way I just listened to @rtfeldman’s podcast [episode with the author of F# for fun and profit](https://podcasts.apple.com/us/podcast/f-in-production-with-scott-wlaschin/id1602572955?i=1000594646820), and at minute 18 they start to talk about Result versus exceptions. They confirm that in a “pure Result environment” there is no need for exceptions but as long as you run code that can raise exceptions you have no choice but to handle exceptions. Obvioulsy.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [January 10, 2024, 10:03pm UTC](https://discourse.elm-lang.org/t/f-for-elm-developers/9495/13 "2024-01-10T22:03:27Z")

</div>

Closed on January 10, 2024, 10:03pm UTC

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
