Making a case for record extension in Elm

For the beloved Elm.

Builder pattern for UI in Elm

Context

A long while back, Elm let you do this:

You can no longer do this. The feature was removed because

  1. Evan didn't see compelling uses of this feature while it existed, "it got crazy pretty quickly"
  2. It made it easier to speed up performance in compiled Elm (as JS)

More context is available in:

  1. This 2016 discussion
  2. This quite angry essay

I don't think the essay does a great job of providing a compelling use case. The author seems to really just want to be able to write custom deriving code (for the ultimate sake of having a generic Dict that works on custom types for keys and values), by adding available methods to an object itself by using record extension (in the style of Scrap Your Type Classes, which in my opinion, is a good reason to do without type classes).

This page you're reading right now is my attempt to paint more clear use cases.

Use cases

1. UI element libraries

Concretely: allowing record extension would allow UI libraries to narrow the ways they expect users to customise their props.
Abstractly: allowing record extension allows API authors to narrow the way users can configure their exposed types.

Let's follow the concrete use case and your mind can fill in the abstract one later.

I am abstracting UI code in Elm. In particular, I want to produce modular stateful form components that I can easily plug into my forms. That is, I want to wire component state and messages such that it's impossible for:

Woah, I'm confused here. I need a simple example of the builder pattern, actually.

Using Elm's Html msg type is a bit limiting, because if my UI library code produces something prewiredInput, then at best, a user can wrap it inside their own div [customAttrs] [preWiredInput]. What if I want to produce a pre-wired