One possible approach, instead of iterating over the descendants we store (in axiom-types) a list of all the "primitive" types, keyed by the primitive. We then do something like the inference caching, and make sure the operand is a kind-of the primitive.

I suppose this is exactly like Axiom::Types.infer, except restricted to the built-in "primitive" types, not all the type subclasses.