Skip to content

Commit 660a181

Browse files
committed
Legalize scanl1/scanr1 over an empty vector
Now scanl1, scanl1', scanr1, scanr1' gives an empty vector for an empty input. The definitions of these functions working on vectors, bundles and streams, the documentations attached to these definitions, and the related tests are correspondingly modified. In the former definition, the functions scanl1 and scanr1 refused to process empty vector and simply errorred. However these functions could, and now they do, simply return an empty vector in case of the absence of elements, as the corresponding functions in Data.List in base do. With this modification, @ postscanl' (<>) mempty @ can be rewritten to more generally applicable @ scanl1' (<>) @.
1 parent e7d09b8 commit 660a181

File tree

9 files changed

+42
-42
lines changed

9 files changed

+42
-42
lines changed

vector/src/Data/Vector.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,7 +1929,7 @@ iscanl' :: (Int -> a -> b -> a) -> a -> Vector b -> Vector a
19291929
{-# INLINE iscanl' #-}
19301930
iscanl' = G.iscanl'
19311931

1932-
-- | /O(n)/ Scan over a non-empty vector
1932+
-- | /O(n)/ Initial-value free scan over a vector
19331933
--
19341934
-- > scanl f <x1,...,xn> = <y1,...,yn>
19351935
-- > where y1 = x1
@@ -1939,7 +1939,7 @@ scanl1 :: (a -> a -> a) -> Vector a -> Vector a
19391939
{-# INLINE scanl1 #-}
19401940
scanl1 = G.scanl1
19411941

1942-
-- | /O(n)/ Scan over a non-empty vector with a strict accumulator
1942+
-- | /O(n)/ Initial-value free scan over a vector with a strict accumulator
19431943
scanl1' :: (a -> a -> a) -> Vector a -> Vector a
19441944
{-# INLINE scanl1' #-}
19451945
scanl1' = G.scanl1'
@@ -1993,12 +1993,12 @@ iscanr' :: (Int -> a -> b -> b) -> b -> Vector a -> Vector b
19931993
{-# INLINE iscanr' #-}
19941994
iscanr' = G.iscanr'
19951995

1996-
-- | /O(n)/ Right-to-left scan over a non-empty vector
1996+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector
19971997
scanr1 :: (a -> a -> a) -> Vector a -> Vector a
19981998
{-# INLINE scanr1 #-}
19991999
scanr1 = G.scanr1
20002000

2001-
-- | /O(n)/ Right-to-left scan over a non-empty vector with a strict
2001+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector with a strict
20022002
-- accumulator
20032003
scanr1' :: (a -> a -> a) -> Vector a -> Vector a
20042004
{-# INLINE scanr1' #-}

vector/src/Data/Vector/Fusion/Bundle.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,12 +475,12 @@ scanl' :: (a -> b -> a) -> a -> Bundle v b -> Bundle v a
475475
{-# INLINE scanl' #-}
476476
scanl' = M.scanl'
477477

478-
-- | Scan over a non-empty 'Bundle'
478+
-- | Initial-value free scan over a 'Bundle'
479479
scanl1 :: (a -> a -> a) -> Bundle v a -> Bundle v a
480480
{-# INLINE scanl1 #-}
481481
scanl1 = M.scanl1
482482

483-
-- | Scan over a non-empty 'Bundle' with a strict accumulator
483+
-- | Initial-value free scan over a 'Bundle' with a strict accumulator
484484
scanl1' :: (a -> a -> a) -> Bundle v a -> Bundle v a
485485
{-# INLINE scanl1' #-}
486486
scanl1' = M.scanl1'

vector/src/Data/Vector/Fusion/Bundle/Monadic.hs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -749,23 +749,23 @@ scanlM' :: Monad m => (a -> b -> m a) -> a -> Bundle m v b -> Bundle m v a
749749
{-# INLINE scanlM' #-}
750750
scanlM' f z s = z `seq` (z `cons` postscanlM f z s)
751751

752-
-- | Scan over a non-empty 'Bundle'
752+
-- | Initial-value free scan over a 'Bundle'
753753
scanl1 :: Monad m => (a -> a -> a) -> Bundle m v a -> Bundle m v a
754754
{-# INLINE scanl1 #-}
755755
scanl1 f = scanl1M (\x y -> return (f x y))
756756

757-
-- | Scan over a non-empty 'Bundle' with a monadic operator
757+
-- | Initial-value free scan over a 'Bundle' with a monadic operator
758758
scanl1M :: Monad m => (a -> a -> m a) -> Bundle m v a -> Bundle m v a
759759
{-# INLINE_FUSED scanl1M #-}
760760
scanl1M f Bundle{sElems = s, sSize = sz} = fromStream (S.scanl1M f s) sz
761761

762-
-- | Scan over a non-empty 'Bundle' with a strict accumulator
762+
-- | Initial-value free scan over a 'Bundle' with a strict accumulator
763763
scanl1' :: Monad m => (a -> a -> a) -> Bundle m v a -> Bundle m v a
764764
{-# INLINE scanl1' #-}
765765
scanl1' f = scanl1M' (\x y -> return (f x y))
766766

767-
-- | Scan over a non-empty 'Bundle' with a strict accumulator and a monadic
768-
-- operator
767+
-- | Initial-value free scan over a 'Bundle' with a strict accumulator
768+
-- and a monadic operator
769769
scanl1M' :: Monad m => (a -> a -> m a) -> Bundle m v a -> Bundle m v a
770770
{-# INLINE_FUSED scanl1M' #-}
771771
scanl1M' f Bundle{sElems = s, sSize = sz} = fromStream (S.scanl1M' f s) sz

vector/src/Data/Vector/Fusion/Stream/Monadic.hs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,12 +1262,12 @@ scanlM' :: Monad m => (a -> b -> m a) -> a -> Stream m b -> Stream m a
12621262
{-# INLINE scanlM' #-}
12631263
scanlM' f z s = z `seq` (z `cons` postscanlM f z s)
12641264

1265-
-- | Scan over a non-empty 'Stream'
1265+
-- | Initial-value free scan over a 'Stream'
12661266
scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
12671267
{-# INLINE scanl1 #-}
12681268
scanl1 f = scanl1M (\x y -> return (f x y))
12691269

1270-
-- | Scan over a non-empty 'Stream' with a monadic operator
1270+
-- | Initial-value free scan over a 'Stream' with a monadic operator
12711271
scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
12721272
{-# INLINE_FUSED scanl1M #-}
12731273
scanl1M f (Stream step t) = Stream step' (t, Nothing)
@@ -1278,7 +1278,7 @@ scanl1M f (Stream step t) = Stream step' (t, Nothing)
12781278
case r of
12791279
Yield x s' -> return $ Yield x (s', Just x)
12801280
Skip s' -> return $ Skip (s', Nothing)
1281-
Done -> EMPTY_STREAM "scanl1M"
1281+
Done -> return Done
12821282

12831283
step' (s, Just x) = do
12841284
r <- step s
@@ -1289,13 +1289,13 @@ scanl1M f (Stream step t) = Stream step' (t, Nothing)
12891289
Skip s' -> return $ Skip (s', Just x)
12901290
Done -> return Done
12911291

1292-
-- | Scan over a non-empty 'Stream' with a strict accumulator
1292+
-- | Initial-value free scan over a 'Stream' with a strict accumulator
12931293
scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
12941294
{-# INLINE scanl1' #-}
12951295
scanl1' f = scanl1M' (\x y -> return (f x y))
12961296

1297-
-- | Scan over a non-empty 'Stream' with a strict accumulator and a monadic
1298-
-- operator
1297+
-- | Initial-value free scan over a 'Stream' with a strict accumulator
1298+
-- and a monadic operator
12991299
scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
13001300
{-# INLINE_FUSED scanl1M' #-}
13011301
scanl1M' f (Stream step t) = Stream step' (t, Nothing)
@@ -1306,7 +1306,7 @@ scanl1M' f (Stream step t) = Stream step' (t, Nothing)
13061306
case r of
13071307
Yield x s' -> x `seq` return (Yield x (s', Just x))
13081308
Skip s' -> return $ Skip (s', Nothing)
1309-
Done -> EMPTY_STREAM "scanl1M"
1309+
Done -> return Done
13101310

13111311
step' (s, Just x) = x `seq`
13121312
do

vector/src/Data/Vector/Generic.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,7 +2111,7 @@ iscanl' f z =
21112111
. stream
21122112

21132113

2114-
-- | /O(n)/ Scan over a non-empty vector
2114+
-- | /O(n)/ Initial-value free scan over a vector
21152115
--
21162116
-- > scanl f <x1,...,xn> = <y1,...,yn>
21172117
-- > where y1 = x1
@@ -2121,7 +2121,7 @@ scanl1 :: Vector v a => (a -> a -> a) -> v a -> v a
21212121
{-# INLINE scanl1 #-}
21222122
scanl1 f = unstream . inplace (S.scanl1 f) id . stream
21232123

2124-
-- | /O(n)/ Scan over a non-empty vector with a strict accumulator
2124+
-- | /O(n)/ Initial-value free scan over a vector with a strict accumulator
21252125
scanl1' :: Vector v a => (a -> a -> a) -> v a -> v a
21262126
{-# INLINE scanl1' #-}
21272127
scanl1' f = unstream . inplace (S.scanl1' f) id . stream
@@ -2181,12 +2181,12 @@ iscanr' f z v =
21812181
$ v
21822182
where n = length v
21832183

2184-
-- | /O(n)/ Right-to-left scan over a non-empty vector
2184+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector
21852185
scanr1 :: Vector v a => (a -> a -> a) -> v a -> v a
21862186
{-# INLINE scanr1 #-}
21872187
scanr1 f = unstreamR . inplace (S.scanl1 (flip f)) id . streamR
21882188

2189-
-- | /O(n)/ Right-to-left scan over a non-empty vector with a strict
2189+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector with a strict
21902190
-- accumulator
21912191
scanr1' :: Vector v a => (a -> a -> a) -> v a -> v a
21922192
{-# INLINE scanr1' #-}

vector/src/Data/Vector/Primitive.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,7 @@ iscanl' :: (Prim a, Prim b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector a
15821582
iscanl' = G.iscanl'
15831583

15841584

1585-
-- | /O(n)/ Scan over a non-empty vector
1585+
-- | /O(n)/ Initial-value free scan over a vector
15861586
--
15871587
-- > scanl f <x1,...,xn> = <y1,...,yn>
15881588
-- > where y1 = x1
@@ -1592,7 +1592,7 @@ scanl1 :: Prim a => (a -> a -> a) -> Vector a -> Vector a
15921592
{-# INLINE scanl1 #-}
15931593
scanl1 = G.scanl1
15941594

1595-
-- | /O(n)/ Scan over a non-empty vector with a strict accumulator
1595+
-- | /O(n)/ Initial-value free scan over a vector with a strict accumulator
15961596
scanl1' :: Prim a => (a -> a -> a) -> Vector a -> Vector a
15971597
{-# INLINE scanl1' #-}
15981598
scanl1' = G.scanl1'
@@ -1646,12 +1646,12 @@ iscanr' :: (Prim a, Prim b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector b
16461646
{-# INLINE iscanr' #-}
16471647
iscanr' = G.iscanr'
16481648

1649-
-- | /O(n)/ Right-to-left scan over a non-empty vector
1649+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector
16501650
scanr1 :: Prim a => (a -> a -> a) -> Vector a -> Vector a
16511651
{-# INLINE scanr1 #-}
16521652
scanr1 = G.scanr1
16531653

1654-
-- | /O(n)/ Right-to-left scan over a non-empty vector with a strict
1654+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector with a strict
16551655
-- accumulator
16561656
scanr1' :: Prim a => (a -> a -> a) -> Vector a -> Vector a
16571657
{-# INLINE scanr1' #-}

vector/src/Data/Vector/Storable.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,7 @@ iscanl' :: (Storable a, Storable b) => (Int -> a -> b -> a) -> a -> Vector b ->
16281628
{-# INLINE iscanl' #-}
16291629
iscanl' = G.iscanl'
16301630

1631-
-- | /O(n)/ Scan over a non-empty vector
1631+
-- | /O(n)/ Initial-value free scan over a vector
16321632
--
16331633
-- > scanl f <x1,...,xn> = <y1,...,yn>
16341634
-- > where y1 = x1
@@ -1638,7 +1638,7 @@ scanl1 :: Storable a => (a -> a -> a) -> Vector a -> Vector a
16381638
{-# INLINE scanl1 #-}
16391639
scanl1 = G.scanl1
16401640

1641-
-- | /O(n)/ Scan over a non-empty vector with a strict accumulator
1641+
-- | /O(n)/ Initial-value free scan over a vector with a strict accumulator
16421642
scanl1' :: Storable a => (a -> a -> a) -> Vector a -> Vector a
16431643
{-# INLINE scanl1' #-}
16441644
scanl1' = G.scanl1'
@@ -1692,12 +1692,12 @@ iscanr' :: (Storable a, Storable b) => (Int -> a -> b -> b) -> b -> Vector a ->
16921692
{-# INLINE iscanr' #-}
16931693
iscanr' = G.iscanr'
16941694

1695-
-- | /O(n)/ Right-to-left scan over a non-empty vector
1695+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector
16961696
scanr1 :: Storable a => (a -> a -> a) -> Vector a -> Vector a
16971697
{-# INLINE scanr1 #-}
16981698
scanr1 = G.scanr1
16991699

1700-
-- | /O(n)/ Right-to-left scan over a non-empty vector with a strict
1700+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector with a strict
17011701
-- accumulator
17021702
scanr1' :: Storable a => (a -> a -> a) -> Vector a -> Vector a
17031703
{-# INLINE scanr1' #-}

vector/src/Data/Vector/Unboxed.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,7 +1678,7 @@ iscanl' :: (Unbox a, Unbox b) => (Int -> a -> b -> a) -> a -> Vector b -> Vector
16781678
{-# INLINE iscanl' #-}
16791679
iscanl' = G.iscanl'
16801680

1681-
-- | /O(n)/ Scan over a non-empty vector
1681+
-- | /O(n)/ Initial-value free scan over a vector
16821682
--
16831683
-- > scanl f <x1,...,xn> = <y1,...,yn>
16841684
-- > where y1 = x1
@@ -1688,7 +1688,7 @@ scanl1 :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
16881688
{-# INLINE scanl1 #-}
16891689
scanl1 = G.scanl1
16901690

1691-
-- | /O(n)/ Scan over a non-empty vector with a strict accumulator
1691+
-- | /O(n)/ Initial-value free scan over a vector with a strict accumulator
16921692
scanl1' :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
16931693
{-# INLINE scanl1' #-}
16941694
scanl1' = G.scanl1'
@@ -1742,12 +1742,12 @@ iscanr' :: (Unbox a, Unbox b) => (Int -> a -> b -> b) -> b -> Vector a -> Vector
17421742
{-# INLINE iscanr' #-}
17431743
iscanr' = G.iscanr'
17441744

1745-
-- | /O(n)/ Right-to-left scan over a non-empty vector
1745+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector
17461746
scanr1 :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
17471747
{-# INLINE scanr1 #-}
17481748
scanr1 = G.scanr1
17491749

1750-
-- | /O(n)/ Right-to-left scan over a non-empty vector with a strict
1750+
-- | /O(n)/ Right-to-left, initial-value free scan over a vector with a strict
17511751
-- accumulator
17521752
scanr1' :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
17531753
{-# INLINE scanr1' #-}

vector/tests/Tests/Vector/Property.hs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,10 @@ testPolymorphicFunctions _ = $(testProperties [
395395
= V.scanl `eq` scanl
396396
prop_scanl' :: P ((a -> a -> a) -> a -> v a -> v a)
397397
= V.scanl' `eq` scanl
398-
prop_scanl1 :: P ((a -> a -> a) -> v a -> v a) = notNull2 ===>
399-
V.scanl1 `eq` scanl1
400-
prop_scanl1' :: P ((a -> a -> a) -> v a -> v a) = notNull2 ===>
401-
V.scanl1' `eq` scanl1
398+
prop_scanl1 :: P ((a -> a -> a) -> v a -> v a)
399+
= V.scanl1 `eq` scanl1
400+
prop_scanl1' :: P ((a -> a -> a) -> v a -> v a)
401+
= V.scanl1' `eq` scanl1
402402
prop_iscanl :: P ((Int -> a -> a -> a) -> a -> v a -> v a)
403403
= V.iscanl `eq` iscanl
404404
prop_iscanl' :: P ((Int -> a -> a -> a) -> a -> v a -> v a)
@@ -420,10 +420,10 @@ testPolymorphicFunctions _ = $(testProperties [
420420
= V.iscanr `eq` iscanr
421421
prop_iscanr' :: P ((Int -> a -> a -> a) -> a -> v a -> v a)
422422
= V.iscanr' `eq` iscanr
423-
prop_scanr1 :: P ((a -> a -> a) -> v a -> v a) = notNull2 ===>
424-
V.scanr1 `eq` scanr1
425-
prop_scanr1' :: P ((a -> a -> a) -> v a -> v a) = notNull2 ===>
426-
V.scanr1' `eq` scanr1
423+
prop_scanr1 :: P ((a -> a -> a) -> v a -> v a)
424+
= V.scanr1 `eq` scanr1
425+
prop_scanr1' :: P ((a -> a -> a) -> v a -> v a)
426+
= V.scanr1' `eq` scanr1
427427

428428
prop_concatMap = forAll arbitrary $ \xs ->
429429
forAll (sized (\n -> resize (n `div` V.length xs) arbitrary)) $ \f -> unP prop f xs

0 commit comments

Comments
 (0)