Skip to content

Commit 9c1d425

Browse files
Add function fromSet to MonoidMap. (#224)
2 parents 599043b + e956497 commit 9c1d425

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

src/internal/Data/MonoidMap/Internal.hs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Data.MonoidMap.Internal
2323
, fromList
2424
, fromListWith
2525
, fromMap
26+
, fromSet
2627
, singleton
2728

2829
-- ** Deconstruction
@@ -479,6 +480,26 @@ fromListWith f =
479480
fromMap :: MonoidNull v => Map k v -> MonoidMap k v
480481
fromMap = MonoidMap . Map.mapMaybe maybeNonNull
481482

483+
-- | \(O(n)\). Constructs a 'MonoidMap' from a 'Set' and a function from
484+
-- keys to values.
485+
--
486+
-- Satisfies the following property for all possible keys __@k@__:
487+
--
488+
-- @
489+
-- 'get' k ('fromSet' f ks) '=='
490+
-- if 'Set'.'Set.member' k ks
491+
-- then f k
492+
-- else 'mempty'
493+
-- @
494+
--
495+
-- This function performs canonicalisation of 'C.null' values, and has a time
496+
-- complexity that is linear in the 'Set.size' of the set.
497+
--
498+
-- @since 0.0.2.0
499+
--
500+
fromSet :: MonoidNull v => (k -> v) -> Set k -> MonoidMap k v
501+
fromSet f = fromMap . Map.fromSet f
502+
482503
-- | \(O(1)\). Constructs a 'MonoidMap' from a single key-value pair.
483504
--
484505
-- Satisfies the following property:

src/public/Data/MonoidMap.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module Data.MonoidMap
2222
, fromList
2323
, fromListWith
2424
, fromMap
25+
, fromSet
2526
, singleton
2627

2728
-- ** Deconstruction

src/test/Data/MonoidMap/ConversionSpec.hs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,22 @@ import Data.MonoidMap
2222
( MonoidMap, nonNullCount )
2323
import Data.Proxy
2424
( Proxy (..) )
25+
import Data.Set
26+
( Set )
2527
import Test.Common
2628
( Key, Test, TestType (TestType), makeSpec, property, testTypesMonoidNull )
2729
import Test.Hspec
2830
( Spec, describe, it )
2931
import Test.QuickCheck
30-
( Fun (..), Property, applyFun2, cover, (===) )
32+
( Fun (..), Property, applyFun, applyFun2, cover, (===) )
3133

3234
import qualified Data.Foldable as F
3335
import qualified Data.List as List
3436
import qualified Data.List.NonEmpty as NE
3537
import qualified Data.Map.Strict as Map
38+
import qualified Data.Monoid.Null as Null
3639
import qualified Data.MonoidMap as MonoidMap
40+
import qualified Data.Set as Set
3741

3842
spec :: Spec
3943
spec = describe "Conversions" $ do
@@ -71,6 +75,11 @@ specFor = makeSpec $ do
7175
prop_toMap_fromMap
7276
@k @v & property
7377

78+
describe "Conversion from sets" $ do
79+
it "prop_fromSet_get" $
80+
prop_fromSet_get
81+
@k @v & property
82+
7483
--------------------------------------------------------------------------------
7584
-- Conversion to and from lists
7685
--------------------------------------------------------------------------------
@@ -186,3 +195,26 @@ prop_toMap_fromMap
186195
:: Test k v => MonoidMap k v -> Property
187196
prop_toMap_fromMap m =
188197
MonoidMap.fromMap (MonoidMap.toMap m) === m
198+
199+
--------------------------------------------------------------------------------
200+
-- Conversion from sets
201+
--------------------------------------------------------------------------------
202+
203+
prop_fromSet_get
204+
:: Test k v => Fun k v -> Set k -> k -> Property
205+
prop_fromSet_get (applyFun -> f) ks k =
206+
MonoidMap.get k (MonoidMap.fromSet f ks)
207+
===
208+
(if Set.member k ks then f k else mempty)
209+
& cover 0.2
210+
(Set.member k ks && Null.null (f k))
211+
"Set.member k ks && Null.null (f k)"
212+
& cover 8.0
213+
(Set.member k ks && not (Null.null (f k)))
214+
"Set.member k ks && not (Null.null (f k))"
215+
& cover 0.2
216+
(not (Set.member k ks) && Null.null (f k))
217+
"not (Set.member k ks) && Null.null (f k)"
218+
& cover 8.0
219+
(not (Set.member k ks) && not (Null.null (f k)))
220+
"not (Set.member k ks) && not (Null.null (f k))"

src/test/Data/MonoidMap/ValiditySpec.hs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import Data.MonoidMap
4040
( MonoidMap )
4141
import Data.MonoidMap.SliceSpec
4242
( Slice (..) )
43+
import Data.Set
44+
( Set )
4345
import Test.Common
4446
( Key
4547
, Test
@@ -128,6 +130,9 @@ specValidMonoidNull = makeSpec $ do
128130
it "propValid_fromMap" $
129131
propValid_fromMap
130132
@k @v & property
133+
it "propValid_fromSet" $
134+
propValid_fromSet
135+
@k @v & property
131136
it "propValid_singleton" $
132137
propValid_singleton
133138
@k @v & property
@@ -347,8 +352,16 @@ propValid_fromMap
347352
propValid_fromMap m =
348353
propValid (MonoidMap.fromMap m)
349354
& cover 2
350-
(Map.filter (Null.null) m /= mempty)
351-
"Map.filter (Null.null) m /= mempty"
355+
(Map.filter Null.null m /= mempty)
356+
"Map.filter Null.null m /= mempty"
357+
358+
propValid_fromSet
359+
:: Test k v => Fun k v -> Set k -> Property
360+
propValid_fromSet (applyFun -> f) ks =
361+
propValid (MonoidMap.fromSet f ks)
362+
& cover 2
363+
(Map.filter Null.null (Map.fromSet f ks) /= mempty)
364+
"Map.filter Null.null (Map.fromSet f ks) /= mempty"
352365

353366
propValid_singleton
354367
:: Test k v => k -> v -> Property

0 commit comments

Comments
 (0)