Ralf Hinze and Ross Paterson, Journal of Functional Programming 16(2):197–217, 2006. doi:10.1017/S0956796805005769
We present 2-3 finger trees, a functional representation of persistent sequences supporting access to the ends in amortized constant time, and concatenation and splitting in time logarithmic in the size of the smaller piece. Representations achieving these bounds have appeared previously, but 2-3 finger trees are much simpler, as are the operations on them. Further, by defining the split operation in a general form, we obtain a general purpose data structure that can serve as a sequence, priority queue, search tree, priority search queue and more.
The basic structure is expressed as a non-regular (or nested) type:
data FingerTree a = Empty | Single a | Deep (Digit a) (FingerTree (Node a)) (Digit a) data Digit a = One a | Two a a | Three a a a | Four a a a a data Node a = Node2 a a | Node3 a a aThis produces trees of 2-3 trees, with favoured access (fingers) at the ends, like
(more examples) and also supports efficient concatenation. To support splitting and searching, we annotate the internal nodes of the tree with values drawn from an application-specific monoid.
In section 4.3, we suggest that the operations of section 3 could be extended to measured trees by replacing the constructors with their smart counterparts. However, applying the smart constructor deep to the result of a recursive call forces the call, losing the laziness that is crucial to the analysis. Instead, we must compute the new measure without forcing the recursive call.
In the case of <|, the last two clauses can be written
a <| Deep v [b, c, d, e] m sf = Deep (|a| + v) [a, b] (node3 c d e <| m) sf a <| Deep v pr m sf = Deep (|a| + v) ([a] ++ pr) m sf
In the case of deepL, the first clause can be written
deepL [] m sf = case viewL m of NilL -> toTree sf ConsL a m' -> Deep (|m| + |sf|) (toList a) m' sf
data ImplicitDeque a = Empty | Single a | Deep (Digit a) (ImplicitDeque (a, a)) (Digit a) data Digit a = One a | Two a a | Three a a aFinger trees result from two extensions of this structure: