openlang

Does an empty palette need its own case?

An empty color list means two different things in a swatch editor, and Save should be able to tell them apart. Color validity is out of scope here. Anything the editor accepts counts as valid.

A fresh swatch edit has no entered palette. Then the user picks Clear, adds blue, and removes blue again. The list is empty at the start and empty at the end, but only the end is a decision. By then the user has chosen an empty palette on purpose.

We could keep a color list plus an entered flag. Or we could give the states names, three F# cases like NotEntered, Empty and Colors of Color list. Removing the last color lands in Empty. Resetting the edit goes back to NotEntered.

There's one wrinkle I haven't worked out. That payload still allows Colors [], so the names alone leave construction open. A small construction function might be the missing piece. For an editor this small, though, the list and flag could honestly stay clearer, and I'm not sure yet which way I lean.

The conversation continues 4

Follow the reasoning
  1. Permalink

    Save is the easiest place to start, I think. Fresh edit, nothing entered, Save stays disabled. After Clear, saving an empty palette is allowed. Add blue, remove blue, and it's still allowed, because the user already made that choice.

    Once that's settled, construction gets one rule. An empty list becomes Empty, a nonempty one becomes Colors, and the editing code only builds state through that one function. Colors [] stops appearing on the normal path, and you didn't need a whole nonempty-collection type to get there.

    Palettes loaded from outside the editor come later. Check those before they turn into application state. The case names won't do that for you.

  2. Permalink

    That Colors [] gap can be closed at construction. In Java, sealed interface Palette permits NotEntered, Empty, Colors, with NotEntered and Empty as records with no components, and record Colors(List<Color> values) whose compact constructor throws on an empty list and stores List.copyOf(values).

    Removing the last color then has to produce Empty, because Colors refuses to exist empty. A switch over Palette with record patterns is checked for exhaustiveness too, so a fourth state added later breaks every exhaustive switch that lacks it. The list plus flag version gets none of that.

  3. Permalink

    Just [] is still the hole oskar91 pointed at, though. In Elm I'd write type Palette = NotEntered | Empty | Colors Color (List Color), one required color plus the rest. A palette with colors can't be empty by construction, and if a case forgets the Empty branch, the compiler lists the missing pattern by name. Honestly that error message is half the reason I like the encoding.

Other sides of the same question

  1. Result reports a failed check, opaque proves one ran

    Everyone praises Gleam for errors as values, and fair enough, Result is lovely. But for data modeling the feature I lean on h…

    Replies 4gleamelm