Introducing plzwrk - A Haskell front-end framework

Mike Solomon


14th May 2020

Table of Contents

  • A hello world in plzwrk
  • Composing elements
  • Stateful elements
  • Getting started with plzwrk
  • Thanks

I really like programming in Haskell. Recently, I learned about Asterius, a Haskell-to-WebAssembly compiler. So I thought it'd be fun to create a small frontend library to build websites that are compiled with Asterius.

Voilà plzwrk.

I've used it to build a couple toy websites and I must say the process has been quite delightful. In this article, I'd like to present a brief overview of plzwrk. If you're a frontend developer and interested in Haskell, I hope that you'll give it a try!

A hello world in plzwrk#

Here it is!

Let's unpack what's going on.

On the first line of the main function, we are creating a browser. plzwrk ships with two browser representations - one backed by Asterius (which we use above) - and a mock one that is useful for testing.

On the second line of main, we create our element to be inserted into the DOM. plzwrk has two ways to insert elements into the DOM:

  • hsx, which is similar to jsx.
  • Functions like div and img from Web.Framework.Plzwrk.Tag that correspond to HTML tags (ie div creates a <div></div> tag).

If you've used jsx or templating languages like Nunjucks before, hsx will probably be more comfortable.

The third and last line sends the element and the browser to plzwrk for rendering. Here's how it looks.

Composing elements#

Here's how we can add an element into another element in plzwrk:

This takes our "Hello world!" and repeats it 10 times.

#el{}# tells hsx to expect a list of elements between the curly brackets. hsx currently has four types of Haskell values that it can accept in curly brackets:

  • el is a list of elements.
  • e is a single element.
  • t is a single piece of text, either in the body of an element or as an attribute.
  • c is a callback that one would supply to click or input.

Let's use them all in the example below:

In the lambda function #c{(\e s -> return $ (consoleLogS browser) "clicked")}#, we see two arguments passed to the listener: e is an event and s is the state.

Speaking of state, let's see how plzwrk handles state!

Stateful elements#

All elements that accept arguments from a state are created with hsx' (note the apostrophe) or with a function like div' or img' (again, note the apostrophe).

When it's time to render using plzwrk, we compose elt with a getter from a state that will hydrate name:

You can see the above example live here.

All event listeners in plzwrk return a modified state, and this modified state is then used to update the DOM.

When we click the "Change name" button, the name will change from "Stacey" to "Bob" in the UI.

The pattern above allows elements to declaritively state their dependencies and leave it to the implementation of the state to provide these dependencies. For example, elt accepts any string as a name, and it's only when we call elt <$> _name that we link it to the Person type.

You can see the above example live here.

In the above example, the phrase "You just turned 42. Congrats!" will be printed 42 times.

Both element and bigger are composed with getters from a state. This is similar to the strategy used in Redux with one caveat - instead of passing setters to elements, we pass the entire state to event handlers. This keeps the actual elements pure (i.e. no accidentally making a network call from the DOM construction function) and allows for maximum flexibility in working with the state.

Getting started with plzwrk#

plzwrk uses Asterius as its backend for web development. Compiling an application using plzwrk is no different than compiling an application using ahc-cabal and ahc-dist as described in the Asterius documentation with one caveat. You must use --constraint "plzwrk +plzwrk-enable-asterius" when running ahc-cabal.

A minimal flow is shown below, mostly copied from the Asterius documentation. It assumes that you have a cabal-buildable project in the pwd. Note the use of the --constraint "plzwrk +plzwrk-enable-asterius" flag in the ahc-cabal step:


Thanks for checking out plzwrk! I'm looking forward to seeing what people build with it. If you've built something with plzwrk and would like to show it off in the README, if you would like to see any features or if you spot a bug, please file an issue on GitHub!

Newer postOlder post

Don’t miss the next post!

Absolutely no spam. Unsubscribe anytime.


About usCareersContact