Using client-side Haskell web frameworks in CodeWorld

Chris Smith
3 min readJun 9, 2020

--

I’ve made another change to make the CodeWorld environment more useful for general Haskell programming.

What?

Here is the calculator from https://reflex-frp.org/tutorial:

Here is the calculator running inside CodeWorld:

You can also use Miso from CodeWorld:

You can even build your own HTML with ghcjs-dom, jsaddle, or even just the JavaScript FFI. For example, here’s how you can incorporate the diagrams library into CodeWorld:

I’d love to add anything else that’s useful. The framework must be usable in an otherwise blank page, so frameworks that expect lost of preexisting HTML, CSS, images, etc. won’t work out so well. If you would like to use CodeWorld with a different client-side web framework or library that meets this description, just leave a comment and let me know, or send a GitHub pull request to modify this file and add it.

Why?

Setting up a development environment with GHCJS can be a real pain. For serious work, nix is emerging as the standard tooling, but nix is the most complex build tool available for Haskell. Building GHCJS with cabal or stack is possible, but the setup takes hours. Entire tooling projects (see Obelisk) have been born out of the goal of helping make it easier to get up and running with a GHCJS client-side web project.

But what if you’re visiting a friend and want to show them what Haskell can do? They don’t have GHC installed, and you don’t want to start your pitch by walking them through an hour of software setup. Or maybe you’re teaching a survey class on different applications of functional programming. Maybe you want to post something to Twitter, or your blog, and let readers tinker and experiment with it easily?

CodeWorld is the answer. Just write code, click Run, and voila! Want to share your code? Just copy and paste the URL and the people you share it with can see, edit, and run their modified versions of your code. Zero installation, no down time.

How?

This was actually a pretty easy change to make, once I realized I should do it. It used to be that the CodeWorld environment ran applications in an HTML page with a giant Canvas, and the codeworld-api package looked up that canvas and drew onto it. After this change, the CodeWorld environment runs applications in a document with an empty body. Any client-side framework, whether it’s codeworld-api, reflex-dom, etc., can add its own elements to the document. The codeworld-api package now dynamically adds its canvas to the document before drawing to it.

There were a few more details to work out. I don’t want the output page to pop up when you’re only running console-mode code in the CodeWorld environment, so there’s a trick with MutationObserver to detect when the running app modifies its own document, and change the parent UI to show it if so.

Implementation details are documented at https://github.com/google/codeworld/issues/1362, if you’re excessively curious.

--

--

Chris Smith
Chris Smith

Written by Chris Smith

Software engineer, volunteer K-12 math and computer science teacher, author of the CodeWorld platform, amateur ring theorist, and Haskell enthusiast.

Responses (1)