@@ -314,11 +314,16 @@ data Rigidified a = RigidEmpty
314
314
deriving Show
315
315
#endif
316
316
317
+ -- | A finger tree whose top level has only Two and/or Three digits, and whose
318
+ -- other levels have only One and Two digits. A Rigid tree is precisely what one
319
+ -- gets by unzipping/inverting a 2-3 tree, so it is precisely what we need to
320
+ -- turn a finger tree into in order to transform it into a 2-3 tree.
317
321
data Rigid a = Rigid {- # UNPACK #-} !Int ! (Digit23 a ) (Thin (Node a )) ! (Digit23 a )
318
322
#ifdef TESTING
319
323
deriving Show
320
324
#endif
321
325
326
+ -- | A finger tree whose digits are all ones and twos
322
327
data Thin a = EmptyTh
323
328
| SingleTh a
324
329
| DeepTh {- # UNPACK #-} !Int ! (Digit12 a ) (Thin (Node a )) ! (Digit12 a )
@@ -331,16 +336,23 @@ data Digit12 a = One12 a | Two12 a a
331
336
deriving Show
332
337
#endif
333
338
339
+ -- | Sometimes, we want to emphasize that we are viewing a node as a top-level
340
+ -- digit of a 'Rigid' tree.
334
341
type Digit23 a = Node a
335
342
336
- -- | 'aptyMiddle' does most of the hard work of computing @fs<*>xs@.
337
- -- It produces the center part of a finger tree, with a prefix corresponding
338
- -- to the prefix of @xs@ and a suffix corresponding to the suffix of @xs@
339
- -- omitted; the missing suffix and prefix are added by the caller.
340
- -- For the recursive call, it squashes the prefix and the suffix into
341
- -- the center tree. Once it gets to the bottom, it turns the tree into
342
- -- a 2-3 tree, applies 'mapMulFT' to produce the main body, and glues all
343
- -- the pieces together.
343
+ -- | 'aptyMiddle' does most of the hard work of computing @fs<*>xs@. It
344
+ -- produces the center part of a finger tree, with a prefix corresponding to
345
+ -- the prefix of @xs@ and a suffix corresponding to the suffix of @xs@ omitted;
346
+ -- the missing suffix and prefix are added by the caller. For the recursive
347
+ -- call, it squashes the prefix and the suffix into the center tree. Once it
348
+ -- gets to the bottom, it turns the tree into a 2-3 tree, applies 'mapMulFT' to
349
+ -- produce the main body, and glues all the pieces together.
350
+ --
351
+ -- 'map23' itself is a bit horrifying because of the nested types involved. Its
352
+ -- job is to map over the *elements* of a 2-3 tree, rather than the subtrees.
353
+ -- If we used a higher-order nested type with MPTC, we could probably use a
354
+ -- class, but as it is we have to build up 'map23' explicitly through the
355
+ -- recursion.
344
356
aptyMiddle
345
357
:: Sized c =>
346
358
(c -> d )
@@ -440,67 +452,57 @@ mapMulNode :: Int -> (a -> b) -> Node a -> Node b
440
452
mapMulNode mul f (Node2 s a b) = Node2 (mul * s) (f a) (f b)
441
453
mapMulNode mul f (Node3 s a b c) = Node3 (mul * s) (f a) (f b) (f c)
442
454
443
-
444
- -- rigidify :: Seq a -> Rigidified (Elem a)
445
- -- rigidify (Seq xs) = rigidify' xs
446
-
447
455
-- | /O(log n)/ (incremental) Takes the extra flexibility out of a 'FingerTree'
448
456
-- to make it a genuine 2-3 finger tree. The result of 'rigidify' will have
449
- -- only 'Two' and 'Three' digits at the top level and only 'One' and 'Two'
450
- -- digits elsewhere. It gives an error if the tree has fewer than four
451
- -- elements .
457
+ -- only two and three digits at the top level and only one and two
458
+ -- digits elsewhere. If the tree has fewer than four elements, 'rigidify'
459
+ -- will simply extract them, and will not build a tree .
452
460
rigidify :: FingerTree (Elem a ) -> Rigidified (Elem a )
453
- -- Note that 'rigidify' may call itself, but it will do so at most
454
- -- once: each call to 'rigidify' will either fix the whole tree or fix one digit
455
- -- and leave the other alone. The patterns below just fix up the top level of
456
- -- the tree; 'rigidify' delegates the hard work to 'thin'.
457
-
458
- -- The top of the tree is fine.
459
-
460
- rigidify (Deep s (Two a b) m (Three c d e)) =
461
- RigidFull $ Rigid s (node2 a b) (thin m) (node3 c d e)
462
- rigidify (Deep s (Three a b c) m (Three d e f)) =
463
- RigidFull $ Rigid s (node3 a b c) (thin m) (node3 d e f)
464
- rigidify (Deep s (Two a b) m (Two c d)) =
465
- RigidFull $ Rigid s (node2 a b) (thin m) (node2 c d)
466
- rigidify (Deep s (Three a b c) m (Two d e)) =
467
- RigidFull $ Rigid s (node3 a b c) (thin m) (node2 d e)
468
-
469
- -- One of the Digits is a Four.
470
- rigidify (Deep s (Four a b c d) m sf) =
471
- rigidify $ Deep s (Two a b) (node2 c d `consTree` m) sf
472
-
473
- rigidify (Deep s pr m (Four a b c d)) =
474
- rigidify $ Deep s pr (m `snocTree` node2 a b) (Two c d)
475
-
476
- -- One of the Digits is a One.
461
+ -- The patterns below just fix up the top level of the tree; 'rigidify'
462
+ -- delegates the hard work to 'thin'.
463
+
464
+ rigidify Empty = RigidEmpty
465
+
466
+ rigidify (Single q) = RigidOne q
467
+
468
+ -- The left digit is Two or Three
469
+ rigidify (Deep s (Two a b) m sf) = rigidifyRight s (node2 a b) m sf
470
+ rigidify (Deep s (Three a b c) m sf) = rigidifyRight s (node3 a b c) m sf
471
+
472
+ -- The left digit is Four
473
+ rigidify (Deep s (Four a b c d) m sf) = rigidifyRight s (node2 a b) (node2 c d `consTree` m) sf
474
+
475
+ -- The left digit is One
477
476
rigidify (Deep s (One a) m sf) = case viewLTree m of
478
- Just2 (Node2 _ b c) m' -> rigidify $ Deep s (Three a b c) m' sf
479
- Just2 (Node3 _ b c d) m' -> rigidify $ Deep s (Two a b) (node2 c d `consTree` m') sf
477
+ Just2 (Node2 _ b c) m' -> rigidifyRight s (node3 a b c) m' sf
478
+ Just2 (Node3 _ b c d) m' -> rigidifyRight s (node2 a b) (node2 c d `consTree` m') sf
480
479
Nothing2 -> case sf of
481
480
One b -> RigidTwo a b
482
481
Two b c -> RigidThree a b c
483
482
Three b c d -> RigidFull $ Rigid s (node2 a b) EmptyTh (node2 c d)
484
483
Four b c d e -> RigidFull $ Rigid s (node3 a b c) EmptyTh (node2 d e)
485
484
486
- rigidify (Deep s pr m (One e)) = case viewRTree m of
487
- Just2 m' (Node2 _ a b) -> rigidify $ Deep s pr m' (Three a b e)
488
- Just2 m' (Node3 _ a b c) -> rigidify $ Deep s pr (m' `snocTree` node2 a b) (Two c e)
489
- Nothing2 -> case pr of
490
- One a -> RigidTwo a e
491
- Two a b -> RigidThree a b e
492
- Three a b c -> RigidFull $ Rigid s (node2 a b) EmptyTh (node2 c e)
493
- Four a b c d -> RigidFull $ Rigid s (node3 a b c) EmptyTh (node2 d e)
485
+ -- | /O(log n)/ (incremental) Takes a tree whose left side has been rigidified
486
+ -- and finishes the job.
487
+ rigidifyRight :: Int -> Digit23 (Elem a ) -> FingerTree (Node (Elem a )) -> Digit (Elem a ) -> Rigidified (Elem a )
494
488
495
- rigidify Empty = RigidEmpty
496
-
497
- rigidify (Single q) = RigidOne q
489
+ -- The right digit is Two, Three, or Four
490
+ rigidifyRight s pr m (Two a b) = RigidFull $ Rigid s pr (thin m) (node2 a b)
491
+ rigidifyRight s pr m (Three a b c) = RigidFull $ Rigid s pr (thin m) (node3 a b c)
492
+ rigidifyRight s pr m (Four a b c d) = RigidFull $ Rigid s pr (thin $ m `snocTree` node2 a b) (node2 c d)
498
493
494
+ -- The right digit is One
495
+ rigidifyRight s pr m (One e) = case viewRTree m of
496
+ Just2 m' (Node2 _ a b) -> RigidFull $ Rigid s pr (thin m') (node3 a b e)
497
+ Just2 m' (Node3 _ a b c) -> RigidFull $ Rigid s pr (thin $ m' `snocTree` node2 a b) (node2 c e)
498
+ Nothing2 -> case pr of
499
+ Node2 _ a b -> RigidThree a b e
500
+ Node3 _ a b c -> RigidFull $ Rigid s (node2 a b) EmptyTh (node2 c e)
499
501
500
502
-- | /O(log n)/ (incremental) Rejigger a finger tree so the digits are all ones
501
503
-- and twos.
502
504
thin :: Sized a => FingerTree a -> Thin a
503
- -- Note that 'thin12' will produce a 'Deep ' constructor immediately before
505
+ -- Note that 'thin12' will produce a 'DeepTh ' constructor immediately before
504
506
-- recursively calling 'thin'.
505
507
thin Empty = EmptyTh
506
508
thin (Single a) = SingleTh a
0 commit comments