Generics in generics

I have a question about syntax with respect to generics. I've created a generic type whose element is labelled 'Element'. Now I'd like to create an extension to Array where the elements of the array are the generic type and the elements off the generic type are equatable. I'm having trouble figuring out the syntax of the array extension. If Generic is the generic type, I've tried

extension Array where Array.Element: Generic<Element>, where Array.Element.Element: Equatable { }

and the compiler in Xcode doesn't object to that, but then I can't figure out how to define methods! Is this the correct syntax for the extension?

This is currently impossible due to the lack of support for generic extensions. It's described in the generics manifesto https://github.com/apple/swift/blob/main/docs/GenericsManifesto.md#parameterized-extensions
But perhaps you could use a workaround with a dedicated protocol to express the constraint:

protocol _GenericProtocol<Element> {
  associatedtype Element
}
struct Generic<Element>: _GenericProtocol { ... }
extension Array where Element: _GenericProtocol, Element.Element: Equatable { ... }

This will be sufficient in most cases.

2 Likes

You can define your constraints within an extension.

struct Generic<Element> {
    let element: Element
}

extension Array {

    func areBoundsEqual<T>() -> Bool where Element == Generic<T>, T: Equatable {
        first?.element == last?.element
    }
}
4 Likes

Thanks for the response. I was able to figure it out from this post and the one from Stan_Smida. I actually had defined the generic with a protocol having an associatedtype, so this suggestion lead directly to the solution. I needed a function in the Array extension that took as a parameter a generic (i.e., the 'Element' of the Array) and returned a generic (again, an 'Element' of thee Array). What worked is the following Array extension, using the terminology in dmt's response:

extension Array where Element: _GenericProtocol. Element.Element: Equatable {

    func test(generic: Element) -> Element {
        ...
    }

}

Again, thanks for both responses.