The list type (list of ) is defined by two introduction rules
(“a list is either empty or a thing followed by a list of things”) and the elimination rule: given and there is a unique with and . Such an is a fold (list catamorphism); in Haskell foldr step init, with [a], [] and (:) as built-in syntax.
Sources: DaoFP §7.2 (“Lists”, “Elimination Rule”), §7.3 (“Functoriality”:
map,badMap), §12.4 (“Lists as initial algebras”), §15.3 (“Free monoid and the list monad”), Exercises 7.2.1–7.2.3; Kittenlab Lecture 5 (ConcatMonoid); 7 Sketches §5.2.4 (free monoid); CTfS Definition 3.1.1.10, Example 3.1.1.11
- Lists as functions (CTfS Definition 3.1.1.10): a list in is a pair with its length and its entries; concatenation uses on and after — so and is the unit.
- Functoriality (§7.3): for ,
map fis the fold with and . The alternative (badMap, which drops all elements) type-checks but fails the functor lawmap id = id— see Functor. - is the Free Monoid on and the Initial Algebra of ;
foldris the catamorphism. (Natural Numbers Object, DaoFP Exercise 7.2.1). - Not every mapping out of a list is a fold, but every Haskell function
[a] -> cwritten by pattern matching on[]and(:)is (DaoFP Exercise 7.2.2, DaoFP Exercise 7.2.3). sum = foldr plus Zon lists of naturals; the List Monad uses concatenation asjoin.
Docs: Kittenlab Lecture 5
# foldr as the list recursor
recList(init, step) = as -> isempty(as) ? init : step(as[1], recList(init, step)(as[2:end]))
recList(0, +)([1, 2, 3]) # 6
mapList(f) = recList(Any[], (a, bs) -> [f(a); bs])
mapList(x -> x^2)([1, 2, 3]) # [1, 4, 9]
third(as) = length(as) >= 3 ? Some(as[3]) : nothingimport Mathlib
#check @List.rec -- the eliminator
#check @List.foldr -- (α → β → β) → β → List α → β
#check @List.map
#check @List.map_id -- the functor law badMap violates
#check @List.get? -- l.get? 2 : Option α, the "third element" of Exercise 7.2.3data List a where
Nil :: List a
Cons :: (a, List a) -> List a
recList :: c -> ((a, c) -> c) -> (List a -> c) -- the list recursor
recList init step = \as -> case as of
Nil -> init
Cons (a, as) -> step (a, recList init step as)
foldr' :: (a -> c -> c) -> c -> [a] -> c -- built-in lists
foldr' step init = \as -> case as of
[] -> init
a : as -> step a (foldr' step init as)
mapList :: (a -> b) -> List a -> List b
mapList f = recList Nil (\(a, bs) -> Cons (f a, bs))