I was able to re-write the protocol and obtained what I want by:
protocol Dispatchable {
associatedtype Messages: Collection
var messages: Messages { get }
func dispatch( _ message: Messages.Element )
}
But I'm still not sure as to why the first method I've used didn't work. And how come, since Collection protocol uses a primary associated type Element I don't have to specify it here.
I guess the associated Element type will be deduced when a class/struct will implement the protocol?
Associated types provide a better way to model the same problem, and the requirements can then be satisfied by a function that produces an opaque result type. (There might be an interesting shorthand feature here, where using some in a protocol requirement implicitly introduces an associated type, but we leave that for future language design to explore.)
This would work even if primary associated types didn't exist. You didn't add any constraints to Collection.Element, so a type that conforms to Dispatchable could use any type that conforms to Collection as its Messages type.
But you could've added constraints to Collection.Element. For example:
associatedtype Messages: Collection where Messages.Element: Equatable
or
associatedtype Messages: Collection where Messages.Element == String
In this case, you could do the same thing with an associated type so it's just a shorthand (not that shorthands are not useful - they are!). There are other situations, though, where you cannot express the value of an associated type (e.g. because it depends on another generic context, or availability), and opaque types could unblock those model designs.