Here are a few ways to make a type conform to MyProto.
You can conform by picking a specific type for T that satisfies the constraint. (The constraint is that T must conform to Sequence and its Element must be Int.) Then write an implementation of myFunc that takes an argument of that specific type. Example:
struct MyStruct: MyProto {
// Set conforms to Sequence.
typealias T = Set<Int>
func myFunc(a: Set<Int>) {
print("\(a.count)")
}
}
You can also make an existing type conform this way, using an extension on the existing type. For example:
extension String: MyProto {
// Range conforms to Sequence.
typealias T = Range<Int>
func myFunc(a: Range<Int>) {
print("\(self) \(a)")
}
}
Another way to conform is to create a generic type, and then make the generic type conform only when its generic parameter satisfies the constraint. Example:
struct MyGenericStruct<T> { }
extension MyGenericStruct: MyProto where T: Sequence<Int> {
func myFunc(a: T) {
print("\(a)")
}
}
This is called a conditional conformance, because MyGenericStruct only conforms to MyProto if its T parameter satisfies the constraint.
If your type always constrains T, it can conform unconditionally, like this:
struct MyLessGenericStruct<T: Sequence<Int>> { }
// T always satisfies the MyProto constraint, so this
// conformance is unconditional.
extension MyLessGenericStruct: MyProto {
func myFunc(a: T) {
print(a)
}
}
You can also make an existing generic type conform to MyProto. Usually this will be a conditional conformance. Example:
extension Array: MyProto where Element: Sequence, Element.Element == Int {
typealias T = Element
func myFunc(a: T) {
let found = self.contains { $0.elementsEqual(a) }
print(found)
}
}
You can also conform if you have a generic parameter that conforms, by using your parameter's conformance to implement your own conformance.
extension Set: MyProto where Element: MyProto {
typealias T = Element.T
func myFunc(a: T) {
self.first?.myFunc(a: a)
}
}
Please note that in many of these examples, I have explicitly defined T using a typealias. But often Swift can infer T from the type of a property or function. For example, we could write that last example like this instead:
extension Set: MyProto where Element: MyProto {
func myFunc(a: Element.T) {
self.first?.myFunc(a: a)
}
}
Swift sees that myFunc can satisfy the MyProto requirement if T is Element.T, and doesn't find any contradictory declarations, so it infers T = Element.T.