Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.

Couple new foldable functions to Data.Map #42

Merged
merged 1 commit into from
Dec 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions docs/Data/Map.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ data Map k v

##### Instances
``` purescript
instance eqMap :: (Eq k, Eq v) => Eq (Map k v)
instance showMap :: (Show k, Show v) => Show (Map k v)
instance ordMap :: (Ord k, Ord v) => Ord (Map k v)
instance semigroupMap :: (Ord k) => Semigroup (Map k v)
instance monoidMap :: (Ord k) => Monoid (Map k v)
instance functorMap :: Functor (Map k)
instance foldableMap :: Foldable (Map k)
instance traversableMap :: (Ord k) => Traversable (Map k)
(Eq k, Eq v) => Eq (Map k v)
(Show k, Show v) => Show (Map k v)
(Ord k, Ord v) => Ord (Map k v)
(Ord k) => Semigroup (Map k v)
(Ord k) => Monoid (Map k v)
Functor (Map k)
Foldable (Map k)
(Ord k) => Traversable (Map k)
```

#### `showTree`
Expand Down Expand Up @@ -113,29 +113,47 @@ update :: forall k v. (Ord k) => (v -> Maybe v) -> k -> Map k v -> Map k v

Update or delete the value for a key in a map

#### `fromFoldable`

``` purescript
fromFoldable :: forall f k v. (Ord k, Foldable f) => f (Tuple k v) -> Map k v
```

Convert any foldable collection of key/value pairs to a map.
On key collision, later values take precedence over earlier ones.

#### `fromFoldableWith`

``` purescript
fromFoldableWith :: forall f k v. (Ord k, Foldable f) => (v -> v -> v) -> f (Tuple k v) -> Map k v
```

Convert any foldable collection of key/value pairs to a map.
On key collision, the values are configurably combined.

#### `toList`

``` purescript
toList :: forall k v. Map k v -> List (Tuple k v)
```

Convert a map to an array of key/value pairs
Convert a map to a list of key/value pairs

#### `fromList`

``` purescript
fromList :: forall k v. (Ord k) => List (Tuple k v) -> Map k v
```

Create a map from an array of key/value pairs
Create a map from a list of key/value pairs

#### `fromListWith`

``` purescript
fromListWith :: forall k v. (Ord k) => (v -> v -> v) -> List (Tuple k v) -> Map k v
```

Create a map from an array of key/value pairs, using the specified function
Create a map from a list of key/value pairs, using the specified function
to combine values for duplicate keys.

#### `keys`
Expand All @@ -144,15 +162,15 @@ to combine values for duplicate keys.
keys :: forall k v. Map k v -> List k
```

Get an array of the keys contained in a map
Get a list of the keys contained in a map

#### `values`

``` purescript
values :: forall k v. Map k v -> List v
```

Get an array of the values contained in a map
Get a list of the values contained in a map

#### `unionWith`

Expand Down
39 changes: 28 additions & 11 deletions docs/Data/StrMap.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ data StrMap :: * -> *

##### Instances
``` purescript
instance functorStrMap :: Functor StrMap
instance foldableStrMap :: Foldable StrMap
instance traversableStrMap :: Traversable StrMap
instance eqStrMap :: (Eq a) => Eq (StrMap a)
instance showStrMap :: (Show a) => Show (StrMap a)
instance semigroupStrMap :: (Semigroup a) => Semigroup (StrMap a)
instance monoidStrMap :: (Semigroup a) => Monoid (StrMap a)
Functor StrMap
Foldable StrMap
Traversable StrMap
(Eq a) => Eq (StrMap a)
(Show a) => Show (StrMap a)
(Semigroup a) => Semigroup (StrMap a)
(Semigroup a) => Monoid (StrMap a)
```

#### `thawST`
Expand Down Expand Up @@ -185,21 +185,38 @@ update :: forall a. (a -> Maybe a) -> String -> StrMap a -> StrMap a

Remove or update a value for a key in a map

#### `fromFoldable`

``` purescript
fromFoldable :: forall f a. (Foldable f) => f (Tuple String a) -> StrMap a
```

Create a map from a foldable collection of key/value pairs

#### `fromFoldableWith`

``` purescript
fromFoldableWith :: forall f a. (Foldable f) => (a -> a -> a) -> f (Tuple String a) -> StrMap a
```

Create a map from a foldable collection of key/value pairs, using the
specified function to combine values for duplicate keys.

#### `fromList`

``` purescript
fromList :: forall a. List (Tuple String a) -> StrMap a
```

Create a map from an array of key/value pairs
Create a map from a list of key/value pairs

#### `fromListWith`

``` purescript
fromListWith :: forall a. (a -> a -> a) -> List (Tuple String a) -> StrMap a
```

Create a map from an array of key/value pairs, using the specified function
Create a map from a list of key/value pairs, using the specified function
to combine values for duplicate keys.

#### `toList`
Expand All @@ -208,7 +225,7 @@ to combine values for duplicate keys.
toList :: forall a. StrMap a -> List (Tuple String a)
```

