Run **native** Elm on your server and your terminal! Yes, native!

module Hello exposing (main)

main : String
main =
    "👋"
$ run make -o hello CLI/Hello.elm

$ ./hello
"👋"

:waving_hand:” friends!

It’s finally here: a true native Elm experience we’ve all wished for! elm-run will run your Elm on the server and on your CLI, in your TUI programs and in your games, unspoiled! No more of that ugly JavaScript duck tape we had to do so far.

After exactly six months of nonstop development, behold the first beta version!

What is it exactly?

It’s a runtime the same way Node.js is for JavaScript code: you compile your Elm to assembly code and it either executes it directly or produces true native OS binaries, like a C compiler would. Runs on macOS, Linux, and Windows.

┌───────────┐                                                                                    
│           │─┐                                                                                  
│elm source │ │┐      ┌─────────────┐     ┌─────────────┐       ┌────────────┐     ┌────────────┐
│           │ ││      │             │     │             │       │            │     │            │
└───────────┘ │├─────►│elm compiler ├────►│   elm ir    ├──────►│ js codegen ├────►│  browser   │
 └────────────┘│      │             │     │             │       │            │     │            │
   └───────────┘      └─────────────┘     └──────┬──────┘       └────────────┘     └────────────┘
                                                 │                                               
                                                 ▼                                               
                                           ┌─────────────┐       ┌────────────┐     ┌────────────┐
                                           │             │       │            │     │            │
                                           │run optimizer├──────►│  codegen   ├────►│ runtime/OS │
                                           │             │       │            │     │            │
                                           └─────────────┘       └────────────┘     └────────────┘

In short, you use the exact same Elm you know and love, and elm-run runs it for you on your computer + server, fast, right on the OS, just like cat or grep or other utilities. It runs all existing published packages. (Okay, maybe not those made for the browser).

But it also runs Elm in a fast, native 3D game engine: from your Elm program straight to the GPU!
No weird transpilations, “bindings,” and whatnot! No contorted “diagram languages.” Just Elm the way you already write it.

elm-run is not an experiment: it’s a proper product aimed at professionals. And for enthusiasts, with elm-game. Everyone benefits, but the features are chosen for pro use, informed by my professional experience (SaaS, e-commerce, e-mail, databases).

Is it really native?

Yes! The real thing! No piggybacking on Node, no “… well, actually it’s just lipstick on JavaScript.”. No transpiling to some other source for yet some other compiler to process, no llvm. (Believe it or not, llvm produces 15% slower VM run loop than the one we ship! Seriously). So, it’s just Elm and your computer.

No, it’s not WebAssembly. elm-run does its own VM + codegen + native emission. elm-run is written in itself, without dependencies: it compiles Elm intermediate language, optimizes for native, emits assembly code for macOS, Linux, and Windows with Intel and Arm processors. It’s not a “dynamic language.” It’s ahead-of-time compiled and optimized bytecode. It also compiles down to straightline executable machine code!

It’s open source, like Elm, and it’s not some “language inspired by Elm:” it runs the stock Elm compiler, unchanged and will never ever attempt to change Elm.

Why?

I really enjoy writing programs in Elm. It’s a fun and pleasant language. In my business, I have needs beyond the browser, and jumping between the pleasant Elm experience and other languages suitable for backend/db development caused me unpleasant cognitive dissonance for years. And I just can’t swallow all this JS/node business. Never could.

Add to that my growing concern with all these security issues we’re seeing with the supply chain, a chance idea (I needed an interpreter for elm-wrap), and well, here we are: “:waving_hand:”.

A proper solution deserves dedication and focus, so I decided to invest this year in solving my cognitive dissonance and lay the groundwork for reimagining the way we write, run, and share code. Put my business aside, and dove into this for days and days, without pause.

The outcome is elm-run, the runtime. Behold! An unapologetically ambitious product that aims to elevate Elm in your life and your work!

Use it today

Today I’m inviting you to beta test:

  • elm-run compiler, the thing that takes Elm compiler’s output and produces the bytecode / native outputs.
  • run orchestrator tool that lets you manage your native Elm coding experience.

The runtimes (things that execute those compiled programs):

  • Command line host-run that runs CLI programs and TUI programs;
  • host-worker, a web server with integrated async/multithreaded Elm runtimes, automatic TLS, etc.;
  • and elm-game, the 2D/3D game engine. :backhand_index_pointing_left: My new favorite!

