To provide a specific example:
protocol CheckHelper {
static func call<T: Collection>(_ q: T, _ s: T) -> Bool
}
func check<Helper: CheckHelper>(_ helper: Helper.Type) -> Bool {
assert(helper.call("foo", "baz"))
assert(helper.call([1, 2], [3, 4]))
}
enum IsBazable: CheckHelper {
static func call<T: Collection>(_ q: T, _ s: T) -> Bool {
return isBazable(q, s)
}
}
check(IsBazable.self)
enum IsBazableImproved: CheckHelper {
static func call<T: Collection>(_ q: T, _ s: T) -> Bool {
return isBazableImproved(q, s)
}
}
check(IsBazableImproed.self)
It's worth pointing out that you could also make the call method an instance method which would allow the helper types to capture state if necessary and also allow check to omit saying .call when a final design for SE-0253: Callable values of user-defined nominal types is accepted.
As an aside, I think your example is a good demonstration of a use case where it really does make sense to allow "static static callables" (i.e. static func call). This allows us to encode stateless higher-rank function signatures in protocols that are reasonably convenient for users. Certainly not as nice as actual type-system higher-rank functions but a lot nicer than having to write .call everywhere.