@@ -531,7 +531,7 @@ apSeq fs xs@(Seq xsFT) = case viewl fs of
531
531
RigidFull r@ (Rigid s pr _m sf) -> Seq $
532
532
Deep (s * length fs)
533
533
(fmap (fmap firstf) (nodeToDigit pr))
534
- (aptyMiddle (fmap firstf) (fmap lastf) fmap fs''FT r)
534
+ (liftA2Middle (fmap firstf) (fmap lastf) fmap fs''FT r)
535
535
(fmap (fmap lastf) (nodeToDigit sf))
536
536
{-# NOINLINE [1] apSeq #-}
537
537
@@ -591,7 +591,7 @@ liftA2Seq f xs ys@(Seq ysFT) = case viewl xs of
591
591
RigidFull r@ (Rigid s pr _m sf) -> Seq $
592
592
Deep (s * length xs)
593
593
(fmap (fmap (f firstx)) (nodeToDigit pr))
594
- (aptyMiddle (fmap (f firstx)) (fmap (f lastx)) (lift_elem f) xs''FT r)
594
+ (liftA2Middle (fmap (f firstx)) (fmap (f lastx)) (lift_elem f) xs''FT r)
595
595
(fmap (fmap (f lastx)) (nodeToDigit sf))
596
596
where
597
597
lift_elem :: (a -> b -> c ) -> a -> Elem b -> Elem c
@@ -638,65 +638,128 @@ data Digit12 a = One12 a | Two12 a a
638
638
-- digit of a 'Rigid' tree.
639
639
type Digit23 a = Node a
640
640
641
- -- | 'aptyMiddle ' does most of the hard work of computing @fs<*>xs @. It
641
+ -- | 'liftA2Middle ' does most of the hard work of computing @liftA2 f xs ys @. It
642
642
-- produces the center part of a finger tree, with a prefix corresponding to
643
- -- the prefix of @xs@ and a suffix corresponding to the suffix of @xs@ omitted;
643
+ -- the first element of @xs@ and a suffix corresponding to its last element omitted;
644
644
-- the missing suffix and prefix are added by the caller. For the recursive
645
645
-- call, it squashes the prefix and the suffix into the center tree. Once it
646
646
-- gets to the bottom, it turns the tree into a 2-3 tree, applies 'mapMulFT' to
647
647
-- produce the main body, and glues all the pieces together.
648
648
--
649
- -- @map23 @ itself is a bit horrifying because of the nested types involved. Its
649
+ -- @f @ itself is a bit horrifying because of the nested types involved. Its
650
650
-- job is to map over the *elements* of a 2-3 tree, rather than the subtrees.
651
651
-- If we used a higher-order nested type with MPTC, we could probably use a
652
- -- class, but as it is we have to build up @map23 @ explicitly through the
652
+ -- class, but as it is we have to build up @f @ explicitly through the
653
653
-- recursion.
654
- aptyMiddle
655
- :: (b -> c )
656
- -> (b -> c )
657
- -> (a -> b -> c )
658
- -> FingerTree (Elem a )
659
- -> Rigid b
660
- -> FingerTree (Node c )
654
+ --
655
+ -- === Description of parameters
656
+ --
657
+ -- ==== Types
658
+ --
659
+ -- @a@ remains constant through recursive calls (in the @DeepTh@ case),
660
+ -- while @b@ and @c@ do not: 'liftAMiddle' calls itself at types @Node b@ and
661
+ -- @Node c@.
662
+ --
663
+ -- ==== Values
664
+ --
665
+ -- 'liftA2Middle' is used when the original @xs :: Sequence a@ has at
666
+ -- least two elements, so it can be decomposed by taking off the first and last
667
+ -- elements:
668
+ --
669
+ -- > xs = firstx <: midxs :> lastx
670
+ --
671
+ -- - the first two arguments @ffirstx, flastx :: b -> c@ are equal to
672
+ -- @f firstx@ and @f lastx@, where @f :: a -> b -> c@ is the third argument.
673
+ -- This ensures sharing when @f@ computes some data upon being partially
674
+ -- applied to its first argument. The way @f@ gets accumulated also ensures
675
+ -- sharing for the middle section.
676
+ --
677
+ -- - the fourth argument is the middle part @midxs@, always constant.
678
+ --
679
+ -- - the last argument, a tuple of type @Rigid b@, holds all the elements of
680
+ -- @ys@, in three parts: a middle part around which the recursion is
681
+ -- structured, surrounded by a prefix and a suffix that accumulate
682
+ -- elements on the side as we walk down the middle.
683
+ --
684
+ -- === Invariants
685
+ --
686
+ -- > 1. Viewing the various trees as the lists they represent
687
+ -- > (the types of the toList functions are given a few paragraphs below):
688
+ -- >
689
+ -- > toListFTN result
690
+ -- > = (ffirstx <$> (toListThinN m ++ toListD sf))
691
+ -- > ++ (f <$> toListFTE midxs <*> (toListD pr ++ toListThinN m ++ toListD sf))
692
+ -- > ++ (flastx <$> (toListD pr ++ toListThinN m))
693
+ -- >
694
+ -- > 2. s = size m + size pr + size sf
695
+ -- >
696
+ -- > 3. size (ffirstx y) = size (flastx y) = size (f x y) = size y
697
+ -- > for any (x :: a) (y :: b)
698
+ --
699
+ -- Projecting invariant 1 on sizes, using 2 and 3 to simplify, we have the
700
+ -- following corollary.
701
+ -- It is weaker than invariant 1, but it may be easier to keep track of.
702
+ --
703
+ -- > 1a. size result = s * (size midxs + 1) + size m
704
+ --
705
+ -- In invariant 1, the types of the auxiliary functions are as follows
706
+ -- for reference:
707
+ --
708
+ -- > toListFTE :: FingerTree (Elem a) -> [a]
709
+ -- > toListFTN :: FingerTree (Node c) -> [c]
710
+ -- > toListThinN :: Thin (Node b) -> [b]
711
+ -- > toListD :: Digit12 b -> [b]
712
+ liftA2Middle
713
+ :: (b -> c ) -- ^ @ffirstx@
714
+ -> (b -> c ) -- ^ @flastx@
715
+ -> (a -> b -> c ) -- ^ @f@
716
+ -> FingerTree (Elem a ) -- ^ @midxs@
717
+ -> Rigid b -- ^ @Rigid s pr m sf@ (@pr@: prefix, @sf@: suffix)
718
+ -> FingerTree (Node c )
661
719
662
720
-- Not at the bottom yet
663
721
664
- aptyMiddle firstf
665
- lastf
666
- map23
667
- fs
668
- (Rigid s pr (DeepTh sm prm mm sfm) sf)
669
- = Deep (sm + s * (size fs + 1 )) -- note: sm = s - size pr - size sf
670
- (fmap (fmap firstf) (digit12ToDigit prm))
671
- (aptyMiddle (fmap firstf)
672
- (fmap lastf)
673
- (fmap . map23)
674
- fs
675
- (Rigid s (squashL pr prm) mm (squashR sfm sf)))
676
- (fmap (fmap lastf) (digit12ToDigit sfm))
722
+ liftA2Middle
723
+ ffirstx
724
+ flastx
725
+ f
726
+ midxs
727
+ (Rigid s pr (DeepTh sm prm mm sfm) sf)
728
+ -- note: size (DeepTh sm pr mm sfm) = sm = size pr + size mm + size sfm
729
+ = Deep (sm + s * (size midxs + 1 )) -- note: sm = s - size pr - size sf
730
+ (fmap (fmap ffirstx) (digit12ToDigit prm))
731
+ (liftA2Middle
732
+ (fmap ffirstx)
733
+ (fmap flastx)
734
+ (fmap . f)
735
+ midxs
736
+ (Rigid s (squashL pr prm) mm (squashR sfm sf)))
737
+ (fmap (fmap flastx) (digit12ToDigit sfm))
677
738
678
739
-- At the bottom
679
740
680
- aptyMiddle firstf
681
- lastf
682
- map23
683
- fs
684
- (Rigid s pr EmptyTh sf)
685
- = deep
686
- (One (fmap firstf sf))
687
- (mapMulFT s (\ (Elem f) -> fmap (fmap (map23 f)) converted) fs)
688
- (One (fmap lastf pr))
741
+ liftA2Middle
742
+ ffirstx
743
+ flastx
744
+ f
745
+ midxs
746
+ (Rigid s pr EmptyTh sf)
747
+ = deep
748
+ (One (fmap ffirstx sf))
749
+ (mapMulFT s (\ (Elem x) -> fmap (fmap (f x)) converted) midxs)
750
+ (One (fmap flastx pr))
689
751
where converted = node2 pr sf
690
752
691
- aptyMiddle firstf
692
- lastf
693
- map23
694
- fs
695
- (Rigid s pr (SingleTh q) sf)
696
- = deep
697
- (Two (fmap firstf q) (fmap firstf sf))
698
- (mapMulFT s (\ (Elem f) -> fmap (fmap (map23 f)) converted) fs)
699
- (Two (fmap lastf pr) (fmap lastf q))
753
+ liftA2Middle
754
+ ffirstx
755
+ flastx
756
+ f
757
+ midxs
758
+ (Rigid s pr (SingleTh q) sf)
759
+ = deep
760
+ (Two (fmap ffirstx q) (fmap ffirstx sf))
761
+ (mapMulFT s (\ (Elem x) -> fmap (fmap (f x)) converted) midxs)
762
+ (Two (fmap flastx pr) (fmap flastx q))
700
763
where converted = node3 pr q sf
701
764
702
765
digit12ToDigit :: Digit12 a -> Digit a
0 commit comments