From a22f493acef4370be9381461ea32921c56d19f01 Mon Sep 17 00:00:00 2001 From: Cyril Sobierajewicz Date: Sat, 19 Dec 2020 19:42:03 +0100 Subject: [PATCH 1/2] Export specialized any and all from Data.Array and Data.Array.NonEmpty --- src/Data/Array.js | 24 ++++++++++++++++++++++++ src/Data/Array.purs | 13 +++++++++++-- src/Data/Array/NonEmpty.purs | 9 +++++++++ test/Test/Data/Array.purs | 10 ++++++++++ test/Test/Data/Array/NonEmpty.purs | 8 ++++++++ 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/Data/Array.js b/src/Data/Array.js index 8f0d63d3..e0f85d72 100644 --- a/src/Data/Array.js +++ b/src/Data/Array.js @@ -307,6 +307,30 @@ exports.zipWith = function (f) { }; }; +//------------------------------------------------------------------------------ +// Folding --------------------------------------------------------------------- +//------------------------------------------------------------------------------ + +exports.any = function (p) { + return function (xs) { + var len = xs.length; + for (var i = 0; i < len; i++) { + if (p(xs[i])) return true; + } + return false; + }; +}; + +exports.all = function (p) { + return function (xs) { + var len = xs.length; + for (var i = 0; i < len; i++) { + if (!p(xs[i])) return false; + } + return true; + }; +}; + //------------------------------------------------------------------------------ // Partial --------------------------------------------------------------------- //------------------------------------------------------------------------------ diff --git a/src/Data/Array.purs b/src/Data/Array.purs index 0364390a..4521fcfd 100644 --- a/src/Data/Array.purs +++ b/src/Data/Array.purs @@ -115,6 +115,9 @@ module Data.Array , zip , unzip + , any + , all + , foldM , foldRecM @@ -134,7 +137,7 @@ import Data.Array.NonEmpty.Internal (NonEmptyArray(..)) import Data.Array.ST as STA import Data.Array.ST.Iterator as STAI import Data.Foldable (class Foldable, foldl, foldr, traverse_) -import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, any, all) as Exports +import Data.Foldable (foldl, foldr, foldMap, fold, intercalate) as Exports import Data.Maybe (Maybe(..), maybe, isJust, fromJust, isNothing) import Data.Traversable (sequence, traverse) import Data.Tuple (Tuple(..), fst, snd) @@ -1035,7 +1038,7 @@ nubByEq :: forall a. (a -> a -> Boolean) -> Array a -> Array a nubByEq eq xs = ST.run do arr <- STA.empty ST.foreach xs \x -> do - e <- not <<< Exports.any (_ `eq` x) <$> (STA.unsafeFreeze arr) + e <- not <<< any (_ `eq` x) <$> (STA.unsafeFreeze arr) when e $ void $ STA.push x arr STA.unsafeFreeze arr @@ -1192,6 +1195,12 @@ unzip xs = snds' <- STA.unsafeFreeze snds pure $ Tuple fsts' snds' +-- | Returns true if at least one array element satisfy the given predicate. +foreign import any :: forall a. (a -> Boolean) -> Array a -> Boolean + +-- | Returns true if all the array elements satisfy the given predicate. +foreign import all :: forall a. (a -> Boolean) -> Array a -> Boolean + -- | Perform a fold using a monadic step function. -- | -- | ```purescript diff --git a/src/Data/Array/NonEmpty.purs b/src/Data/Array/NonEmpty.purs index 0f9d4415..be90f846 100644 --- a/src/Data/Array/NonEmpty.purs +++ b/src/Data/Array/NonEmpty.purs @@ -89,6 +89,9 @@ module Data.Array.NonEmpty , zip , unzip + , any + , all + , foldM , foldRecM @@ -438,6 +441,12 @@ zip xs ys = unsafeFromArray $ toArray xs `A.zip` toArray ys unzip :: forall a b. NonEmptyArray (Tuple a b) -> Tuple (NonEmptyArray a) (NonEmptyArray b) unzip = bimap unsafeFromArray unsafeFromArray <<< A.unzip <<< toArray +any :: forall a. (a -> Boolean) -> NonEmptyArray a -> Boolean +any p = adaptAny $ A.any p + +all :: forall a. (a -> Boolean) -> NonEmptyArray a -> Boolean +all p = adaptAny $ A.all p + foldM :: forall m a b. Monad m => (b -> a -> m b) -> b -> NonEmptyArray a -> m b foldM f acc = adaptAny $ A.foldM f acc diff --git a/test/Test/Data/Array.purs b/test/Test/Data/Array.purs index 08174c4f..be147e6f 100644 --- a/test/Test/Data/Array.purs +++ b/test/Test/Data/Array.purs @@ -415,6 +415,16 @@ testArray = do log "unzip should deconstruct a list of tuples into a tuple of lists" assert $ A.unzip [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"] == Tuple [1, 2, 3] ["a", "b", "c"] + log "any should return true if at least one array element satisfy the given predicate" + assert $ not $ A.any (_ > 2) [] + assert $ A.any (_ > 2) [1, 2, 3] + assert $ not $ A.any (_ > 3) [1, 2, 3] + + log "all should return true if all the array elements satisfy the given predicate" + assert $ A.all (_ > 0) [] + assert $ A.all (_ > 0) [1, 2, 3] + assert $ not $ A.all (_ > 1) [1, 2, 3] + log "foldM should perform a fold using a monadic step function" assert $ A.foldM (\x y -> Just (x + y)) 0 (A.range 1 10) == Just 55 assert $ A.foldM (\_ _ -> Nothing) 0 (A.range 1 10) == Nothing diff --git a/test/Test/Data/Array/NonEmpty.purs b/test/Test/Data/Array/NonEmpty.purs index b42c08e9..d8ca501c 100644 --- a/test/Test/Data/Array/NonEmpty.purs +++ b/test/Test/Data/Array/NonEmpty.purs @@ -285,6 +285,14 @@ testNonEmptyArray = do log "unzip should deconstruct a list of tuples into a tuple of lists" assert $ NEA.unzip (fromArray [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"]) == Tuple (fromArray [1, 2, 3]) (fromArray ["a", "b", "c"]) + log "any should return true if at least one array element satisfy the given predicate" + assert $ NEA.any (_ > 2) $ fromArray [1, 2, 3] + assert $ not $ NEA.any (_ > 3) $ fromArray [1, 2, 3] + + log "all should return true if all the array elements satisfy the given predicate" + assert $ NEA.all (_ > 0) $ fromArray [1, 2, 3] + assert $ not $ NEA.all (_ > 1) $ fromArray [1, 2, 3] + log "fromFoldable" for_ (fromArray [[], [1], [1,2], [1,2,3,4,5]]) \xs -> do assert $ NEA.fromFoldable xs == NEA.fromArray xs From 7bcd5728449b29c92a161b6cd7fcba1f21451646 Mon Sep 17 00:00:00 2001 From: Cyril Sobierajewicz Date: Sun, 20 Dec 2020 00:26:11 +0100 Subject: [PATCH 2/2] Update documentation and tests --- src/Data/Array.purs | 18 +++++++++++++++++- test/Test/Data/Array.purs | 8 ++++---- test/Test/Data/Array/NonEmpty.purs | 6 +++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Data/Array.purs b/src/Data/Array.purs index 4521fcfd..811081d8 100644 --- a/src/Data/Array.purs +++ b/src/Data/Array.purs @@ -1195,10 +1195,26 @@ unzip xs = snds' <- STA.unsafeFreeze snds pure $ Tuple fsts' snds' --- | Returns true if at least one array element satisfy the given predicate. +-- | Returns true if at least one array element satisfies the given predicate, +-- | iterating the array only as necessary and stopping as soon as the predicate +-- | yields true. +-- | +-- | ```purescript +-- | any (_ > 0) [] = False +-- | any (_ > 0) [-1, 0, 1] = True +-- | any (_ > 0) [-1, -2, -3] = False +-- | ``` foreign import any :: forall a. (a -> Boolean) -> Array a -> Boolean -- | Returns true if all the array elements satisfy the given predicate. +-- | iterating the array only as necessary and stopping as soon as the predicate +-- | yields false. +-- | +-- | ```purescript +-- | all (_ > 0) [] = True +-- | all (_ > 0) [1, 2, 3] = True +-- | all (_ > 0) [-1, -2, -3] = False +-- | ``` foreign import all :: forall a. (a -> Boolean) -> Array a -> Boolean -- | Perform a fold using a monadic step function. diff --git a/test/Test/Data/Array.purs b/test/Test/Data/Array.purs index be147e6f..e1b7f460 100644 --- a/test/Test/Data/Array.purs +++ b/test/Test/Data/Array.purs @@ -416,14 +416,14 @@ testArray = do assert $ A.unzip [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"] == Tuple [1, 2, 3] ["a", "b", "c"] log "any should return true if at least one array element satisfy the given predicate" - assert $ not $ A.any (_ > 2) [] - assert $ A.any (_ > 2) [1, 2, 3] - assert $ not $ A.any (_ > 3) [1, 2, 3] + assert $ not $ A.any (_ > 0) [] + assert $ A.any (_ > 0) [-1, 0, 1] + assert $ not $ A.any (_ > 0) [-1, -2, -3] log "all should return true if all the array elements satisfy the given predicate" assert $ A.all (_ > 0) [] assert $ A.all (_ > 0) [1, 2, 3] - assert $ not $ A.all (_ > 1) [1, 2, 3] + assert $ not $ A.all (_ > 0) [-1, -2, -3] log "foldM should perform a fold using a monadic step function" assert $ A.foldM (\x y -> Just (x + y)) 0 (A.range 1 10) == Just 55 diff --git a/test/Test/Data/Array/NonEmpty.purs b/test/Test/Data/Array/NonEmpty.purs index d8ca501c..9db55f4d 100644 --- a/test/Test/Data/Array/NonEmpty.purs +++ b/test/Test/Data/Array/NonEmpty.purs @@ -286,12 +286,12 @@ testNonEmptyArray = do assert $ NEA.unzip (fromArray [Tuple 1 "a", Tuple 2 "b", Tuple 3 "c"]) == Tuple (fromArray [1, 2, 3]) (fromArray ["a", "b", "c"]) log "any should return true if at least one array element satisfy the given predicate" - assert $ NEA.any (_ > 2) $ fromArray [1, 2, 3] - assert $ not $ NEA.any (_ > 3) $ fromArray [1, 2, 3] + assert $ NEA.any (_ > 0) $ fromArray [-1, 0, 1] + assert $ not $ NEA.any (_ > 0) $ fromArray [-1, -2, -3] log "all should return true if all the array elements satisfy the given predicate" assert $ NEA.all (_ > 0) $ fromArray [1, 2, 3] - assert $ not $ NEA.all (_ > 1) $ fromArray [1, 2, 3] + assert $ not $ NEA.all (_ > 0) $ fromArray [-1, -2, -3] log "fromFoldable" for_ (fromArray [[], [1], [1,2], [1,2,3,4,5]]) \xs -> do