Skip to content

Commit 40f5b0a

Browse files
authored
Merge pull request #83 from purescript/filterA
Add filterA, a faster version of filterM
2 parents 54e5240 + 2d3d60e commit 40f5b0a

File tree

3 files changed

+21
-12
lines changed

3 files changed

+21
-12
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
},
2727
"devDependencies": {
2828
"purescript-assert": "^2.0.0",
29-
"purescript-console": "^2.0.0"
29+
"purescript-console": "^2.0.0",
30+
"purescript-const": "^2.0.0"
3031
}
3132
}

src/Data/Array.purs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ module Data.Array
6767
, concatMap
6868
, filter
6969
, partition
70+
, filterA
7071
, filterM
7172
, mapMaybe
7273
, catMaybes
@@ -121,7 +122,7 @@ import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, f
121122
import Data.Maybe (Maybe(..), maybe, isJust, fromJust)
122123
import Data.NonEmpty (NonEmpty, (:|))
123124
import Data.Traversable (scanl, scanr) as Exports
124-
import Data.Traversable (sequence)
125+
import Data.Traversable (sequence, traverse)
125126
import Data.Tuple (Tuple(..))
126127
import Data.Unfoldable (class Unfoldable, unfoldr)
127128

@@ -417,17 +418,20 @@ foreign import partition
417418
-> Array a
418419
-> { yes :: Array a, no :: Array a }
419420

420-
-- | Filter where the predicate returns a monadic `Boolean`.
421+
-- | Filter where the predicate returns a `Boolean` in some `Applicative`.
421422
-- |
422423
-- | ```purescript
423-
-- | powerSet :: forall a. [a] -> [[a]]
424-
-- | powerSet = filterM (const [true, false])
424+
-- | powerSet :: forall a. Array a -> Array (Array a)
425+
-- | powerSet = filterA (const [true, false])
425426
-- | ```
427+
filterA :: forall a f. Applicative f => (a -> f Boolean) -> Array a -> f (Array a)
428+
filterA p =
429+
traverse (\x -> Tuple x <$> p x)
430+
>>> map (mapMaybe (\(Tuple x b) -> if b then Just x else Nothing))
431+
432+
-- | Deprecated alias for `filterA`.
426433
filterM :: forall a m. Monad m => (a -> m Boolean) -> Array a -> m (Array a)
427-
filterM p = uncons' (\_ -> pure []) \x xs -> do
428-
b <- p x
429-
xs' <- filterM p xs
430-
pure if b then x : xs' else xs'
434+
filterM = filterA
431435

432436
-- | Apply a function to each element in an array, keeping only the results
433437
-- | which contain a value, creating a new array.

test/Test/Data/Array.purs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Prelude
55
import Control.Monad.Eff (Eff)
66
import Control.Monad.Eff.Console (log, CONSOLE)
77

8+
import Data.Const (Const(..))
89
import Data.Array as A
910
import Data.Array ((:), (\\), (!!))
1011
import Data.Foldable (for_, foldMapDefaultR, class Foldable, all, traverse_)
@@ -205,9 +206,12 @@ testArray = do
205206
log "filter should remove items that don't match a predicate"
206207
assert $ A.filter odd (A.range 0 10) == [1, 3, 5, 7, 9]
207208

208-
log "filterM should remove items that don't match a predicate while using a monadic behaviour"
209-
assert $ A.filterM (Just <<< odd) (A.range 0 10) == Just [1, 3, 5, 7, 9]
210-
assert $ A.filterM (const Nothing) (A.range 0 10) == Nothing
209+
log "filterA should remove items that don't match a predicate while using an applicative behaviour"
210+
assert $ A.filterA (Just <<< odd) (A.range 0 10) == Just [1, 3, 5, 7, 9]
211+
assert $ A.filterA (const Nothing) (A.range 0 10) == Nothing
212+
213+
log "filterA should apply effects in the right order"
214+
assert $ A.filterA (Const <<< show) (A.range 1 5) == Const "12345"
211215

212216
log "mapMaybe should transform every item in an array, throwing out Nothing values"
213217
assert $ A.mapMaybe (\x -> if x /= 0 then Just x else Nothing) [0, 1, 0, 0, 2, 3] == [1, 2, 3]

0 commit comments

Comments
 (0)