Skip to content

Commit 51a1f7c

Browse files
treeowlfoxik
authored andcommitted
Use a top-down version of fromList
Ross Paterson came up with a version of fromList that avoids the tree rebuilding inherent in the `(|>)`-based approach. This version is somewhat strictified and rearranged. It reduces allocation substantially over the old version. Mutator time goes down too, but for some reason GC time rises to match it.
1 parent a556ef2 commit 51a1f7c

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

Data/Sequence.hs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1752,11 +1752,34 @@ findIndicesR p xs = foldlWithIndex g [] xs
17521752
-- Lists
17531753
------------------------------------------------------------------------
17541754

1755+
-- The implementation below, by Ross Paterson, avoids the rebuilding
1756+
-- the previous (|>)-based implementation suffered from.
1757+
17551758
-- | /O(n)/. Create a sequence from a finite list of elements.
17561759
-- There is a function 'toList' in the opposite direction for all
17571760
-- instances of the 'Foldable' class, including 'Seq'.
17581761
fromList :: [a] -> Seq a
1759-
fromList = Data.List.foldl' (|>) empty
1762+
fromList xs = Seq $ mkTree 1 $ Data.List.map Elem xs
1763+
where
1764+
{-# SPECIALIZE mkTree :: Int -> [Elem a] -> FingerTree (Elem a) #-}
1765+
{-# SPECIALIZE mkTree :: Int -> [Node a] -> FingerTree (Node a) #-}
1766+
mkTree :: (Sized a) => Int -> [a] -> FingerTree a
1767+
mkTree s [] = s `seq` Empty
1768+
mkTree s [x1] = s `seq` Single x1
1769+
mkTree s [x1, x2] = Deep (2*s) (One x1) Empty (One x2)
1770+
mkTree s [x1, x2, x3] = Deep (3*s) (One x1) Empty (Two x2 x3)
1771+
mkTree s (x1:x2:x3:xs) = s `seq` case getNodes (3*s) xs of
1772+
(ns, sf) -> m `seq` deep' (Three x1 x2 x3) m sf
1773+
where m = mkTree (3*s) ns
1774+
1775+
deep' pr@(Three x1 _ _) m sf = Deep (3*size x1 + size m + size sf) pr m sf
1776+
1777+
getNodes :: Int -> [a] -> ([Node a], Digit a)
1778+
getNodes s [x1] = s `seq` ([], One x1)
1779+
getNodes s [x1, x2] = s `seq` ([], Two x1 x2)
1780+
getNodes s [x1, x2, x3] = s `seq` ([], Three x1 x2 x3)
1781+
getNodes s (x1:x2:x3:xs) = s `seq` (Node3 s x1 x2 x3:ns, d)
1782+
where (ns, d) = getNodes s xs
17601783

17611784
#if __GLASGOW_HASKELL__ >= 708
17621785
instance GHC.Exts.IsList (Seq a) where

0 commit comments

Comments
 (0)