I’ve been enjoying all these things for a while now: writing code generators for the virtual machine and standard library, CLI utilities, profiler, debugger, etc. It’s fun! It even runs on elm-wrap cloud in production! However modest that may be, we can say it’s already a “production runtime,” even though we’ve still got a ways to go before a 1.0 release.

What do these do?

Cli + TUI

The CLI runtime is the workhorse, the daily driver.

So far we had to jump through hoops with various JS runtimes, have Ports blues, and spend most of our time writing this horrible plumbing instead of being productive with Elm!

elm-run changes that forever!

Write your normal headless Elm like you are used to, run it and that’s it! It will run both simple and complex workloads, async or multi-threaded (Actors! Yay!), fetch stuff with HTTP, TCP, or sockets. It knows all the advanced things one would expect from a proper “server-grade runtime.” (protip: Nonchalantly throw around terms like shared memory at team meetings).

CLI runtime is powerful and fast. It’s tighly integrated with Elm: it knows Elm in the async reactor core! It’s made for Elm and for TEA and nothing else! No compromise! run utility runs on that one, so does the compiler. It also works as a proper OS process on the server, like your job workers. In fact, it’s great on the server! With the bytecode distribution model, it’s way safer than shipping just some random llvm-produced executables. It has all the goodies that a pro ops team
would expect: SFI, auditing, capabilities, …

Programming is exactly how you’d imagine. It has the run loop and init->update->subscriptions cycle. It can do one-shot batch mode or run infinitely as an OS process.

Here’s the grep example from The Book of elm-run (that you’ll get in the beta toolkit):

It also knows how to render TUIs for you. Natively integrated into your OS, with a fast view engine. Just like all those other TUI toolkits. Except this one feels like home:


import Terminal.Tui.View as V

...

bg : ( Int, Int, Int ) -> V.Attribute msg
bg ( r, g, b ) =
    V.bgRgb r g b

view : Model -> View Msg
view model =
    let
        cols =
            max 1 model.windowSize.cols

        rows =
            max 1 model.windowSize.rows

        bodyRows =
            max 1 (rows - 2)
    in
    V.column
        [ V.widthCells cols
        , V.heightCells rows
        , bg Theme.bg
        , fg Theme.text
        ]
        [ topBar cols model
        , dashboard cols bodyRows model
        , footerStatus cols model
        ]


main : Terminal.Program Model Msg
main =
    Terminal.program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

I find it practical to have a small TUI app around to monitor the production db of my wife’s online shop. But I also use little TUI programs for overseeing tests, matrix tests, and a bunch of other things like analyzing code the compiler produced.

Actors

All hosts run a fully async reactor loop (written in C targetting native async idioms of each OS). Parallelism is through Actors that are nothing more than “mini-TEA” programs themselves:

Actor.spawn
    (Actor.program
        { init = workerInit
        , update = workerUpdate
        , subscriptions = workerSubscriptions
        }
        { replyTo = mainPid }
    )

Simple and fun! Familiar and powerful! Super useful for non-blocking UIs in TUI and elm-game.

There are also simpler “Type A” actors that are just Tasks executed on their own thread.

Web server

A web server that serves async web requests exactly how you’d imagine: subscribe to a request and process it async! Or maybe you want to process a web socket or a TCP connection. Familiar and boring in a good way!

This is my test corpus fixture, httpbin style:

main : Worker.Program Model Msg
main =
    Worker.program
        { init = init
        , update = update
        , subscriptions = subscriptions
        }

subscriptions : Model -> Sub Msg
subscriptions model =
    Http.onRequest GotRequest


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotRequest req ->
            if req.path == "/quit" then
                ( model, Worker.exit 0 )

            else if req.path == "/echo" then
                -- Echo the request body verbatim. Used by HttpPostBodyTest /
                -- HttpPutBodyTest to verify the client forwarded the body.
                ( model
                , Http.respond
                    { connectionId = req.connectionId
                    , streamId = req.streamId
                    , status = 200
                    , contentType = "text/plain"
                    , body = req.method ++ " " ++ String.fromInt (String.length req.body) ++ " " ++ req.body
                    }
                )
            ...

