Generics let one function or data type work with many kinds of value. Protocols say what those values must be able to do. Together, they let you reuse code without giving up type checking.

Generic functions and types

Type parameters use angle brackets:

A bound may appear inline or in a where clause:

Use && between separate predicates and & to compose protocols in one conformance bound.

Protocols

A protocol may require methods, initializers, static methods, and associated types. It may also provide default implementations:

protocol Named {
	func name() -> String
}

protocol Pet {
	associated Food: Named
	func favorite_food() -> Food

	func description() -> String {
		"a pet who likes " + self.favorite_food().name()
	}
}

Self names the conforming type.

Extensions and conformances

An extension adds methods or declares conformance:

Generic extensions bind their parameters explicitly:

A protocol can also be extended, adding a method to every conformer that meets the extension's constraints.

Protocol arguments and associated types

Protocol arguments distinguish different conformances, as in Equatable<RHS> or Add<RHS>. Associated types describe a type selected by a conformance, as Iterator.Element does. Associated equality constraints use == in a where clause.

Protocols and generic parameters may define defaults, for example:

protocol EqualTo<RHS = Self> {
	func equals(_ other: RHS) -> Bool
}

Existentials

any P stores a value behind an object-safe protocol interface:

Associated bindings can be written in the existential type:

typealias IntIterator = any Iterator<Element = Int>

A protocol is object-safe when its requirements keep Self in receiver position in the ways supported by the compiler. Use a generic parameter when the concrete type should remain known; use any P when different conforming types must share one runtime representation.

Static value generics

A static generic parameter is a compile-time value and participates in type identity:

Static constraints use ==, <, and <=. Type arguments accept a limited set of compile-time expressions, so types such as Matrix<N + 1, (M) * 2> are possible while type checking remains predictable.

Further reading

TalkTalk's protocols draw from type classes and qualified types:

TalkTalk uses both protocol arguments and associated types. Protocol arguments versus associated types explains why they are separate features in this language.