liveBook · Manning

List

As explained in Learn Haskell by Example

A list is an ordered sequence data structure whose elements can be processed recursively from its first element and remaining tail.

A list is a homogeneous, ordered sequence: every element has the same type. Write values in square brackets, separated by commas, such as [1, 2, 3] or [True]. Its type also uses brackets: [Int], [Bool], and [Char]. An empty list still has an element type, so [] can be a [Float]. section 2.2.2

intList :: [Int]
intList = [1, 2, 3]

boolList :: [Bool]
boolList = [True]

floatList :: [Float]
floatList = []

doubleList :: [Double]
doubleList = [1, 1 + 1, 1 + 2]

These declarations pair list values with their element types, including an empty Float list and a Double list containing expressions. section 2.2.2

Lists can grow dynamically and do not have a fixed size. They are especially useful for collections such as letters in a message. A String is a list of characters, so functions over lists can also process strings. section 2.2.2 section 2.5

In Haskell, a list has two constructors: [] for the empty list and (:) for prepending one element to an existing list. For example, 1 : [2, 3] produces [1, 2, 3]. The pattern x : xs splits a nonempty list into its first element x and remaining tail xs. section 2.4.1

Compute a list length recursively

Pattern matching handles both possible list shapes. The empty list is the stopping case; a nonempty list contributes one, then continues with its tail. listLength [] = 0 listLength (x : xs) = 1 + listLength xs Leaving out the x : xs case makes the function partial: it works for [] but fails on nonempty lists because the patterns are nonexhaustive. section 2.4.1

Use lists with recursion when immutable data and the absence of loops require a repeated operation over successive tails:

  • Match [] to define the base case. section 2.4.1
  • Match x : xs to handle one element and recursively process xs. section 2.4.1
  • Construct a new list rather than modifying the old one. section 2.5

Transform every character

A Caesar cipher creates a new string by transforming the first character, prepending it to the recursively transformed tail, and preserving the empty-list base case. caesar :: Int -> String -> String caesar n [] = [] caesar n (x : xs) = rotChar n x : caesar n xs For example, caesar 13 "Caesars Cipher!" yields "Pnrfnef Pvcure!". section 2.5

The same head-and-tail structure supports searches. An index function compares the current element, returns 0 when it matches, and otherwise adds 1 while searching the tail. Its empty-list case must be defined deliberately; using undefined reports failure when no matching character exists. section 2.4.1

How Learn Haskell by Example covers it

How deep it goes
Defines notation, homogeneous typing, constructors, pattern matching, and recursive implementations, while deferring generalization of transformations.
Examples
Demonstrates typed numeric and Boolean lists, recursive length and index functions, and a Caesar cipher over a String.
What it assumes
Introduces list operations for beginners while assuming only basic Haskell syntax and simple atomic types.
What you can do after
Build it from scratch with empty and nonempty patterns to search or transform a list recursively.
How it connects
Connects lists to Strings, recursion, pattern matching, immutable data, type inference, and Caesar cipher transformation.

Also explained in

Compare how 21 books explain list →

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.