Your intuition about copying is exactly the right direction you should be thinking. However, the 'copying' intelligently implemented by the Haskell runtime. For example, given
data Tree = Empty | Branch Tree Integer Tree
You could implement a function to replace the left branch:
replaceLeft :: Tree -> Tree -> Tree
replaceLeft (Branch _ i r) newLeft = Branch newLeft i r
The result isn't that you create a entire copy of the new tree, as that isn't necessary. The value i
and the trees r
and newLeft
are unchanged so we don't have to copy their contents into fresh memory.
The new Branch
that is created (this is the only real allocation in this example: the creation of the structure to hold the left/right trees on the Integer
) still references the exact same values from the old branch, no copying needed!
Since the data structures are immutable, there's no harm in doing this.