Elm to F# transpiler

You can now transpile elm code to F#.

raylib examplle

I’d love to hear about any issues, surprises, questions, suggestions <3

be aware

  • F#'s compile times are very slow with 5-20+s until any normal project gets executed. Can recommend F# only for when you can get fast iteration in elm itself (like tests in a tooling project).

  • Directly using an existing elm+web/node/… setup will not work out of the box.
    The transpiler spits out pure F# declarations; there is no pre-defined platform and all effects must be handled by your F# code.
    You either need to switch out all cmd/sub/tasks for ports or call relevant elm functions directly from F#.

  • You may need to vendor and edit packages if they transpile with errors (please tell me).

suggestions for other transpile targets?

My goal was speeding up elm tooling (e.g. elm-syntax-format as F# is 50% faster without any changes), enabling game/ui programming and stress-testing elm-syntax-type-infer.

I’m not satisfied yet with speed but mostly compile times so I intend to work on swift/ocaml/your suggestion, except for roc/zig/vlang/odin (too buggy still), rust (complicated), gleam(/haxe) (slow).

Thank you!

16 Likes

I’m curious what makes Odin too buggy? Of those listed in that group it’s by far the most stable and is used commercially.

1 Like

I’m sure it’s fine. I just had a bug in the first 5 minutes of trying it out when defining a recursive type where the compiler hang indefinitely so I just moved on.
Your words make me more confident to give it another shot!

If you want some help, I’m by no means an expert but I’d love to (when I have time)

1 Like

Great to see this. A couple of questions:

  • What did you do with the implementation of Int in F#? Does it map to a 64-bit float and therefore behave the same way that Int does when compiled to javascript, or something else?

  • Did you re-use/write any tests that check the runtime behaviour of Elm code running as F# is the same as Elm code running as Javascript? Curious about what tests might already exist in this area to help with Elm porting projects.

  • “implementation of Int in F#? Does it map to a 64-bit float” → int64. See all type conversions in section how do I use the transpiled output? below the code blocks. Initially I simply used float but folks in slack suggested to use int64 for performance
  • “any tests” → no. The closest thing to that is that I use the transpiled version of elm-syntax-format every day as my formatter and haven’t noticed any discrepancies (same with all the other examples I run less frequently). But tests like that would be cool and I would use them if they existed.

I only really intent do be “reasonably compatible”, so things like runtime errors, NaN as Int for e.g. Char.toCode, int preciseness beyond 53 bits and other “undefined behavior” is not something I have worried about (but I agree the more compatible the better).

I am not sure if the-more-compatible-the-better is necessarily the case. Yes, more compatible it will run a larger % of existing packages without encountering anything that relies on quirks of javascript implementation. On the other hand, the fact that javascript chose to have all numbers be floats wasn’t a very good design choice in the first place, so it seems reasonable to change this on other platforms. Just curious about how you chose to handle these tradeoffs is all.

If you feel like working on elm-syntax-to-gleam again, you might be interested in this:

1 Like