stz pattern matching unions

stz pattern matching unions
Photo by Krista Mangulsone / Unsplash

Currently you define unions in such a way that you can re-interpret the data in another form. This is the class C style union.

pet (union | as-cat: cat, as-dog: dog)

But what if we wanted tagged unions? essentially a type+data?

To be useful we need to be able to pull apart the tagged union and resolve things back to what they actually are. This is, weirdly, called pattern matching.

Let's start by inventing a syntax for a tagged union:

pet (tagged-union | cat, dog)

When we get a pet but we need to know if it's a dog or a cat, that's when we'd check the type information attached to it:

[ my-pet: pet |
  my-pet
    case: cat then: [as-cat | ...],
    case: dog then: [as-dog | ...],
    default: [...]
]

This would require us access to the type information at runtime. There is another approach we could consider. Using compile time polymorphism:

[ my-pet: pet |
  [cat switch | cat: cat | ...]
  [dog switch | dog: dog | ...]
  [any switch | pet: pet | ...]
  pet switch
]

In this case we're defining three blocks that may or may not be closures (and could even by coroutines if that's useful) that have the same name, in this case switch, and then we send that message to the pet.

The compiler knows pet is a tagged-union and will use pattern matching and if necessary doing so at runtime if it needs to tag them in memory. This approach means no new syntax is necessary, but some new syntax might be nice.

We now have / to indicate a Maybe, so we could use + to indicate a tagged-union:

[ pet: dog + cat | ... ]

Sending switch to a pet where every possible expression doesn't exist would result in a compilation error. You could also add the generic version which has a dog + cat parameter as the 'default'.

We can also wrap this up in a may be such that getting a pet from the pet store is only acceptable if you get a cat or a dog. If you get a bird then instead you would get a wrong-pet error:

[ pet: (dog + case)? | ... ]