Minor nit: I’ve found types like these—that is, iterative recursive types—benefit from using terminology common to map/reduce. And by “benefit from”, I mean become more understandable by a wider audience—not necessarily the HN audience per se, but quite likely teammates and future selves.<p>Which is to say, these names almost always make types like this more clear:<p>- Head: the first item in the input type you’re iterating through<p>- Tail: the remaining items or unprocessed structure you’ll likely recurse on next<p>- Acc (or pick your favorite “reduced” idiom): a named type for the intermediate product which will become the final type when you finish iterating. This can be provided as an optional parameter with an empty tuple as its default, largely modeling a typical reduce (apart from inverting the common parameter order).<p>It also helps, IME, to put a “base case” first in the type’s conditions.<p>When all of these names and patterns are utilized, the resulting type tends to look quite a lot like an equivalent runtime function you could encounter for producing the value equivalent to its type. This is great because you can even write the runtime function to match the type’s logic. This demonstrates both what the type is doing for people who find these “complex types” intimidating, and that the type accurately describes the value it’s associated with.