I'd rather use polymorphism (rather than checking the type) and define `~` on `BuildIn::Negation` so return the wrapped matcher.

One gotcha once we go that route: you'll need to make the boolean operators config option define `!` to delegate to `~`, rather than aliasing it, because as an alias, it would be bound directly to this implementation of `~` and not call `Negation`'s implementation.