Skip to content

Commit f526723

Browse files
authored
Fix partitionDefault and add instances for Map (#9)
1 parent 47c9559 commit f526723

File tree

4 files changed

+50
-3
lines changed

4 files changed

+50
-3
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"purescript-identity": "^3.0.0",
2323
"purescript-arrays": "^4.0.0",
2424
"purescript-either": "^3.0.0",
25-
"purescript-lists": "^4.1.1"
25+
"purescript-lists": "^4.1.1",
26+
"purescript-maps": "^3.0.0"
2627
},
2728
"devDependencies": {
2829
"purescript-assert": "^3.0.0",

src/Data/Filterable.purs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ import Data.Foldable (foldl, foldr)
2121
import Data.Functor (class Functor)
2222
import Data.List (List(..), filter, mapMaybe) as List
2323
import Data.Maybe (Maybe(..))
24+
import Data.Map (Map, empty, insert, alter, toUnfoldable) as Map
2425
import Data.Monoid (class Monoid, mempty)
2526
import Data.Semigroup ((<>))
26-
import Prelude (const)
27+
import Data.Tuple (Tuple(..))
28+
import Prelude (const, class Ord)
2729

2830
-- | `Filterable` represents data structures which can be _partitioned_/_filtered_.
2931
-- |
@@ -56,7 +58,7 @@ class (Functor f) <= Filterable f where
5658
-- | Upgrade a boolean-style predicate to an either-style predicate mapping.
5759
eitherBool :: forall a.
5860
(a -> Boolean) -> a -> Either a a
59-
eitherBool p x = if p x then Left x else Right x
61+
eitherBool p x = if p x then Right x else Left x
6062

6163
-- | A default implementation of `partition` using `partitionMap`.
6264
partitionDefault :: forall f a. Filterable f =>
@@ -149,3 +151,27 @@ instance filterableList :: Filterable List.List where
149151

150152
-- filter :: forall a. (a -> Boolean) -> List a -> List a
151153
filter = List.filter
154+
155+
instance filterableMap :: Ord k => Filterable (Map.Map k) where
156+
partitionMap p xs =
157+
foldr select { left: Map.empty, right: Map.empty } (toList xs)
158+
where
159+
toList :: forall v. Map.Map k v -> List.List (Tuple k v)
160+
toList = Map.toUnfoldable
161+
162+
select (Tuple k x) { left, right } = case p x of
163+
Left l -> { left: Map.insert k l left, right }
164+
Right r -> { left, right: Map.insert k r right }
165+
166+
partition p = partitionDefault p
167+
168+
filterMap p xs =
169+
foldr select Map.empty (toList xs)
170+
where
171+
toList :: forall v. Map.Map k v -> List.List (Tuple k v)
172+
toList = Map.toUnfoldable
173+
174+
select (Tuple k x) m = Map.alter (const (p x)) k m
175+
176+
filter p = filterDefault p
177+

src/Data/Witherable.purs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ import Data.Functor (map)
1818
import Data.Identity (Identity(..))
1919
import Data.List (List)
2020
import Data.Maybe (Maybe(..))
21+
import Data.Map (Map)
2122
import Data.Monoid (class Monoid, mempty)
2223
import Data.Newtype (unwrap)
2324
import Data.Traversable (class Traversable, traverse)
2425
import Data.Unit (unit)
26+
import Prelude (class Ord)
2527

2628
-- | `Witherable` represents data structures which can be _partitioned_ with
2729
-- | effects in some `Applicative` functor.
@@ -94,6 +96,10 @@ instance witherableList :: Witherable List where
9496
wilt p xs = map partitioned (traverse p xs)
9597
wither p xs = map filtered (traverse p xs)
9698

99+
instance witherableMap :: Ord k => Witherable (Map k) where
100+
wilt p xs = map partitioned (traverse p xs)
101+
wither p xs = map filtered (traverse p xs)
102+
97103
instance witherableMaybe :: Witherable Maybe where
98104
wilt p Nothing = pure { left: Nothing, right: Nothing }
99105
wilt p (Just x) = map convert (p x) where

test/Main.purs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import Data.Filterable (filter, filterMap, partition, partitionMap)
88
import Data.Identity (Identity(Identity))
99
import Data.List (List(Nil), (:))
1010
import Data.Maybe (Maybe(..))
11+
import Data.Map (fromFoldable) as Map
12+
import Data.Tuple (Tuple(..))
1113
import Data.Witherable (wither)
1214
import Test.Assert (ASSERT, assert)
1315

@@ -53,4 +55,16 @@ main = do
5355
assert $ filter (_ > 5) [1,2,3,4,5,6,7,8,9] == [6,7,8,9]
5456
assert $ partition (_ > 5) [1,2,3,4,5,6,7,8,9] `testEqNoYes` { no: [1,2,3,4,5], yes: [6,7,8,9]}
5557

58+
log "Test filterableMap instance" *> do
59+
let pred x = if x > 2 then Just (x * 10) else Nothing
60+
let predE x = if x > 2 then Right (x * 10) else Left x
61+
let m = Map.fromFoldable
62+
let xs = m [Tuple 1 1, Tuple 2 2, Tuple 3 3, Tuple 4 4]
63+
assert $ filterMap pred xs == m [Tuple 3 30, Tuple 4 40]
64+
assert $ filter (_ > 2) xs == m [Tuple 3 3, Tuple 4 4]
65+
assert $ partition (_ > 2) xs `testEqNoYes` { no: m [Tuple 1 1, Tuple 2 2]
66+
, yes: m [Tuple 3 3, Tuple 4 4] }
67+
assert $ partitionMap predE xs `testEqLeftRight` { left: m [Tuple 1 1, Tuple 2 2]
68+
, right: m [Tuple 3 30, Tuple 4 40] }
69+
5670
log "All done!"

0 commit comments

Comments
 (0)