Convert a map into an array of key/value pairs
Convert a map into a list of key/value pairs

#### `keys`

Expand All @@ -224,7 +241,7 @@ Get an array of the keys in a map
values :: forall a. StrMap a -> List a
```

Get an array of the values in a map
Get a list of the values in a map

#### `union`

Expand Down
30 changes: 21 additions & 9 deletions src/Data/Map.purs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module Data.Map
, checkValid
, insert
, lookup
, fromFoldable
, fromFoldableWith
, toList
, fromList
, fromListWith
Expand Down Expand Up @@ -239,30 +241,40 @@ alter f k m = case f (k `lookup` m) of
update :: forall k v. (Ord k) => (v -> Maybe v) -> k -> Map k v -> Map k v
update f k m = alter (maybe Nothing f) k m

-- | Convert a map to an array of key/value pairs
-- | Convert any foldable collection of key/value pairs to a map.
-- | On key collision, later values take precedence over earlier ones.
fromFoldable :: forall f k v. (Ord k, Foldable f) => f (Tuple k v) -> Map k v
fromFoldable = foldl (\m (Tuple k v) -> insert k v m) empty

-- | Convert any foldable collection of key/value pairs to a map.
-- | On key collision, the values are configurably combined.
fromFoldableWith :: forall f k v. (Ord k, Foldable f) => (v -> v -> v) -> f (Tuple k v) -> Map k v
fromFoldableWith f = foldl (\m (Tuple k v) -> alter (combine v) k m) empty where
combine v (Just v') = Just $ f v v'
combine v Nothing = Just v

-- | Convert a map to a list of key/value pairs
toList :: forall k v. Map k v -> List (Tuple k v)
toList Leaf = Nil
toList (Two left k v right) = toList left ++ pure (Tuple k v) ++ toList right
toList (Three left k1 v1 mid k2 v2 right) = toList left ++ pure (Tuple k1 v1) ++ toList mid ++ pure (Tuple k2 v2) ++ toList right

-- | Create a map from an array of key/value pairs
-- | Create a map from a list of key/value pairs
fromList :: forall k v. (Ord k) => List (Tuple k v) -> Map k v
fromList = foldl (\m (Tuple k v) -> insert k v m) empty
fromList = fromFoldable

-- | Create a map from an array of key/value pairs, using the specified function
-- | Create a map from a list of key/value pairs, using the specified function
-- | to combine values for duplicate keys.
fromListWith :: forall k v. (Ord k) => (v -> v -> v) -> List (Tuple k v) -> Map k v
fromListWith f = foldl (\m (Tuple k v) -> alter (combine v) k m) empty where
combine v (Just v') = Just $ f v v'
combine v Nothing = Just v
fromListWith = fromFoldableWith

-- | Get an array of the keys contained in a map
-- | Get a list of the keys contained in a map
keys :: forall k v. Map k v -> List k
keys Leaf = Nil
keys (Two left k _ right) = keys left ++ pure k ++ keys right
keys (Three left k1 _ mid k2 _ right) = keys left ++ pure k1 ++ keys mid ++ pure k2 ++ keys right

-- | Get an array of the values contained in a map
-- | Get a list of the values contained in a map
values :: forall k v. Map k v -> List v
values Leaf = Nil
values (Two left _ v right) = values left ++ pure v ++ values right
Expand Down
31 changes: 22 additions & 9 deletions src/Data/StrMap.purs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ module Data.StrMap
, insert
, lookup
, toList
, fromFoldable
, fromFoldableWith
, fromList
, fromListWith
, delete
Expand Down Expand Up @@ -181,33 +183,44 @@ alter f k m = case f (k `lookup` m) of
update :: forall a. (a -> Maybe a) -> String -> StrMap a -> StrMap a
update f k m = alter (maybe Nothing f) k m

-- | Create a map from an array of key/value pairs
fromList :: forall a. L.List (Tuple String a) -> StrMap a
fromList l = pureST (do
-- | Create a map from a foldable collection of key/value pairs
fromFoldable :: forall f a. (Foldable f) =>
f (Tuple String a) -> StrMap a
fromFoldable l = pureST (do
s <- SM.new
for_ l (\(Tuple k v) -> SM.poke s k v)
return s)

foreign import _lookupST :: forall a h r z. Fn4 z (a -> z) String (SM.STStrMap h a) (Eff (st :: ST.ST h | r) z)

-- | Create a map from an array of key/value pairs, using the specified function
-- | to combine values for duplicate keys.
fromListWith :: forall a. (a -> a -> a) -> L.List (Tuple String a) -> StrMap a
fromListWith f l = pureST (do
-- | Create a map from a foldable collection of key/value pairs, using the
-- | specified function to combine values for duplicate keys.
fromFoldableWith :: forall f a. (Foldable f) =>
(a -> a -> a) -> f (Tuple String a) -> StrMap a
fromFoldableWith f l = pureST (do
s <- SM.new
for_ l (\(Tuple k v) -> runFn4 _lookupST v (f v) k s >>= SM.poke s k)
return s)

-- | Create a map from a list of key/value pairs
fromList :: forall a. L.List (Tuple String a) -> StrMap a
fromList = fromFoldable

-- | Create a map from a list of key/value pairs, using the specified function
-- | to combine values for duplicate keys.
fromListWith :: forall a. (a -> a -> a) -> L.List (Tuple String a) -> StrMap a
fromListWith = fromFoldableWith

foreign import _collect :: forall a b . (String -> a -> b) -> StrMap a -> Array b

-- | Convert a map into an array of key/value pairs
-- | Convert a map into a list of key/value pairs
toList :: forall a. StrMap a -> L.List (Tuple String a)
toList = L.toList <<< _collect Tuple

-- | Get an array of the keys in a map
foreign import keys :: forall a. StrMap a -> Array String

-- | Get an array of the values in a map
-- | Get a list of the values in a map
values :: forall a. StrMap a -> L.List a
values = L.toList <<< _collect (\_ v -> v)

Expand Down
22 changes: 22 additions & 0 deletions test/Test/Data/Map.purs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,28 @@ mapTests = do
log "Singleton to list"
quickCheck $ \k v -> M.toList (M.singleton k v :: M.Map SmallKey Int) == singleton (Tuple k v)

log "fromFoldable [] = empty"
quickCheck (M.fromFoldable [] == (M.empty :: M.Map Unit Unit)
<?> "was not empty")

log "fromFoldable & key collision"
do
let nums = M.fromFoldable [Tuple 0 "zero", Tuple 1 "what", Tuple 1 "one"]
quickCheck (M.lookup 0 nums == Just "zero" <?> "invalid lookup - 0")
quickCheck (M.lookup 1 nums == Just "one" <?> "invalid lookup - 1")
quickCheck (M.lookup 2 nums == Nothing <?> "invalid lookup - 2")

log "fromFoldableWith const [] = empty"
quickCheck (M.fromFoldableWith const [] == (M.empty :: M.Map Unit Unit)
<?> "was not empty")

log "fromFoldableWith (+) & key collision"
do
let nums = M.fromFoldableWith (+) [Tuple 0 1, Tuple 1 1, Tuple 1 1]
quickCheck (M.lookup 0 nums == Just 1 <?> "invalid lookup - 0")
quickCheck (M.lookup 1 nums == Just 2 <?> "invalid lookup - 1")
quickCheck (M.lookup 2 nums == Nothing <?> "invalid lookup - 2")

log "toList . fromList = id"
quickCheck $ \arr -> let f x = M.toList (M.fromList x)
in f (f arr) == f (arr :: List (Tuple SmallKey Int)) <?> show arr
Expand Down
22 changes: 22 additions & 0 deletions test/Test/Data/StrMap.purs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,28 @@ strMapTests = do
log "Singleton to list"
quickCheck $ \k v -> M.toList (M.singleton k v :: M.StrMap Int) == singleton (Tuple k v)

log "fromFoldable [] = empty"
quickCheck (M.fromFoldable [] == (M.empty :: M.StrMap Unit)
<?> "was not empty")

log "fromFoldable & key collision"
do
let nums = M.fromFoldable [Tuple "0" "zero", Tuple "1" "what", Tuple "1" "one"]
quickCheck (M.lookup "0" nums == Just "zero" <?> "invalid lookup - 0")
quickCheck (M.lookup "1" nums == Just "one" <?> "invalid lookup - 1")
quickCheck (M.lookup "2" nums == Nothing <?> "invalid lookup - 2")

log "fromFoldableWith const [] = empty"
quickCheck (M.fromFoldableWith const [] == (M.empty :: M.StrMap Unit)
<?> "was not empty")

log "fromFoldableWith (+) & key collision"
do
let nums = M.fromFoldableWith (+) [Tuple "0" 1, Tuple "1" 1, Tuple "1" 1]
quickCheck (M.lookup "0" nums == Just 1 <?> "invalid lookup - 0")
quickCheck (M.lookup "1" nums == Just 2 <?> "invalid lookup - 1")
quickCheck (M.lookup "2" nums == Nothing <?> "invalid lookup - 2")

log "toList . fromList = id"
quickCheck $ \arr -> let f x = M.toList (M.fromList x)
in f (f arr) == f (arr :: List (Tuple String Int)) <?> show arr
Expand Down