It runs the same VM as the other hosts, so it can do all the same things like spawn actors, OS processes, etc. It also happens to be the industrial-strength, hyperscaler-grade web server.

The Game

And then there’s elm-game, my new favorite! Hadn’t looked at it for months, thinking I’ll release by 0.6.0 per the roadmap. But then @MartinS asked if it can mix audio in pure Elm and stream it. Hmm…

So yes, pure audio mixing in Elm and just stream it to the OS: Sound.queuePcm { sampleRate = outputSampleRate, channels = 2, samples = samples } . Look ma! No ports!

Haven’t done anything but since Friday, almost missed the release deadline today! Disaster! But haven’t had this much fun in a while!

Always been a fan of Lua LÖve, even tried making a few small games with my son way back when. I’d patiently explain to him, “Son, every engine always has an init phase, the run loop, and the frame renderer. And it processes your stick and keyboard inputs when they come. Nothing much to it: init, update, view, pick up input events.”

Time passed, he studies Game Design. Early on into elm-run, he’s working next to me in the office, struggling with his assignment in Unreal. That beast might be the “cutting edge”, “pro” thing, but wow does it kill any joy! You have an idea for a quickie little mechanic to try out, but that beast just hammers you in with all the endless menus and weird UI stuff and its C++ that isn’t! You’re like, never mind.

Hmm, :thinking:… init, view, update, subscribe… native Elm on my screen…

It’s a time stealing monster friends! It’s so addictive, I’m afraid to release it before we test the “pro” runtimes! I’m afraid you’ll ignore the cool web server and the CLI! (I keep convincing myself, “it’s good for perf testing.”)

It’s a decent little engine, in the spirit of Elm. Does all the usual 2D and 3D stuff; and audio without Ports! Obviously, multithreaded through Actors. And it’s just Elm, packages and all. Not being much of a game maker, I’m hoping all you good people will make it great! And make great games! Elm game jams! Yay!!!

It’s a really funny feeling to write Markdown in immediate mode in Elm, just blitting pixels to the screen (and the GPU) and laying things out. Didn’t expect it to feel so liberating without Html and virtual dom!

Welcome to Native!

So friends, we start today! This early beta is by invitation. Not because I don’t love you (I do, :heart_hands:). It’s just that I have limited mental bandwidth, and have been writing this code for so long that I simply don’t hit the bad corners anymore. Yet almost everyone that tried it ran into a new problem I haven’t seen before within hours: either under-optimized parts or mysterious compile errors due to code shapes I never thought of trying, or stacks of packages I didn’t know existed!

Native here truly means that: three platforms, two architectures. All the stuff that V8 and the browser do for Elm in the Browser, elm-run has to do by itself. And there’s a LOT of it! No single human can hope to test that and find all the rough spots.

So, if you don’t mind, I’d like you to tell me you’re interested at the beta page by sending some info about your hardware, and then I’ll start contacting you, subject to how quickly I can turn around any issues we find, and your declared tolerance for things that break.

The goal is to onboard everyone rapido! I’d love to start with a good mix of macOS/Linux/Windows early adopters, and then expand in order of improvements and my ability to support everyone.

I’m more of a relationship person, preferring to work one-on-one with interested people. If you’re trying it, means you invested your time into something I did, so at least I can pay you back with attention and support.

The smoother things get, the more people I can onboard. I gather a month, maybe two, should do until we start seeing really stable products. And hopefully some games!

This is the first time for me to release such a massive and ambitious developer product. I know for a fact that for most of you it is a waste of time have to try something only for it not to meet your expectations, and then you have to wait for things to improve. Kills the fun. I’d rather you have a great start. Some people, on the other hand, are tolerant to these things. So I’m hoping we have a good mix here!

I’m very much looking forward to Elm Camp to have productive and informed discussions and talk ideas! I’m DYING to see the stuff you’ll do.

The Conversation

I’ll provide communication details in the invitation (issue reporting, binary updates, etc). elm-talk will likely be the only channel for bug reporting and technical discussions. It’s almost ready to go live! Just a bit more backend work.

In the meantime, please ask questions here in public, or contact me through this discourse, on Slack, Discord, phone, whatever works for you! My door is always open and I’m excited to talk!

I’ll post occasional updates here and on the site as well.

