Stream: ideas

Topic: Matching on open tag unions


view this post on Zulip Karl (Jul 20 2026 at 18:54):

I'm working on a Tailwind-like styling system. The plan is to map to tags margin-2 -> Margin(All, 2), rounded-tl-lg -> Rounded(Tl, Lg) to allow for component tree serialization. Then there'd be a registry of tag handlers that matches the tag and passes the associated data into the handler and the handler does the work to actually make it happen.

I'd like for the tag union to be open but there doesn't seem to be a way to get at the tag or contents in the fallback handler. Did I miss something? Is my design intent off?

view this post on Zulip Norbert Hajagos (Jul 20 2026 at 19:17):

You cannot know the shape of the fallback tag union, that's why it's a fallback. It might be a single payload thing or have 10 different kinds of payloads all with different representation at the hardware level. If you want a "fallback" tag, you should manually define that, kinda like how the Rust std::io::EfforKind has an Other enum variant. For the fallback case, you would probably use a default value (since you want an open union I assume returning an error is not your goal)

view this post on Zulip Karl (Jul 20 2026 at 19:22):

I appreciate the response. I'm used to GC language making shapes a non-concern.

view this post on Zulip Norbert Hajagos (Jul 20 2026 at 19:42):

You're welcome! Open tag unions are weird. They don't really map to oop concepts (if that's your bckground). They aren't the generic object you can defult to. They are used mostly as either an intermediate type to build up a closed union or as an API contract that says "I want to be able to add more variants to this union later without breaking you usage code, so you have to assume there's always a case you're not handling ". There's not really anything you can "do" with the fallback variant, except pass it through or discard.

view this post on Zulip Karl (Jul 20 2026 at 19:43):

My only other experience with them is in OCaml and I didn't spend that much time with the language.

view this post on Zulip Norbert Hajagos (Jul 20 2026 at 19:43):

you have more experience than me then :D

view this post on Zulip Karl (Jul 20 2026 at 19:57):

I was vaguely assuming I could have a list, use the tag id for the lookup and vaguely pass the rest through.

I wonder if it'd be theoretically possible to match you own module's tags on an open union without running into coherence issues. Like it'd match on the closed list and then on the extended closed list and then hit the fallback.

It'd be useful here but I don't know how useful it'd be in general. Aside from monkeypatching in dynamic languages, my only experience with being able to re-open more or less anything is with Clojure's protocols which are basically Rust traits where being able to arbitrarily map somet random Java object type to a particular protocol was periodically useful.

view this post on Zulip Jonathan (Jul 20 2026 at 20:52):

I don't know if it's that useful, but perhaps you could store the string version/some other generic but common representation before parsing alongside? Otherwise I think once it has been parsed into a tag but then effectively discarded into the open part of the union there's not much you can do?

view this post on Zulip Jonathan (Jul 20 2026 at 20:53):

That is, if it's for something like handling unknown cases

view this post on Zulip Jonathan (Jul 20 2026 at 20:54):

Ah my bad, I realise Norbert covered that already


Last updated: Jul 23 2026 at 13:15 UTC