Today I started learning Haskell. I’m kind of new with functional languages, and I’m enjoying Haskell a lot.
However I’ve got a question about its design which is bugging me: from what I understood so far it looks like accessing an element to the back of a list is a lot more complicated that accessing the element to the front (something like xs:x where xs::[a] and x::a doesn’t seem to be possible).
(From what I understood) it’s possible to append a list to another one (xs++[a]), but it’ll cost more at run time (it requires to traverse the whole list) and it cannot be used for pattern matching.
Why is Haskell missing such operation?
The list datatype
is defined like above. There’s only two patterns you can match:
[]andx : xs, wherexis the head andxsis the tail.Prepending to a list
(:) <-- b / \ 0 (:) <-- a / \ 1 (:) / \ 2 []simply adds a new cons cell and reuses the original list as the tail.
However, keep in mind that Haskell data structures are immutable. Appending to the tail of a list
(:) <-- a (:) <-- b / \ / \ 1 (:) 1 (:) / \ / \ 2 [] 2 (:) / \ 3 []requires building an entirely new list, because no part of the original structure can be reused.
In fact, consider
(:) <-- a (:) <-- b / \ / \ 0 (:) <-- a 0 (:) <-- [ x+1 | x <- b ] / \ / \ 0 (:) <-- a 1 (:) <-- [ x+1 | x <- [ x+1 | x <- b ] ] ... ...How would you ever get the last element of the list, or append to the end?
There are other data structures such as dequeues which are more suited for both front- and back-based access.