From 2d7ac79961754dec9d64573d3c1a10a619453efe Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 8 Aug 2017 21:32:38 +0100 Subject: [PATCH] Add extra defaults for `partition` and `filter` This commit adds four new functions: `partitionDefaultFilter`, `partitionDefaultFilterMap`, `filterDefaultPartition`, and `filterDefaultPartitionMap`. --- src/Data/Filterable.purs | 42 ++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/Data/Filterable.purs b/src/Data/Filterable.purs index 1a3ecb6..24786f5 100644 --- a/src/Data/Filterable.purs +++ b/src/Data/Filterable.purs @@ -6,8 +6,12 @@ module Data.Filterable , filter , eitherBool , partitionDefault + , partitionDefaultFilter + , partitionDefaultFilterMap , maybeBool , filterDefault + , filterDefaultPartition + , filterDefaultPartitionMap , partitioned , filtered , cleared @@ -19,9 +23,10 @@ import Data.Array (partition, mapMaybe, filter) as Array import Data.Either (Either(..)) import Data.Foldable (foldl, foldr) import Data.Functor (class Functor) +import Data.HeytingAlgebra (not) import Data.List (List(..), filter, mapMaybe) as List -import Data.Maybe (Maybe(..)) import Data.Map (Map, empty, insert, alter, toUnfoldable) as Map +import Data.Maybe (Maybe(..)) import Data.Monoid (class Monoid, mempty) import Data.Semigroup ((<>)) import Data.Tuple (Tuple(..)) @@ -60,6 +65,11 @@ eitherBool :: forall a. (a -> Boolean) -> a -> Either a a eitherBool p x = if p x then Right x else Left x +-- | Upgrade a boolean-style predicate to a maybe-style predicate mapping. +maybeBool :: forall a. + (a -> Boolean) -> a -> Maybe a +maybeBool p x = if p x then Just x else Nothing + -- | A default implementation of `partition` using `partitionMap`. partitionDefault :: forall f a. Filterable f => (a -> Boolean) -> f a -> { no :: f a, yes :: f a } @@ -67,16 +77,37 @@ partitionDefault p xs = let o = partitionMap (eitherBool p) xs in {no: o.left, yes: o.right} --- | Upgrade a boolean-style predicate to a maybe-style predicate mapping. -maybeBool :: forall a. - (a -> Boolean) -> a -> Maybe a -maybeBool p x = if p x then Just x else Nothing +-- | A default implementation of `partition` using `filter`. Note that this is +-- | almost certainly going to be suboptimal compared to direct implementations. +partitionDefaultFilter :: forall f a. Filterable f => + (a -> Boolean) -> f a -> { no :: f a, yes :: f a } +partitionDefaultFilter p xs = { yes: filter p xs, no: filter (not p) xs } + +-- | A default implementation of `partition` using `filterMap`. Note that this +-- | is almost certainly going to be suboptimal compared to direct +-- | implementations. +partitionDefaultFilterMap :: forall f a. Filterable f => + (a -> Boolean) -> f a -> { no :: f a, yes :: f a } +partitionDefaultFilterMap p xs = + { yes: filterMap (maybeBool p) xs + , no: filterMap (maybeBool (not p)) xs + } -- | A default implementation of `filter` using `filterMap`. filterDefault :: forall f a. Filterable f => (a -> Boolean) -> f a -> f a filterDefault = filterMap <<< maybeBool +-- | A default implementation of `filter` using `partition`. +filterDefaultPartition :: forall f a. Filterable f => + (a -> Boolean) -> f a -> f a +filterDefaultPartition p xs = (partition p xs).yes + +-- | A default implementation of `filter` using `partitionMap`. +filterDefaultPartitionMap :: forall f a. Filterable f => + (a -> Boolean) -> f a -> f a +filterDefaultPartitionMap p xs = (partitionMap (eitherBool p) xs).right + partitioned :: forall f l r. Filterable f => f (Either l r) -> { left :: f l, right :: f r } partitioned = partitionMap id @@ -174,4 +205,3 @@ instance filterableMap :: Ord k => Filterable (Map.Map k) where select (Tuple k x) m = Map.alter (const (p x)) k m filter p = filterDefault p -