I am confused about the this data type in Haskell - Map. In particular, there is a function call insert (from the Data.Map module) which allows you to append new values to the Map data structure. So, here is my confusion. If haskell data structure is immutable, how can you insert new data into an existing Map data structure?
2 Answers
insert doesn't actually modify the input Map. It returns a new Map that contains the same entries as the original Map, plus the one you are inserting.
Underneath the hood, the compiler may not actually have to copy all the old entries to a new Map, though; it can reuse the original if it determines that nothing else is using the input Map. Immutability is a property of the language, not necessarily the implementation of the language.
2 Comments
insert only needs to copy O(log N) nodes of the tree, and reuse much of the old (immutable) tree.Map is implemented as a tree, and unchanged subtrees can be (and are) shared between the old Map and the new one. This is permissible whether something else is using the input Map or not (because immutability guarantees that the sharing won't cause aliasing problems).Perhaps an example will make this clearer.
Prelude> let map1 = empty
Prelude> map1
fromList []
Prelude> let map2 = insert "Lemon" 6 map1
Prelude> map2
fromList [("Lemon", 6)]
Prelude> map1
fromList []
Prelude> let map3 = insert "Lime" 7 map2
Prelude> map3
fromList [("Lime", 7), ("Lemon", 6)]
Prelude> map2
fromList [("Lemon", 6)]
Prelude> map1
fromList []
Each time we define a new variable (map1, map2, map3), the previous version of the Map remains completely unchanged. Once we have defined that (for example) map1 contains the key "Lemon", nothing can ever change that definition. We can create a new map that contains additional keys (or fewer keys, indeed), but we cannot change map1 itself.