A list of all Elm kernel functions:
Might be useful as a checklist if anyone was to attempt some porting of the Elm kernel to a different platform for example.
A list of all Elm kernel functions:
Might be useful as a checklist if anyone was to attempt some porting of the Elm kernel to a different platform for example.
Well done Rupert! There are some other Elm Kernel functions on elm-explorations/* packages:
I always wondered what happens if we upgrade Elm Kernel functionality from ES3/ES5 to ES6! Since ECMAScript 2015 is widely supported in all major browsers, what are the performance and security optimizations this kind of updating Kernel code achieves?
Having worked quite a bit on Elmās Kernel code, I would say that ES6+ would provide ⦠nothing! Mostly. (Iād love to be proven wrong, though.)
let/const back to var for performance: Using `var` in limited contexts to avoid runtime TDZ checks Ā· Issue #52924 Ā· microsoft/TypeScript Ā· GitHubBut thereās at least one feature from ES6+ that Elm could benefit from: Regex unicode mode! I would love to have that available.
Then thereās the Temporal API that I think would be a great fit for Elm. Iām more excited about Elm using new API:s, than new syntax under the hood.
I have added all the elm-explorations ones to the sheet as well - adds another 115. Most of them in elm-explorations/linear-algebra.
Command used to extract all Kernel function calls from Elm code is:
find . -name "*.elm" -exec grep -hoE 'Elm\.Kernel\.[^[:space:]]+' {} + | sort -u
Itās slightly off-topic, but if someone would like to transpile Elm code, Iāve created bytes decoders for elmi/elmo files : GitHub - Warry/elm-stuff: Decode interfaces (.elmi, i.dat) and objects (.elmo, o.dat) from elm-stuff/
I started but never finished a JS generator based on it, but the kernel part was a nightmare and it kind of discouraged me.
edit: published: Warry/elm-stuff/
Itās great!
It worth a dedicated post and also a more detailed example on how to use it.
EDIT: currently, I implemented this, but Iām not sure what to do with the result ![]()
Improved Modularity and Tree Shaking: ES6 modules (import/export) enable better bundling and tree shaking, reducing bundle size and improving load times. This leads to faster initial page loads and more efficient caching.
Better Memory Management: ES6 features like let and const reduce memory leaks by limiting variable scope compared to ES5ās var.
Async/Await Enhancements: Replacing ES5 callbacks with ES6 async/await improves readability and reduces callback hell, which can indirectly enhance performance by simplifying control flow.
Strict Mode by Default: ES6 modules enforce strict mode automatically, helping catch common coding errors and preventing unsafe actions like accidental global variable creation.
Reduced Global Scope Pollution: ES6 modules encapsulate code, minimizing exposure to global scope and reducing the risk of variable collisions or unintended overrides.
Better Encapsulation: Features like closures promote encapsulation, making it harder for malicious code to tamper with internal logic.
These are some basic improvements over ES5 design which Iām pretty sure about. So, it might be more than ⦠Nothing!
Oh, I replied to a bot. Sneaky! Never mind then.
You asked for some resolution about my initial question, and after 3 days of basic research and a consice answer, you call me a Bot! Thatās not an appropriate behavior in Elm community, Simon ā¦
it opens up meta programming if youāre ambitious. for example, from interfaces you could generate JSON encoders/decoders, or generate typescript type definitions.
Also, I have a problem with a large Elm program which takes a long time and a lot of memory to compile. I think Iāve narrowed the problem down to large .elmi files, which I think is related to the compiler expanding out all record field types. Coincidentally I recently posted about this on my blog: Elm compilation time with large records | Allanderek's blog
So I think I can possibly make use of this package to further inspect the .elmi files and possibly even come up with a plan to reduce the compilation time. Iāve had some success by making some of the record types opaque (because then they are not expanded), but itās surprisingly difficult to figure out which records would be best to opaquify (if Iām allowed to make up verbs). It feels like there will definitely be some objective criteria (and hence some algorithm) which would report the ābestā records to opaquify.
All of this is to say this (Warry/elm-stuff) is a cracking package and I agree with setop it deserves a post of its own.
Great post!
Hereās another thread that also talks about using opaque types to improve compilation speed: Improving Compilation time: Insights from Elm Compiler Internals
I talked to someone at Elm Camp 2025, who said that in a project they work on, they have this convention of having Types.elm files which expose everything, which makes the problem worse since basically all record types are exposed then (and end up in .elmi files). And changing a Types.elm file causes a lot of unrelated files to need re-checking. So that could potentially be something to look into, too.
Great thanks! Iāll look into both of these, I do not have that Types.elm convention, but nevertheless it might be that I can avoid exporting something that I do (though I use elm-review to avoid that).
About a possible improvement by using es6, my friend who was investigating Closures in recursive calls get shadowed, causing stack overflows Ā· Issue #2017 Ā· elm/compiler Ā· GitHub said that he can fix it cleanly if he can use let.
This bug is kind of patched up on GitHub - Zokka-Dev/zokka-compiler: Fork of compiler for Elm, a functional language for reliable webapps. , but on that implementation, I heard it creates closure on every iteration to hide var from outside of the loop created by tail call optimization, which slows down all the tail calls. So, if we can use let, we can avoid creating closures, which should improve performance significantly compared to the patch.
Against our intuition, the problematic part is encoding type aliases to elmi, so, wrapping the blobbed type in just a sum type instead of opaque type also fixes the problem.
Yes, sorry youāre correct, I used the wrong term, I meant custom type/sum type it doesnāt have to be opaque at all. The distinction is really between structural and nominal types, but in Elm custom types are always nominal and record types are structural. A custom type is never expanded to its variants whether or not its variants are hidden within a module which doesnāt export them. The reason for this is that the application of a variant constructor always produces a single nominal custom type (though it may of course be parameterised). Similarly there is no sub-typing in custom types as there is with record types (extensible records). So when type inference compares (unifies) two custom types it only ever needs to consider their names, not the structure of those types since if the names are same then the structure is the same, but thatās not true for record types.
I think there is an interesting avenue to explore in making both custom types and record types structural by default and nominal when made opaque through a module boundary. I discuss this in this blog post.
Late to the party but I second everything @lydell said.
ES5 remains the best compilation target if youāre not writing the JS.
I will at least give him service and write this for a record.
Improved Modularity and Tree Shaking:
not for elm where code generation does all the possible tree-shaking that could happen while itās generating JS. Doing any extra pass has cost for no benefit.
Better Memory Management
JS is garbage collected language. Lifetime of a identifier has nothing to do with lifetime of a memory. Further VM optimizations work based on own analysis and can optimize things out of scope (closure) even if semantically they should be availabe but provably they are not used. var was function scoped while const and let are block scoped. In elm you donāt even have blocks only functions so even if there would be some novel runtime implementation taking this to account I donāt see how this could be any benefical for elm.
Async/Await Enhancements:
Async and await are syntax sugar for generators. Elm doesnāt even use generators because it has different concurrency model. But even than generators are just a form of continuations like callbasks are CSP based in the VM. async await is just syntax suggar. So there are no benefits to generating those to be found.
Strict Mode by Default
Elm doesnāt compile to modules - it has own module system
Reduced Global Scope Pollution:
same as above
Better Encapsulation:
closures are in JS since first version and elm uses those to implement lexical scopes.
Computers are not magic. Buzzwords donāt work as magic spells.
The reason why someone does call someone else a ābotā perhaps can have something to do with someone using LLMs to generate AI slop and then expect real humans with better things to do to spend their time reacting to it. The problem here is the asymmetry of the effort. People are more than willing to help others but also they have better thing than to argue with text generators.
And for the hot take. I prefer to write ES5 even by hand compare to ES6 which covers every concept by layer of obfuscating syntax sugar.