Тип данных списка
data [a] = [] | a : [a]
определяется как выше. Есть только два образца, которые вы можете сопоставить: []
и x : xs
, где x
- голова, а xs
- хвост.
Добавление к списку
a = 1 : 2 : []
b = 0 : a
(:) <-- b
/ \
0 (:) <-- a
/ \
1 (:)
/ \
2 []
просто добавляет новую ячейку cons и повторно использует исходный список как хвост.
Однако имейте в виду, что структуры данных Haskell являются неизменяемыми. Дополнение к концу списка
a = 1 : 2 : []
b = a ++ [3]
(:) <-- a (:) <-- b
/ \ / \
1 (:) 1 (:)
/ \ / \
2 [] 2 (:)
/ \
3 []
требует создания совершенно нового списка, потому что никакая часть исходной структуры не может быть повторно использована.
На самом деле, рассмотрим
a = 0 : a
b = 0 : [ x+1 | x <- b ]
(:) <-- a (:) <-- b
/ \ / \
0 (:) <-- a 0 (:) <-- [ x+1 | x <- b ]
/ \ / \
0 (:) <-- a 1 (:) <-- [ x+1 | x <- [ x+1 | x <- b ] ]
... ...
Как бы вы получили последний элемент списка или добавили в конец?
Существуют и другие структуры данных, такие как dequeue s, которые больше подходят как для фронтального, так и для заднего доступа.