Mandatory Answers

  • Is this open source?
    Yes, bona-fide, BSD licensed open source. Just like Elm itself.
    Even comes with a book of internals, so you can learn stuff if you’re into low level things. But the source for the runtime and compiler is not yet public. It will be, but only after 1.0.

  • What’s it made in? Did you use hip language/tool X?
    No.
    I started on December 1 '25 by writing a small C interpreter for Elm IR, slowly getting it just fast enough to run larger Elm programs, and then moved as much as I could to Elm.
    A career in tech taught me that the best and most sustainable products come from making your own cake all the way. No transpiling to X, no llvm backend, no some thing random people on the internet tell you is magically fast because is written in some equally magical language that some other random people say that is fast because, well, some rando in some big brand company tried it once and tweeted about it.
    Friend, this cake has only three ingredients: Elm, assembly (written in Elm), C. More and more Elm/assembly, less and less C.

  • Yes. It builds on Linux, macOS and Windows.
    macOS is my platform so that’s the most tested. I wrote most things cross-platform and am now building on all platforms daily. And Elm bytecode tools obviously run cross-platform. One nice benefit of choosing that architecture. Saves a lot of build minutes!

  • Is it fast? Yes, decent. But let’s revisit this question after v0.5.0.
    The VM already executes around the same speed as WASM3 interpreter on a few synthetic WASM tests I could find. That target worked as predicted! Not very meaningful for judging the speed of your programs, but at least the base is ok. The Book guides you in writing a small CLI program that goes faster than system utilities like grep.
    There’s also a very very fast compiler to native executables that runs more and more programs on the test corpus. I don’t know the final speed yet, but writing all that assembly is paying off! Let’s wait for 0.5.0.

  • Wut? A “VM”?! That’s slow! Cool kids use llvm!
    A purpose-built runtime with tight loops and ops in handwritten assembly is the right choice for all the productive scenarios Elm is suitable for. You can’t do secure distribution with native binaries without cooperation of OS gatekeepers. Ask any pro ops person: small, audited runtime with SFI and capabilities + inspectable deliverables; or an opaque executable compiled with some rando’s llm’d llvm that won’t be buildable with the next version of llvm?
    elm-run aims at pro use. It’s fast enough. And as mentioned, llvm/mlir/whatevaIR are not made for functional languages. No matter what they sell you. A runtime and compiler that know the language intimately, made for that language–in that language–are an infinitely larger long-term win over chasing “native compilation” by depending on some third party’s vision of what that means.
    If I may say so myself, elm-run is an elegant and enjoyable product–second only to Elm itself!-- so you won’t mind waiting a few more months for insta-compiled native. (And you won’t have to recompile whatever you already shipped).

  • Can I run it in production?!
    I do! It’s still beta, though, and it is beta exactly so you run it in prod and help discover any warts! But I don’t know what you do. Let’s talk.

  • Is this it?
    No. This is just table stakes to do all the exciting stuff. I’m looking forward to your help; the minute this product is out, I have an insane pipeline of stuff to release. Elm is truly a productivity language! And now unchained from the browser,… wow!

Once you pick this up, I hope you’ll be as excited as I am!


In a most embarrassing turn of fate, I misconfigured a backend and the beta page can’t submit applications! Super embarrassing! Blame elm-game! Will provision a new server soon with a clean setup, but safer to say that the page goes up tomorrow. Contact me directly in the meantime! Don’t hesitate.

The form now works if that’s your preferred way. Thank you all for great interest! :heart_hands:

48 Likes

Hey folks :waving_hand:

I’m adding to the announcement that I have been working with Damir on rewriting elm-review with elm-run. The intent is to have elm-review rewritten fully in Elm, and hopefully to crank out better performance. Also, going to native would allow running the tool without Node.js and npm, allowing it to be installed in a standalone way or with elm-tooling, and distances us from the daily security problems in the npm ecosystem.

I’m one of the few who’s hit the bad corners (over and over again) so I have been giving Damir a lot of extra work :grin:
I’m not yet at the point where I can tell you whether it’s faster with elm-run or with Node.js, but I hope to give more updates soon!

However, the rewrite to Elm has been very pleasurable. It’s simply the language and experience that I have come to love over these years, mostly with more access to Tasks :grin:

Going from Node.js to 100% Elm for all the CLI work has been a lot of rewrite work (because it accumulated a lot of features over the years) but really fun.

