I think the main concept introduced here is to hand-write what would be the match expression for each union. I've done similar stuff in languages with no ADT's, but without exhaustiveness checking you're left with co-locating the matcher next to the union type and hoping you remember to update it if anything changes.