I was working on an online REPL similar to the one in the Elm guide or Online REPL and Mini-IDE but with a focus on using it on my mobile phone when I don’t have internet access.
There is an input area at the bottom where I can enter multiple lines of Elm code. The input field grows as needed, and I tried my best to ensure that it is usually not hidden by the on-screen keyboard on my phone.
With every keystroke, the code is checked and if it is valid I will see the type definition above my input (in the example the declaration elm = "delightful") and the evaluated result below, which is the String “delightful”.
If I press the “run code” button, it will print the entire compiler output, which is useful for finding errors like in the example where a number was supplied insted of the expected String to create a Tree type alias.
The formatting is supplied by the compiler and looks like it would in the console.
I can scroll up to see older code that I entered, can easily copy each down into the input area with one button press or remove it completely.
It also has a button to execute multiple bulk clean-up operations. From a full reset to removing all outdated declarations to only removing errors, I have multiple options there.
For people just starting out, I added an introductory text at the top of the page and a button to insert example code.
Right now it randomly picks one of several examples each with multiple entered expressions.
Result for now?
The REPL UI is built in Elm, and uses ports to communicate with the Elm compiler compiled to WebAssembly. The glue code is written in TypeScript. Both are available on github and I wrote a little about it in this post.
The code is far from ready, but after the Elm-in-Elm compiler rewrites were released in the past weeks, I will check if I can use them instead.
Thanks , I don’t know who else also used the GHC WASM backend to compile the Elm compiler.
But back in June, at least Evan had not yet done so (or planned to). He had some ideas though to reduce the binary size by only compiling one file at a time (which I have not tried yet).
If one starts with the full elm compiler and then only removes what does not compile on wasm32-wasi (like http calls and some file IO), the effort is low and not many changes are needed.
Starting with my own fork, and then with elm-dev and then with Evan’s compiler, always trying to go from the minimal state and then adding more functionality as I got more working was very slow and not worth the effort
I’m also interested in comparisons, but I think for my use cases of REPL and a few hundred lines of Elm code the Elm-in-Elm implementations will be the better fit.
Guesses for comparisons
My first guess is that the wasm compiler will not be smaller than 1M in transferred size and that the Elm implementations will be.
I don’t have much experience with WebAssembly, but for me wasm files were always surprisingly big and getting e.g. rust or c below 0.5M required many tricks. A hello-world from ghc-wasm weighs ~1.2M uncompressed.
About speed:
Evan mentioned that the algorithm for inferring types needs mutable state, so that might slow down the Elm implementations.
But for smallish files, I expect that the overhead for all the string<->binary conversions and executing WASM will favor the Elm implementations. Even if the wasm compiler should be faster on bigger files - or if type annotations are missing.
It might be the first instance of the Elm compiler compiled to WebAssembly, but it’s not the first to run the (actual) Elm compiler in the browser. Ellie used to (but doesn’t anymore) compile the compiler to JS using GHCJS: https://youtu.be/gNWx-zWxUd4?si=UmBE8QAcWDtDIrdR&t=361
Thank you for sharing this link to “Putting the Elm Platform in the Browser”, they definitely did a better job than me, I think my GHCJS builds were around 20M instead of their initial 13.
Does someone happen to know why it was removed?
Or was it more more that it was just never added again after the backend rewrite @luke?
because I was just thinking that I should check whether I can use your code instead of mine for my purposes , so please don’t abandon your project!
I’ll trade you for a bottle of nice local beer (except for Zäpfle).
Now, seriously: I don’t intend to stop or remove the code, but I think for the REPL the wasm build is too big. Even if it might be used similarily to the official guide inside a text-based tour.
But I intend to explore other ways of writing/running Elm code in the browser and want to check out options.
And I’m also interested in translating the error messages and loading several translations into Elm programs would be easier than building multiple wasm binaries.
I don’t have a source, but as far as I remember one of the reasons was that Elm 0.19 started using some low level Haskell thing for performance that wasn’t supported by GHCJS.
I started with a few tests over the past week and don’t want this thread to close while I’m away on the weekend, so I will now post already a naive size comparison
Naive size comparison overview
As an overview, I got these download sizes (gzipped) of the compilers:
~200K for each of the two Elm implementations guida-lang and pithub
That the type signature was inferred and not editable
Maybe some slightly different styling treatment like a bg color and maybe a tiny label could help disambiguate it a little?
That the result at the bottom was auto-generated.
Given the “run code” button immediately to the left seemed to imply to me I would have to manually run it. I’m still left a little unsure what the run code is for! It seems more of a “save this to my history” ?
Also a small Result: label might be nice along with some extra spacing so it’s clear it’s separate from the code (like how I’ve manually added spacing in the screenshot).
Thank you for your feedback, a result label and more spacing would work well, I think.
Maybe it also makes sense to either show the evaluated result (if it returns a single value and not a function) or the inferred type.
Will need to dig into that, because the result is for now just js.