Once I tried to make a union of a sorted set and an unsorted one. Result set inherits behaviour of a bigger input set so when i first got my sometimes-sorted set i thought like loosing my mind.
The issue doesn't have much to do with dynamic typing, any subtyping support can trigger it. Take Java, if Set had a `Set union(Collection)` method a SortedSet could return a new SortedSet (cast as a set, but still with the actual behaviour of a sorted set).
But you would not be able to pass it to a method that takes a SortedSet, which means you can't rely on the sorted behavior. Incorrectly using behavior that your implementation doesn't support is where the confusion comes from, it doesn't come from your implantation having extra behavior that you can't use.
class Set<A> { public Set<A> union(Collection<A> c) { ... } }
class SortedSet<A> extends Set<A> {
@Override public SortedSet<A> union(Collection<A> c) { ... }
}
In other words, the more specific type overrides the operations of the more general type into more specialised operations.
defnly agree that you can get these problems in languages with static types, but i think you have to go out of your way vs dynamic languages, where these types of shenanigans are easier and (in my experience) prevalent.
e.g., in your example, because your returned type is Set, you presumably would not be relying on the result to be a sorted set! -- so there would be no problem. if you WERE relying on it being a sorted set, you would have to explicitly downcast -- i.e. would pointing a gun and at your foot and pulling the trigger. maybe you know it's unloaded, but the danger is clear from the type system. ;)