Skip to content

Commit c2b2048

Browse files
committed
Improve *>
Use `applicativeTree` and techniques from `<*>` to make `*>` share as much as possible and offer immediate access with correct time bounds.
1 parent 3a177c7 commit c2b2048

File tree

1 file changed

+75
-14
lines changed

1 file changed

+75
-14
lines changed

Data/Sequence.hs

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -271,13 +271,13 @@ instance Monad Seq where
271271

272272
instance Applicative Seq where
273273
pure = singleton
274-
xs *> ys = replicateSeq (length xs) ys
274+
xs *> ys = cycleN (length xs) ys
275275

276-
fs <*> xs = case viewl fs of
276+
fs <*> xs@(Seq xsFT) = case viewl fs of
277277
EmptyL -> empty
278278
firstf :< fs' -> case viewr fs' of
279279
EmptyR -> fmap firstf xs
280-
Seq fs''FT :> lastf -> case (rigidify . (\(Seq a) -> a)) xs of
280+
Seq fs''FT :> lastf -> case rigidify xsFT of
281281
RigidEmpty -> empty
282282
RigidOne (Elem x) -> fmap ($x) fs
283283
RigidTwo (Elem x1) (Elem x2) ->
@@ -933,18 +933,79 @@ replicateM n x
933933
| n >= 0 = unwrapMonad (replicateA n (WrapMonad x))
934934
| otherwise = error "replicateM takes a nonnegative integer argument"
935935

936-
-- | @'replicateSeq' n xs@ concatenates @n@ copies of @xs@.
937-
replicateSeq :: Int -> Seq a -> Seq a
938-
replicateSeq n s
939-
| n < 0 = error "replicateSeq takes a nonnegative integer argument"
936+
-- | @'cycleN' n xs@ concatenates @n@ copies of @xs@.
937+
cycleN :: Int -> Seq a -> Seq a
938+
cycleN n xs
939+
| n < 0 = error "cycleN takes a nonnegative integer argument"
940940
| n == 0 = empty
941-
| otherwise = go n s
942-
where
943-
-- Invariant: k >= 1
944-
go 1 xs = xs
945-
go k xs | even k = kxs
946-
| otherwise = xs >< kxs
947-
where kxs = go (k `quot` 2) $! (xs >< xs)
941+
| n == 1 = xs
942+
cycleN n (Seq xsFT) = case rigidify xsFT of
943+
RigidEmpty -> empty
944+
RigidOne (Elem x) -> replicate n x
945+
RigidTwo x1 x2 -> Seq $
946+
Deep (n*2) pair
947+
(runIdentity $ applicativeTree (n-2) 2 (Identity (node2 x1 x2)))
948+
pair
949+
where pair = Two x1 x2
950+
RigidThree x1 x2 x3 -> Seq $
951+
Deep (n*3) triple
952+
(runIdentity $ applicativeTree (n-2) 3 (Identity (node3 x1 x2 x3)))
953+
triple
954+
where triple = Three x1 x2 x3
955+
RigidFull r@(Rigid s pr _m sf) -> Seq $
956+
Deep (n*s)
957+
(nodeToDigit pr)
958+
(cycleNMiddle (n-2) r)
959+
(nodeToDigit sf)
960+
961+
cycleNMiddle
962+
:: Sized c => Int
963+
-> Rigid c
964+
-> FingerTree (Node c)
965+
966+
STRICT_1_OF_2(cycleNMiddle)
967+
968+
-- Not at the bottom yet
969+
970+
cycleNMiddle n
971+
(Rigid s pr (DeepTh sm prm mm sfm) sf)
972+
= Deep (sm + s * (n + 1)) -- note: sm = s - size pr - size sf
973+
(digit12ToDigit prm)
974+
(cycleNMiddle n
975+
(Rigid s (squashL pr prm) mm (squashR sfm sf)))
976+
(digit12ToDigit sfm)
977+
978+
-- At the bottom
979+
980+
cycleNMiddle n
981+
(Rigid s pr EmptyTh sf)
982+
= deep
983+
(One sf)
984+
(runIdentity $ applicativeTree n s (Identity converted))
985+
(One pr)
986+
where converted = node2 pr sf
987+
988+
cycleNMiddle n
989+
(Rigid s pr (SingleTh q) sf)
990+
= deep
991+
(Two q sf)
992+
(runIdentity $ applicativeTree n s (Identity converted))
993+
(Two pr q)
994+
where converted = node3 pr q sf
995+
996+
{-# SPECIALIZE
997+
cycleNMiddle
998+
:: Int
999+
-> Rigid (Node c)
1000+
-> FingerTree (Node (Node c))
1001+
#-}
1002+
{-# SPECIALIZE
1003+
cycleNMiddle
1004+
:: Int
1005+
-> Rigid (Elem c)
1006+
-> FingerTree (Node (Elem c))
1007+
#-}
1008+
9481009

9491010
-- | /O(1)/. Add an element to the left end of a sequence.
9501011
-- Mnemonic: a triangle with the single element at the pointy end.

0 commit comments

Comments
 (0)