And the result is so much nicer than before. Being able to rely on Tasks instead of JS ports reduces the amount of state one needs to manage a lot. The whole architecture feels a lot nicer, it feels a lot more maintainable, and I’ve uncovered a number of edge cases and problems that weren’t handled properly in JS but that the Elm compiler caught and asks me to handle.
(Un?)Surprisingly, none of that was caught when I was adding TypeScript to the codebase… :disappointed_face:

I’ve definitely enjoyed working with elm-run so far :blush:

24 Likes

Curious about this comment - are you writing custom Tasks for elm-review ? Or do you just mean that you have more IO Tasks available from the elm-run platform ?

2 Likes

I have access to more IO Tasks from the elm-run platform, specifically around access to the file system or spawning commands which are not there in plain Elm, and that I had to previously use ports for.

5 Likes

Very excited to play around with this! Congrats on the initial release :tada:

4 Likes

:exploding_head: :smiley: :exploding_head:

My mind is running through so many things this empowers.

:thinking: :exploding_head: :thinking:

Excited to build on this. Amazing. Thank you. :folded_hands:

5 Likes

Friends! The beta form is live if you prefer it over contacting me directly. Ping me through the form or here or on Slack. People are contacting me in all these ways, so whatever works best for you.

Regret again the delay!

4 Likes

Man, this looks so cool, can’t wait to try it!

Is there a place where we’ll be able to follow development and discussions as they happen?

As a user, I’d like to be able to, eventually, understand my programs from the high level Elm representation, to the lower level stuff. Obviously this takes a while to master, but having a book of internals sounds very compelling to me, to avoid having a “black box” feeling.

One thing that pops to mind is OCaml having a “rewind” step debugger (works only on byte code output though). I believe some variations of this idea exist even with certain C debuggers, but limited due to unrestricted IO. I don’t know what you have in mind there, but it sounds like this could be quite the differentiating factor (time travel possible maybe?).

Happy to see where this goes, and I hope you can find a way to monetize so that you can keep working on this comfortably.

4 Likes

This sounds amazing! We at Feedback.one would looove to try it out!

3 Likes

There is about a billion things I could use this for in djelm for running elm on a django server. Damn fine work my man!

2 Likes

This sounds very interesting indeed, thank you for the work. However, I do have to ask. @damir, is this project vibe-coded?

2 Likes

Wish I had some time to vibe in these past months!

No. This is not vibe coded, in any sense of that phrase.

This is an original, premeditated product, with clear positioning, clear objectives, tech choices and the roadmap I obsessed over for weeks before I committed to it, and then published. There are witnesses here that can confirm that part for you.

In short, the exact opposite of these vibe-coded things we’re seeing: high-on-slop-fumes overhyped desperate-attention-seeking vague claims of “innovative, novel, unique;” lack of clear direction; no premeditated objectives and positioning; no coherent tech strategy in line with stated objectives. Impenetrable mountains of slop in languages and tools decided by the machines.

FWIW, at this scale of code and effort, I don’t think these tools can deliver the goods without product discipline.

Conversely, at this scale of code, effort, and investment, I believe it would be irresponsible not to use all the tools we have at our disposal.

Since you had to ask, I was obliged to answer.

Now I have to ask: could we please not continue this line of conversation, and keep the questions (and praise!) about elm-run?

4 Likes

I can’t even imagine the amount of effort and skill that went into this. Crazy work, thank you!

3 Likes

Amazing!!! Inspiring! Impressive! Thank you for this work.

Elm Community

What impact does this have on the Elm community in terms of packages and training materials? I love the idea of being able to do so much more without actually changing the language and I appreciate

How does this work in practice? If there are packages that are only available on this platform then doesn’t that fragment Elm a little and so change Elm? Obviously this all hinges on what you consider to be “Elm”: a language with a type system and compiler, a philosophy, a package ecosystem, a community, etc.. Right now Elm refers to all of that.

Do you see elm-run impacting that unity in any way? If so what are your thoughts?

Package Discovery

How will we organize and discover packages that work in the browser, as a CLI, as a native server, as a game? Do you envision organizing these things by platform or by granular capabilities or…?

