abstract type Animal end
abstract type Dog <: Animal end
Let’s say that in my package Zoo I define two new types:
using Barnyard
abstract type Zebra <: Animal end
abstract type Lizard <: Animal end
But, now I want certain method to apply to Zebra and Dog while a different one should apply to types such as Lizard. I want an intervening type Mammal that sits above both Zebra and Dog and below Animal. (Also maybe a Reptile type for Lizard to go under, but that’s easy.)
Let’s suppose the maintainers of Barnyard reject my PR for some reason, and I don’t want to maintain a hard fork. Is there a way to inject an intermediate level into the type hierarchy from outside the package? It seems like it is not possible:
using Barnyard
abstract type Mammal <: Animal end
abstract type Zebra <: Mammal end
abstract type Dog <: Mammal end
The last line here fails with:
ERROR: invalid redefinition of constant Dog
I suppose I could use Mammal = Union(Dog,Zebra) but this seems not very sustainable.
You can’t redefine an existing type in another package, it’s not a thing. You need to use holy traits instead. You can even do that with existing abstract types, which could be something like:
I see. I didn’t intend to redefine the type, only to add new information about how the types relate. But, it looks like this is related to the discussion about multiple inheritance. I’m not actually interested in multiple inheritance in this case (turning the type tree into a type lattice), just in ‘stretching’ the existing type tree by interposing a new node that I can stick new branches onto. But, if one were able to declare new supertypes after the fact, it would (in general) allow to create multiple inheritance, which is apparently a difficult feature to implement with multiple dispatch & hasn’t been done yet (might never be done). I’m curious if this simpler case would be easier to implement than the general case, but it’s probably not trivial either.
Thanks for the info about Holy traits. I think this probably good enough for what I am doing.
I imagine it would cause hell for method dispatch and code caching if you could insert types into the hierarchy at will, anywhere in the ecosystem. But that’s a guess.
I’m leaning toward “not causing hell”: any methods that are not aware of the insertion of Mammal would continue to work just fine, since the original supertype (Animal here) would still be a supertype of Dog, so the dispatch should work its way up to the original supertype and then get the original method appropriate for that. However, if I were to specialize an existing function for Animal with a method for Mammal, that would constitute type piracy I think, and could cause real problems.