liveBook · Manning

Generics

As explained in Learn Haskell by Example

A function that can operate with values of more than one type through generalized type behavior.

Generics let one definition work over more than one type. In Haskell, this is commonly called parametric polymorphism: a type signature contains type variables such as a or t instead of fixed types. A type variable may stand for any type, but every occurrence of that variable in one use must stand for the same type. The variable names themselves do not matter. section 2.5.2 section 3.3.2

A generic function states the relationship between its inputs and outputs without committing to particular value types. For transform :: (t -> a) -> [t] -> [a], transform accepts a function from t to a and a list of t, then produces a list of a. The input and output element types can differ, while each repeated variable remains consistent. section 2.5.2

ghci> :type transform
transform :: (t -> a) -> [t] -> [a]

Inspect the generic type of transform in GHCi. The signature shows that list elements are converted by a supplied function rather than requiring a fixed element type. section 2.5.2

Specializing a generic function

If f :: Int -> String is passed to transform, t becomes Int and a becomes String. Therefore transform f accepts [Int] and returns [String]. Haskell can infer this specialization, so a definition such as g xs = transform f xs receives the type [Int] -> [String]. section 2.5.2

This flexibility makes higher-order functions useful: the same operation need not be rewritten for each element type. Mapping a function over a list is a typical case, and generic types support abstract, composable code throughout Haskell programs. section 2.5.2 section 2.6

Type parameters also appear in data types. Maybe a represents either Just a value of any chosen type or Nothing. A helper with type fromMaybe :: a -> Maybe a -> a uses one a to ensure that its default value, possible wrapped value, and result all share a type. section 3.3.2 section 3.3.2

Listing 3.6 A function to extract a value from a Maybe using a default
fromMaybe :: a -> Maybe a -> a
fromMaybe _ (Just v) = v  #1
fromMaybe v Nothing = v  #2

See a complete generic function that extracts a Maybe value or returns a same-typed default. section 3.3.2

Keep these practical distinctions in mind:

  • Parametric polymorphism uses unrestricted type variables; their repeated uses must agree on one type. section 2.5.2
  • Type classes can later restrict what operations are assumed for a type variable. section 2.5.2
  • Generic is also a derivable facility for generating type-class implementations from a datatype definition, including JSON and database-related classes. section 16.4
  • Type-variable scope can produce confusing compiler errors when multiple helper functions are involved. section 6.0 section 6.2

Use a generic signature when an algorithm depends on the shape of data and the relationships among values, not on one concrete type. Let the compiler infer a specific use where possible, while reading each repeated type variable as a consistency requirement. section 2.5.2 section 3.3.2

How Learn Haskell by Example covers it

How deep it goes
Explains type-variable substitution and inference through function and Maybe examples, while deferring constraints to type classes.
Examples
Uses transform from lists to lists, an Int-to-String function, and fromMaybe over Maybe values.
What it assumes
Introduces parametric types from zero while relying on basic function signatures, lists, and pattern matching.
What you can do after
Apply it by reading and writing signatures whose repeated type variables enforce consistent types across inputs and results.
How it connects
Connects parametric polymorphism with higher-order functions, type inference, Maybe, algebraic data types, and type classes.

Also explained in

Compare how 20 books explain generics →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.