I just ran over and spent 5 minutes looking at some Gren Packages and their search interface.

  • It looks like their libraries declare a platform of “node” | “browser” | “common”. The gren-tui package configuration has “node”, the gren-hex has “common”, and the browser module obviously has browser.
  • However, when I look around Gren’s package search interface I see a fairly significant gap: I cannot tell which platform a package supports from the search page. Maybe someone familiar with Gren can explain it better or maybe I am just missing something obvious. I would find it really valuable to be able to quickly and immediately discover things that can work in different contexts.

NodeJS?

It looks like we get a native server option that can receive Http requests and respond without ports. Great!!!

What about those wishing to run their server on NodeJS in order to use existing NodeJS libraries? Or perhaps they prefer NodeJS as a platform for other reasons? Is it simply the case that you would only use elm-run if you wanted a native server? That sounds like a good and distinct product position and I am probably speaking to an edge case, but it seems that offering a NodeJS solution that removed the need for ports for Http handling could be useful; benefiting from normalized Apis around Http request handling. Or maybe not worth the complexity. :man_shrugging:

Super Awesome

The above is intended only as light inquiry. To reiterate: Awesome work!!! Reading your post gave me goosebumps and put a huge smile on my face.

1 Like

We already have this and I don’t feel that it’s impacted the community in a negative way. elm-pages 12.3.0 isn’t really usable outside of building an elm-pages app or script. There’s also a variety of packages that require pairing with a JS script for introducing things like web components, e.g. elm-canvas 5.0.0.

Separately, the vast majority of Elm code is pure functions. The thing that differentiates one Elm platform from another is how it handles effects. In this case, elm-run requires capability arguments for a lot effect related functions, so a package which has the type

foo : Fs.Stdin -> ??? -> ???

can only be used if you’re in the context of an app that provides Fs.Stdin as a type. This is very similar to how browser navigation works in Elm today, that requires a Browser.Navigation.Key which today we only get from browser 1.0.2 and elm-program-test 4.0.1 (maybe 1 or 2 other pacakges).

Like I could see a future where elm-ui renames Element.layout to Element.toHtml, and adds Element.toTui and Element.toView which respectively return Terminal.Tui.View.View msg and some native graphical type. This would make elm-ui 99% just Elm code and then there’d be 3 platform specific functions for converting to the appropriate platform type.


Just my own opinions/thought

2 Likes

True.

On the one hand, I get the larger point that the question of platform reduces away to module dependencies because platform capabilities are only exposed through module Apis. There are islands of libraries that depend on elm-ui and only work in that sub ecosystem. It can be viewed as just another species of tree analysis. Totally. Very elegant and all. One can say: "Let’s not solve this as a problem of discovering ‘platform’ things but rather let’s extend our package search system to show packages with a common transitive dependency i.e. show me only packages that require X and which don’t require Y.

On the other hand, I think that the size and nature of elm-run’s differentiation is more significant and could therefore justify a commensurate solution. This is really a question of the Fairbairn threshold. Given it can be viewed as a dependency tree problem do we simply ask users to use that general set of primitives to solve their problem? Or is a specific facade justified? Of course, it can be both.

I am really glad to hear that you don’t feel this is a threat to the uniformity of the community (by the way, I am very happy Lamdera user and that is itself a small platform). I asked because this community is generally very strongly in favor of keeping things the Elm way and I was hoping that this wouldn’t create a sense of fragmentation. One thing I detest about TypeScript is that it is so balkanized that it drives combinatorial explosions in configuration complexity. You have CommonJS, AMD, UMD, ESNext. You have different module resolutions. The command line compiler disagrees often with the IDE language service which disagrees often with the run-time behavior. Then there are tools to tie those things together and make them whole, but then those tools don’t work together and you need tools to connect those tools to the other tools… and it becomes the old Now there are 15 competing standards joke. The point being that I am very slightly suspicious of anything that could push Elm off that cliff. That said - we are nowhere near the edge at this point.

@john_s good questions!

You answered it yourself: being able to do so much more without changing the language. That’s the goal. Of course, “doing so much more” also means “not doing the exact same thing,” so now we can split hairs over how that Venn diagram looks like.

A web server programmed exactly like Elm with init, update, subscription and exact same idioms we learned in Elm in the Browser is still Elm. Unchanged. Yes, it changes what you do: you are programming a web server, a different beast from the browser. You’re writing Http.respond instead of Http.request. But you’re still doing web, still using exact same compiler that will let you write exact same language and nothing more.

