monoidmap 0.0.1.9 → 0.0.2.0
raw patch · 6 files changed
+169/−5 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−0
- monoidmap.cabal +1/−1
- src/internal/Data/MonoidMap/Internal.hs +21/−0
- src/public/Data/MonoidMap.hs +1/−0
- src/test/Data/MonoidMap/ConversionSpec.hs +33/−1
- src/test/Data/MonoidMap/ValiditySpec.hs +109/−3
CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.0.2.0++- Added the `fromSet` function to `MonoidMap`.+ # 0.0.1.9 - Added the following traversal functions to `MonoidMap`:
monoidmap.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: monoidmap-version: 0.0.1.9+version: 0.0.2.0 bug-reports: https://github.com/jonathanknowles/monoidmap/issues license: Apache-2.0 license-file: LICENSE
src/internal/Data/MonoidMap/Internal.hs view
@@ -23,6 +23,7 @@ , fromList , fromListWith , fromMap+ , fromSet , singleton -- ** Deconstruction@@ -478,6 +479,26 @@ -- fromMap :: MonoidNull v => Map k v -> MonoidMap k v fromMap = MonoidMap . Map.mapMaybe maybeNonNull++-- | \(O(n)\). Constructs a 'MonoidMap' from a 'Set' and a function from+-- keys to values.+--+-- Satisfies the following property for all possible keys __@k@__:+--+-- @+-- 'get' k ('fromSet' f ks) '=='+-- if 'Set'.'Set.member' k ks+-- then f k+-- else 'mempty'+-- @+--+-- This function performs canonicalisation of 'C.null' values, and has a time+-- complexity that is linear in the 'Set.size' of the set.+--+-- @since 0.0.2.0+--+fromSet :: MonoidNull v => (k -> v) -> Set k -> MonoidMap k v+fromSet f = fromMap . Map.fromSet f -- | \(O(1)\). Constructs a 'MonoidMap' from a single key-value pair. --
src/public/Data/MonoidMap.hs view
@@ -22,6 +22,7 @@ , fromList , fromListWith , fromMap+ , fromSet , singleton -- ** Deconstruction
src/test/Data/MonoidMap/ConversionSpec.hs view
@@ -22,18 +22,22 @@ ( MonoidMap, nonNullCount ) import Data.Proxy ( Proxy (..) )+import Data.Set+ ( Set ) import Test.Common ( Key, Test, TestType (TestType), makeSpec, property, testTypesMonoidNull ) import Test.Hspec ( Spec, describe, it ) import Test.QuickCheck- ( Fun (..), Property, applyFun2, cover, (===) )+ ( Fun (..), Property, applyFun, applyFun2, cover, (===) ) import qualified Data.Foldable as F import qualified Data.List as List import qualified Data.List.NonEmpty as NE import qualified Data.Map.Strict as Map+import qualified Data.Monoid.Null as Null import qualified Data.MonoidMap as MonoidMap+import qualified Data.Set as Set spec :: Spec spec = describe "Conversions" $ do@@ -71,6 +75,11 @@ prop_toMap_fromMap @k @v & property + describe "Conversion from sets" $ do+ it "prop_fromSet_get" $+ prop_fromSet_get+ @k @v & property+ -------------------------------------------------------------------------------- -- Conversion to and from lists --------------------------------------------------------------------------------@@ -186,3 +195,26 @@ :: Test k v => MonoidMap k v -> Property prop_toMap_fromMap m = MonoidMap.fromMap (MonoidMap.toMap m) === m++--------------------------------------------------------------------------------+-- Conversion from sets+--------------------------------------------------------------------------------++prop_fromSet_get+ :: Test k v => Fun k v -> Set k -> k -> Property+prop_fromSet_get (applyFun -> f) ks k =+ MonoidMap.get k (MonoidMap.fromSet f ks)+ ===+ (if Set.member k ks then f k else mempty)+ & cover 0.2+ (Set.member k ks && Null.null (f k))+ "Set.member k ks && Null.null (f k)"+ & cover 8.0+ (Set.member k ks && not (Null.null (f k)))+ "Set.member k ks && not (Null.null (f k))"+ & cover 0.2+ (not (Set.member k ks) && Null.null (f k))+ "not (Set.member k ks) && Null.null (f k)"+ & cover 8.0+ (not (Set.member k ks) && not (Null.null (f k)))+ "not (Set.member k ks) && not (Null.null (f k))"
src/test/Data/MonoidMap/ValiditySpec.hs view
@@ -17,6 +17,8 @@ ( Proxy (Proxy) ) import Data.Function ( (&) )+import Data.Functor.Identity+ ( Identity ) import Data.Group ( Group ) import Data.Map.Strict@@ -40,6 +42,8 @@ ( MonoidMap ) import Data.MonoidMap.SliceSpec ( Slice (..) )+import Data.Set+ ( Set ) import Test.Common ( Key , Test@@ -61,8 +65,17 @@ import Test.Hspec ( Spec, it ) import Test.QuickCheck- ( Fun, Property, applyFun, applyFun2, conjoin, counterexample, cover )+ ( Fun+ , Property+ , applyFun+ , applyFun2+ , applyFun3+ , conjoin+ , counterexample+ , cover+ ) +import qualified Data.Foldable as F import qualified Data.Map.Strict as Map import qualified Data.Monoid.Null as Null import qualified Data.MonoidMap as MonoidMap@@ -128,6 +141,9 @@ it "propValid_fromMap" $ propValid_fromMap @k @v & property+ it "propValid_fromSet" $+ propValid_fromSet+ @k @v & property it "propValid_singleton" $ propValid_singleton @k @v & property@@ -176,6 +192,24 @@ it "propValid_mapKeysWith" $ propValid_mapKeysWith @k @v & property+ it "propValid_mapAccumL" $+ propValid_mapAccumL+ @k @v & property+ it "propValid_mapAccumR" $+ propValid_mapAccumR+ @k @v & property+ it "propValid_mapAccumLWithKey" $+ propValid_mapAccumLWithKey+ @k @v & property+ it "propValid_mapAccumRWithKey" $+ propValid_mapAccumRWithKey+ @k @v & property+ it "propValid_traverse" $+ propValid_traverse+ @k @v & property+ it "propValid_traverseWithKey" $+ propValid_traverseWithKey+ @k @v & property it "propValid_intersectionWith" $ propValid_intersectionWith @k @v & property@@ -347,9 +381,17 @@ propValid_fromMap m = propValid (MonoidMap.fromMap m) & cover 2- (Map.filter (Null.null) m /= mempty)- "Map.filter (Null.null) m /= mempty"+ (Map.filter Null.null m /= mempty)+ "Map.filter Null.null m /= mempty" +propValid_fromSet+ :: Test k v => Fun k v -> Set k -> Property+propValid_fromSet (applyFun -> f) ks =+ propValid (MonoidMap.fromSet f ks)+ & cover 2+ (Map.filter Null.null (Map.fromSet f ks) /= mempty)+ "Map.filter Null.null (Map.fromSet f ks) /= mempty"+ propValid_singleton :: Test k v => k -> v -> Property propValid_singleton k v =@@ -461,6 +503,70 @@ :: Test k v => Fun (v, v) v -> Fun k k -> MonoidMap k v -> Property propValid_mapKeysWith (applyFun2 -> f) (applyFun -> g) m = propValid (MonoidMap.mapKeysWith f g m)++propValid_mapAccumL+ :: forall k v s. s ~ Int+ => Test k v+ => Fun (s, v) (s, v)+ -> s+ -> MonoidMap k v+ -> Property+propValid_mapAccumL (applyFun2 -> f) s m =+ propValid $ snd $ MonoidMap.mapAccumL f s m++propValid_mapAccumR+ :: forall k v s. s ~ Int+ => Test k v+ => Fun (s, v) (s, v)+ -> s+ -> MonoidMap k v+ -> Property+propValid_mapAccumR (applyFun2 -> f) s m =+ propValid $ snd $ MonoidMap.mapAccumR f s m++propValid_mapAccumLWithKey+ :: forall k v s. s ~ Int+ => Test k v+ => Fun (s, k, v) (s, v)+ -> s+ -> MonoidMap k v+ -> Property+propValid_mapAccumLWithKey (applyFun3 -> f) s m =+ propValid $ snd $ MonoidMap.mapAccumLWithKey f s m++propValid_mapAccumRWithKey+ :: forall k v s. s ~ Int+ => Test k v+ => Fun (s, k, v) (s, v)+ -> s+ -> MonoidMap k v+ -> Property+propValid_mapAccumRWithKey (applyFun3 -> f) s m =+ propValid $ snd $ MonoidMap.mapAccumRWithKey f s m++propValid_traverse+ :: forall k v t. (Applicative t, Foldable t, Test k v)+ => t ~ Identity+ => Fun v (t v)+ -> MonoidMap k v+ -> Property+propValid_traverse (applyFun -> f) m+ = conjoin+ $ fmap propValid+ $ F.toList @t+ $ MonoidMap.traverse f m++propValid_traverseWithKey+ :: forall k v t. (Applicative t, Foldable t, Test k v)+ => t ~ Identity+ => Fun (k, v) (t v)+ -> MonoidMap k v+ -> Property+propValid_traverseWithKey (applyFun2 -> f) m+ = conjoin+ $ fmap propValid+ $ F.toList @t+ $ MonoidMap.traverseWithKey f m propValid_intersection :: (Test k v, GCDMonoid v) => MonoidMap k v -> MonoidMap k v -> Property