Designing protocols operating over pairs of types

Hi all,

I understand that the title of this topic is a bit confusing but I also wasn't sure how to call it. Basically, I want to achieve the following behavior:

public protocol KLDivergence where Self: Distribution {
  associatedtype TargetDistribution: Distribution

  static func callAsFunction(_ source: Self, _ target: TargetDistribution) -> Float
}

public struct Categorical: Distribution {
  ...
}

extension Categorical: KLDivergence where TargetDistribution == Categorical {
  ...

}

extension Categorical: KLDivergence where TargetDistribution == Other {
  ...
}

The last part is the tricky one. Multiple conformance extensions to the same protocol are not allowed in Swift. I am aware that there have been discussions in Swift about potentially handling mutually exclusive extensions and overlapping types. However, I believe this case is somewhat special in that the protocols we are conforming to can be thought of as being different. With a slight abuse of notation, the above can be thought of as:

extension Categorical: KLDivergence<Categorical> {
  ...

}

extension Categorical: KLDivergence<Other> {
  ...
}

So I am wondering if something like this could be supported or if there is another way to achieve the desired behavior; namely, having the protocol KLDivergence be defined over pairs of types (i.e., SourceDistribution and TargetDistribution) and then having the compiler be able to find the static ccallAsFunction defined in it given only SourceDistribution and TargetDistribution (so that the user does not also need to provide the a KL divergence type / instance. In Scala, we can achieve something like this using implicit instances of KLDivergences, but I'm not sure if something similar can be achieved in Swift as there is no equivalent notion of implicits.

Thanks,
Anthony

What you’re looking for is something similar to multi-parameter type classes in Haskell. This has come up occasionally in the past. I believe the most recent discussion happened here: Improving the UI of generics - #53 by Joe_Groff.

3 Likes

Thanks! That would satisfy what I need. Do you know if there's been any further discussion about potentially supporting something like this?