If you did 10 hours of Elm for the Browser a week, and now you’re down to five and the other five programming the web server, then yeah, you’re splitting your time, and your vision of “what can this language do for me” certainly changed. But you’re still doing 10 hours of Elm programming.

Or suddenly you’re doing 20 hours, playing with Elm Game 'cause it’s so much fun! Means I did my job and drove up cumulative usage hours of Elm!

I decided the compiler is the yardstick for “the same thing.” The compiler guarantees it’s still the same language. That’s why I went to insane lengths to keep using the same compiler. Probably 1/3 of total effort went into ensuring that I can deliver a usable runtime over that unchanged compiler. Could have rewritten it twice in that time! Would have been way easier. But it wouldn’t have been the same thing. In my product strategy, everything up and to the left of that “run optimizer” in the diagram is not for debate. Unquestionable.

It’s a deliberate move, a very expensive signal that I’m not here to fragment the community; only enlarge.

The package stuff you speak of is a non-issue, really. My intent with the whole distribution business goes way beyond elm-run described here. Hopefully the few here who read the draft chapter of the web server book saw the first hint. You maybe don’t know that I started working on elm-wrap before I had the idea for elm-run. Like here, it extends what you can do without taking away from what you could do. Software distribution is my deep concern, and I delivered so far maybe 15% of the vision. With all this stuff coming up, I don’t think you’ll be concerned about “package fragmentation cliff.”

I started writing about my strategy to prevent balkanization, but let’s leave that for another post. You won’t believe me, anyway.

"🙂" Keep on smiling!

1 Like

In this article linked from the most recent Elm News Letter:

It says:

the “host” concept the authors now call a bit of a kludge they’re planning to tear out

I think what he is talking about here, the “host” concept, is this capability argument (Fs.Stdin), but a bit unsure.

Anway, what I wanted to ask is, do you plan to keep this for the long term ? Or will it as cekrem claims, be ripped out and replaced with some other mechanism to enable “capabilities”, such as package tagging for example ? Would keep the IO APIs cleaner.

I think Browser.Navigation - browser 1.0.2 is an interesting example/test case. The top half of the functions in the module can only be run from within Browser.application, while the bottom half can be run from anywhere. There’s nothing preventing Browser.Navigation.load from being called from within Platform.worker. If that app is running from within Node, that function call makes no sense!

So Browser.Navigation already demonstrates both sides of the situation, both with and without a capabilities approach.

I wonder how else this can be accomplished, both from an academic perspective and practical, the restricting of functions to within a particular program.

My personal take, right now, is that the passing of a capability/key is very explicit, which feels very Elm-ish. It does require extra work, but it makes it very clear about what is happening. As I’ve been playing for the past week, I’ve been doing a lot of acquiring/checking presence of appropriate capabilities and then passing them around. Right now that means passing around a lot of arguments.

I’ve also learned from changes @miniBill has made to elm-open-api-cli over the years (specifically the CliMonad a) as well as Elm Land changes and the work @jfmengels has been doing with the elm-review refactor, and I can very much see myself refactoring away from rudimentary Task e a and the like to something specific to each app. I can see capabilities working with with this style of change.

And I think I’m starting to ramble a bit so I’ll leave it at that.

One way it could be accomplished could be by tagging packages with capabilities. But this would mean they are course grained at the package level.

So for your Fs example, suppose the package elm-run/file-system is tagged “fs” - that would mean it supplies or requires the filesystem capability. Then I write some new package rupert/stuff that does some stuff with files, and I have to tag it “fs” in order to consume elm-run/file-system, which in turn means that if you want to use my package, you also need the “fs” tag. So any application built on rupert/stuff and transitively on elm-run/file-system needs to be tagged “fs” and that would be what unlocks the capability and lets you use it.

But I also notice in your example you used the capability key “Fs.Stdin” which suggests to me that these capabilities are intended to be more fine-grained than the package level.

This reminds me of the Java security properties mechanism: The Security Properties File - which lets you permit/deny capabilities to the platform, and proofs can be extracted from bytecode that the properties cannot be violated.

Which suggests another way of doing it - to not explicitly pass capability keys, but to check bytecode against the local settings. If a Task attempts to do something it is not permitted to, crash/fail/ignore.