How do associated types differ from generic type parameters?
A generic type parameter is supplied by the caller when they use the type — Array<Int> — whereas an associated type is a placeholder declared inside a protocol that’s filled in by whatever type conforms to it, like associatedtype Element in Sequence.
The key implication is that protocols with associated types (PATs) can’t be used as standalone existential types in the same simple way generic classes can — you can’t just write var x: Sequence, because the compiler needs to know Element to make the type concrete; you either constrain it with some Sequence<Int>, use any Sequence<Int> with primary associated types, or type-erase manually.
I’d reach for a PAT-based protocol when I want to define a capability — like “this thing can be iterated” or “this thing can cache items of some type” — that many unrelated types can adopt, each with their own associated type, without forcing them into a class hierarchy. A generic class makes more sense when you actually want shared implementation and storage, not just a shared interface — for example a Cache<Key: Hashable, Value> class that owns a dictionary internally, versus a Repository protocol with associatedtype Model that different backing stores conform to independently.