Generics, also called polymorphic functions, abstract over types. A monomorphic function is fixed to one data type; a generic function uses one or more type parameters so the same definition can operate on many types. This removes type-specific detail and makes definitions easier to reuse. section 2.4 section 2.7
In Scala, a method declares type parameters in square brackets after its name, conventionally with short uppercase names such as A, B, and C. A type parameter introduces a type variable that can be used throughout the signature. Reusing A in several positions requires those positions to have the same type, with the compiler enforcing that relationship. section 2.4.1 section 2.4.1
Searching without assuming equality
A String-only findFirst can search an Array[String] for a String key, but its structure is nearly identical for Int or any other element type. Generalize it as findFirst[A](as: Array[A], p: A => Boolean): Int. The caller supplies p, a test for A, instead of relying on an equals method that may not be useful. The function returns the first matching index or -1. section 2.4.1
Listing 2.4 Polymorphic function to find an element in an array
def findFirst[A](as: Array[A], p: A => Boolean): Int = #1
@annotation.tailrec
def loop(n: Int): Int =
if n >= as.length then -1
else if p(as(n)) then n #2
else loop(n + 1)
loop(0)
Compare the generic search signature with its recursive loop: A determines both the array element type and the predicate input, while the predicate supplies the only needed operation on an element. section 2.4.1
Generic signatures do more than permit reuse: they restrict what an implementation can do. For an unknown A, code can use only operations supplied as arguments or derived from them. This can turn implementation into type-guided reasoning. For partial1[A, B, C], the required B => C result must accept b: B and combine it with the available a: A by calling f(a, b). section 2.5 section 2.7
The same idea extends beyond ordinary methods. A polymorphic List[A] represents lists of different element types with one data-type definition. Polymorphic function types quantify over a type parameter for every type encountered, enabling transformations such as F[x] => G[x] while preserving the particular x. section 3.1 section 13.4.2
Parametricity can also yield guarantees: because a polymorphic map cannot behave differently according to the function types it receives, laws such as mapping identity can support free theorems and map-fusion reasoning. section 7.3.1



















