Given the direction Swift is taking with existentials, it may be worth revisiting overlapping conformances.
Swift has deliberately banned having generic types conform to the same protocol twice even with different bounds, because there may be an overlap. For instance,
protocol Monoid {
static var neutral : Self {get}
func append(_ next: Self) -> Self
}
struct Func<S, T> {
let body : (S) -> T
}
extension Func : Monoid where S == T {
static var neutral : Self {Func{$0}}
func append(_ next: Self) -> Self {
Func {next.closure(closure($0))
}
}
extension Func : Monoid where T : Monoid {
static var neutral : Self {Func {_ in .neutral}}
func append(_ next: Self) -> Self {
Func {closure($0).append(next.closure($0))}
}
}
The problem being: which overload does Swift use if S==T
and T : Monoid
?
Right now, the solution is to just ban multiple conformance. But we cloud do something similar to what we're now doing with existential boxes: we could allow multiple conformance and throw a compile error if we're attempting to create instances where the conformance actually overlaps. This could even be combined with the rejected considered alternative in the linked proposal where you provide "tie breaker" overloads.
Basically, the idea was that you provide an explicit overload for any possible overlapping conformance, e.g.:
extension Func : Monoid where S == T, T : Monoid {
/// do what you consider appropriate
}
The authors of the linked proposal found this unsatisfying because you get a quickly growing number of overlapping conformances with each additional conformance. But if we only considered it an error if you created instances where no "tie breaker" is declared, that would mitigate the issue.
What do y'all think?