git.iko.soy/monoidal-containers
on d0401dc help sign in
10 files changed+176−267
since splitsnapshots
unifiedsplit
.travis.yml+110−124 Changelog.md−11 README.md−4 default.nix+6−4 monoidal-containers.cabal+7−6 src/Data/HashMap/Monoidal.hs+24−43 src/Data/IntMap/Monoidal.hs+8−20 src/Data/IntMap/Monoidal/Strict.hs+9−21 src/Data/Map/Monoidal.hs+8−20 src/Data/Map/Monoidal/Strict.hs+4−14
.travis.yml+110−124
@@ -1,153 +1,139 @@
11# This Travis job script has been generated by a script via
22#
3−# haskell-ci 'monoidal-containers.cabal' '-o' '.travis.yml'
4−#
5−# To regenerate the script (for example after adjusting tested-with) run
6−#
7−# haskell-ci regenerate
3+# runghc make_travis_yml_2.hs 'monoidal-containers.cabal'
84#
95# For more information, see https://github.com/haskell-CI/haskell-ci
106#
11−# version: 0.10.3
12−#
13−version: ~> 1.0
147language: c
15−os: linux
16−dist: xenial
8+sudo: false
9+
1710git:
18− # whether to recursively clone submodules
19− submodules: false
11+ submodules: false # whether to recursively clone submodules
12+
2013cache:
2114 directories:
2215 - $HOME/.cabal/packages
2316 - $HOME/.cabal/store
24− - $HOME/.hlint
17+
2518before_cache:
26− - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log
19+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
2720 # remove files that are regenerated by 'cabal update'
28− - rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*
29− - rm -fv $CABALHOME/packages/hackage.haskell.org/*.json
30− - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache
31− - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar
32− - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx
33− - rm -rfv $CABALHOME/packages/head.hackage
34−jobs:
21+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.*
22+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json
23+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.cache
24+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar
25+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx
26+
27+ - rm -rfv $HOME/.cabal/packages/head.hackage
28+
29+matrix:
3530 include:
36− - compiler: ghc-8.10.2
37− addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.10.2","cabal-install-3.2"]}}
38− os: linux
39− - compiler: ghc-8.8.4
40− addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.8.4","cabal-install-3.2"]}}
41− os: linux
42− - compiler: ghc-8.6.5
43− addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.6.5","cabal-install-3.2"]}}
44− os: linux
45− - compiler: ghc-8.4.3
46− addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.4.3","cabal-install-3.2"]}}
47− os: linux
48− - compiler: ghc-8.2.2
49− addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.2.2","cabal-install-3.2"]}}
50− os: linux
51− - compiler: ghc-8.0.2
52− addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-8.0.2","cabal-install-3.2"]}}
53− os: linux
54− - compiler: ghc-7.8.4
55− addons: {"apt":{"sources":[{"sourceline":"deb http://ppa.launchpad.net/hvr/ghc/ubuntu xenial main","key_url":"https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x063dab2bdc0b3f9fcebc378bff3aeacef6f88286"}],"packages":["ghc-7.8.4","cabal-install-3.2"]}}
56− os: linux
31+ - compiler: "ghc-8.6.1"
32+ env: GHCHEAD=true
33+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-head,ghc-8.6.1], sources: [hvr-ghc]}}
34+ - compiler: "ghc-8.4.3"
35+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
36+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-8.4.3], sources: [hvr-ghc]}}
37+ - compiler: "ghc-8.2.2"
38+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
39+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-8.2.2], sources: [hvr-ghc]}}
40+ - compiler: "ghc-8.0.2"
41+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
42+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-8.0.2], sources: [hvr-ghc]}}
43+ - compiler: "ghc-7.8.4"
44+ # env: TEST=--disable-tests BENCH=--disable-benchmarks
45+ addons: {apt: {packages: [ghc-ppa-tools,cabal-install-2.2,ghc-7.8.4], sources: [hvr-ghc]}}
46+
47+ allow_failures:
48+ - compiler: "ghc-8.6.1"
49+
5750before_install:
58− - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')
59− - WITHCOMPILER="-w $HC"
60− - HADDOCK=$(echo "/opt/$CC/bin/haddock" | sed 's/-/\//')
61− - HCPKG="$HC-pkg"
51+ - HC=${CC}
52+ - HCPKG=${HC/ghc/ghc-pkg}
6253 - unset CC
63− - CABAL=/opt/ghc/bin/cabal
64− - CABALHOME=$HOME/.cabal
65− - export PATH="$CABALHOME/bin:$PATH"
66− - TOP=$(pwd)
67− - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"
54+ - ROOTDIR=$(pwd)
55+ - mkdir -p $HOME/.local/bin
56+ - "PATH=/opt/ghc/bin:/opt/ghc-ppa-tools/bin:$HOME/local/bin:$PATH"
57+ - HCNUMVER=$(( $(${HC} --numeric-version|sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+).*/\1 * 10000 + \2 * 100 + \3/') ))
6858 - echo $HCNUMVER
69− - CABAL="$CABAL -vnormal+nowrap"
70− - set -o pipefail
71− - TEST=--enable-tests
72− - BENCH=--enable-benchmarks
73− - HEADHACKAGE=false
74− - rm -f $CABALHOME/config
75− - |
76− echo "verbose: normal +nowrap +markoutput" >> $CABALHOME/config
77− echo "remote-build-reporting: anonymous" >> $CABALHOME/config
78− echo "write-ghc-environment-files: always" >> $CABALHOME/config
79− echo "remote-repo-cache: $CABALHOME/packages" >> $CABALHOME/config
80− echo "logs-dir: $CABALHOME/logs" >> $CABALHOME/config
81− echo "world-file: $CABALHOME/world" >> $CABALHOME/config
82− echo "extra-prog-path: $CABALHOME/bin" >> $CABALHOME/config
83− echo "symlink-bindir: $CABALHOME/bin" >> $CABALHOME/config
84− echo "installdir: $CABALHOME/bin" >> $CABALHOME/config
85− echo "build-summary: $CABALHOME/logs/build.log" >> $CABALHOME/config
86− echo "store-dir: $CABALHOME/store" >> $CABALHOME/config
87− echo "install-dirs user" >> $CABALHOME/config
88− echo " prefix: $CABALHOME" >> $CABALHOME/config
89− echo "repository hackage.haskell.org" >> $CABALHOME/config
90− echo " url: http://hackage.haskell.org/" >> $CABALHOME/config
59+
9160install:
92− - ${CABAL} --version
61+ - cabal --version
9362 - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
63+ - BENCH=${BENCH---enable-benchmarks}
64+ - TEST=${TEST---enable-tests}
65+ - HADDOCK=${HADDOCK-true}
66+ - UNCONSTRAINED=${UNCONSTRAINED-true}
67+ - NOINSTALLEDCONSTRAINTS=${NOINSTALLEDCONSTRAINTS-false}
68+ - GHCHEAD=${GHCHEAD-false}
69+ - travis_retry cabal update -v
70+ - "sed -i.bak 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config"
71+ - rm -fv cabal.project cabal.project.local
72+ # Overlay Hackage Package Index for GHC HEAD: https://github.com/hvr/head.hackage
9473 - |
95− echo "program-default-options" >> $CABALHOME/config
96− echo " ghc-options: $GHCJOBS +RTS -M6G -RTS" >> $CABALHOME/config
97− - cat $CABALHOME/config
98− - rm -fv cabal.project cabal.project.local cabal.project.freeze
99− - travis_retry ${CABAL} v2-update -v
100− # Generate cabal.project
101− - rm -rf cabal.project cabal.project.local cabal.project.freeze
102− - touch cabal.project
103− - |
104− echo "packages: ." >> cabal.project
105− - if [ $HCNUMVER -ge 80200 ] ; then echo 'package monoidal-containers' >> cabal.project ; fi
106− - "if [ $HCNUMVER -ge 80200 ] ; then echo ' ghc-options: -Werror=missing-methods' >> cabal.project ; fi"
107− - |
108− - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(monoidal-containers)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
74+ if $GHCHEAD; then
75+ sed -i 's/-- allow-newer: .*/allow-newer: *:base/' ${HOME}/.cabal/config
76+ for pkg in $($HCPKG list --simple-output); do pkg=$(echo $pkg | sed 's/-[^-]*$//'); sed -i "s/allow-newer: /allow-newer: *:$pkg, /" ${HOME}/.cabal/config; done
77+
78+ echo 'repository head.hackage' >> ${HOME}/.cabal/config
79+ echo ' url: http://head.hackage.haskell.org/' >> ${HOME}/.cabal/config
80+ echo ' secure: True' >> ${HOME}/.cabal/config
81+ echo ' root-keys: 07c59cb65787dedfaef5bd5f987ceb5f7e5ebf88b904bbd4c5cbdeb2ff71b740' >> ${HOME}/.cabal/config
82+ echo ' 2e8555dde16ebd8df076f1a8ef13b8f14c66bad8eafefd7d9e37d0ed711821fb' >> ${HOME}/.cabal/config
83+ echo ' 8f79fd2389ab2967354407ec852cbe73f2e8635793ac446d09461ffb99527f6e' >> ${HOME}/.cabal/config
84+ echo ' key-threshold: 3' >> ${HOME}/.cabal.config
85+
86+ grep -Ev -- '^\s*--' ${HOME}/.cabal/config | grep -Ev '^\s*$'
87+
88+ cabal new-update head.hackage -v
89+ fi
90+ - grep -Ev -- '^\s*--' ${HOME}/.cabal/config | grep -Ev '^\s*$'
91+ - "printf 'packages: \".\"\\n' > cabal.project"
92+ - touch cabal.project.local
93+ - "if ! $NOINSTALLEDCONSTRAINTS; then for pkg in $($HCPKG list --simple-output); do echo $pkg | grep -vw -- monoidal-containers | sed 's/^/constraints: /' | sed 's/-[^-]*$/ installed/' >> cabal.project.local; done; fi"
10994 - cat cabal.project || true
11095 - cat cabal.project.local || true
111− - if [ -f "./configure.ac" ]; then (cd "." && autoreconf -i); fi
112− - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH}
113− - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"
114− - rm cabal.project.freeze
115− - travis_wait 40 ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all
116− - travis_wait 40 ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all
117−script:
96+ - if [ -f "./configure.ac" ]; then
97+ (cd "." && autoreconf -i);
98+ fi
99+ - rm -f cabal.project.freeze
100+ - cabal new-build -w ${HC} ${TEST} ${BENCH} --project-file="cabal.project" --dep -j2 all
101+ - cabal new-build -w ${HC} --disable-tests --disable-benchmarks --project-file="cabal.project" --dep -j2 all
102+ - rm -rf .ghc.environment.* "."/dist
118103 - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
119− # Packaging...
120− - ${CABAL} v2-sdist all
121− # Unpacking...
122− - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/
104+
105+# Here starts the actual work to be performed for the package under test;
106+# any command which exits with a non-zero exit code causes the build to fail.
107+script:
108+ # test that source-distributions can be generated
109+ - (cd "." && cabal sdist)
110+ - mv "."/dist/monoidal-containers-*.tar.gz ${DISTDIR}/
123111 - cd ${DISTDIR} || false
124− - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;
125− - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm '{}' \;
126− - PKGDIR_monoidal_containers="$(find . -maxdepth 1 -type d -regex '.*/monoidal-containers-[0-9.]*')"
127− # Generate cabal.project
128− - rm -rf cabal.project cabal.project.local cabal.project.freeze
129− - touch cabal.project
130− - |
131− echo "packages: ${PKGDIR_monoidal_containers}" >> cabal.project
132− - if [ $HCNUMVER -ge 80200 ] ; then echo 'package monoidal-containers' >> cabal.project ; fi
133− - "if [ $HCNUMVER -ge 80200 ] ; then echo ' ghc-options: -Werror=missing-methods' >> cabal.project ; fi"
134− - |
135− - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(monoidal-containers)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
112+ - find . -maxdepth 1 -name '*.tar.gz' -exec tar -xvf '{}' \;
113+ - "printf 'packages: monoidal-containers-*/*.cabal\\n' > cabal.project"
114+ - touch cabal.project.local
115+ - "if ! $NOINSTALLEDCONSTRAINTS; then for pkg in $($HCPKG list --simple-output); do echo $pkg | grep -vw -- monoidal-containers | sed 's/^/constraints: /' | sed 's/-[^-]*$/ installed/' >> cabal.project.local; done; fi"
136116 - cat cabal.project || true
137117 - cat cabal.project.local || true
138− # Building...
139118 # this builds all libraries and executables (without tests/benchmarks)
140− - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all
141− # Building with tests and benchmarks...
119+ - cabal new-build -w ${HC} --disable-tests --disable-benchmarks all
120+
142121 # build & run tests, build benchmarks
143− - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all
144− # cabal check...
145− - (cd ${PKGDIR_monoidal_containers} && ${CABAL} -vnormal check)
146− # haddock...
147− - ${CABAL} v2-haddock $WITHCOMPILER --with-haddock $HADDOCK ${TEST} ${BENCH} all
148− # Building without installed constraints for packages in global-db...
149− - rm -f cabal.project.local
150− - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all
151−
152−# REGENDATA ("0.10.3",["monoidal-containers.cabal","-o",".travis.yml"])
122+ - cabal new-build -w ${HC} ${TEST} ${BENCH} all
123+
124+ # cabal check
125+ - (cd monoidal-containers-* && cabal check)
126+
127+ # haddock
128+ - rm -rf ./dist-newstyle
129+ - if $HADDOCK; then cabal new-haddock -w ${HC} ${TEST} ${BENCH} all; else echo "Skipping haddock generation";fi
130+
131+ # Build without installed constraints for packages in global-db
132+ - if $UNCONSTRAINED; then rm -f cabal.project.local; echo cabal new-build -w ${HC} --disable-tests --disable-benchmarks all; else echo "Not building without installed constraints"; fi
133+
134+ # Build with split-these set to false
135+ - cabal new-configure -f-split-these
136+ - cabal new-build -w ${HC} ${TEST} ${BENCH} all
137+
138+# REGENDATA ["monoidal-containers.cabal"]
153139# EOF
Changelog.md−11
@@ -1,16 +1,5 @@
11# Monoidal containers
22
3−# 0.6.0.1
4−
5− * Support semialign-1.1
6−
7−# 0.6
8−
9− * Deprecates 0.5.* and reverts behavior of fromList, insert, mapKeys, etc. to match behavior in Data.Map. The only difference in behavior between Data.Map.Monoidal.MonoidalMap and Data.Map.Map is now the semigroup and monoid instances (as was the case in 0.4 and earlier).
10− * Fix the argument order of Data.HashMap.Monoidal.insert
11− * Remove Data.HashMap.Monoidal.insertOrReplace as it is now identical to Data.HashMap.Monoidal.insert
12− * Added Data.HashMap.Monoidal.insertWith and Data.HashMap.Monoidal.fromListWith
13−
143# 0.5.0.1
154
165 * Add a flag, `split-these`, to select whether to use the new "these"/"semialign" packages or the older combined "these" package.
README.md−4
@@ -6,7 +6,3 @@ of the values to be used when resolving conflicts between keys when merging
66structures. Sadly, these are not the semantics offered by the provided
77instances. This package provides `newtypes` with an appropriate set of
88instances and utility functions to make them usable.
9−
10−## Important Note
11−
12−This library is designed to be a drop-in replacement for `Data.Map` and similar. Absolutely no other semantic changes are introduced in functions like `fromList` or `insert`. They are still left-biased like `Data.Map`'s. The only difference is in instances for `Semigroup`.
default.nix+6−4
@@ -1,15 +1,17 @@
11{ mkDerivation, aeson, base, containers, deepseq, hashable, lens
2−, newtype, semialign, semigroups, stdenv, these
2+, newtype, semialign ? null, semigroups, stdenv, these
33, unordered-containers
44}:
55mkDerivation {
66 pname = "monoidal-containers";
7− version = "0.6";
7+ version = "0.5.0.1";
88 src = ./.;
99 libraryHaskellDepends = [
10− aeson base containers deepseq hashable lens newtype semialign
10+ aeson base containers deepseq hashable lens newtype
1111 semigroups these unordered-containers
12− ];
12+ ] ++ stdenv.lib.optional (semialign == null) [ semialign ];
13+ configureFlags =
14+ stdenv.lib.optional (semialign == null) [ "-f-split-these" ];
1315 homepage = "http://github.com/bgamari/monoidal-containers";
1416 description = "Containers with monoidal accumulation";
1517 license = stdenv.lib.licenses.bsd3;
monoidal-containers.cabal+7−6
@@ -1,5 +1,5 @@
11name: monoidal-containers
2−version: 0.6.0.1
2+version: 0.5.0.1
33synopsis: Containers with monoidal accumulation
44description:
55 Containers with merging via monoidal accumulation. The 'Monoid' instances
@@ -24,7 +24,7 @@ category: Data
2424build-type: Simple
2525cabal-version: >=1.10
2626extra-source-files: Changelog.md
27−tested-with: GHC ==7.8.4, GHC ==8.0.2, GHC ==8.2.2, GHC ==8.4.3, GHC ==8.6.5, GHC ==8.8.4, GHC ==8.10.2
27+tested-with: GHC ==7.8.4, GHC ==8.0.2, GHC ==8.2.2, GHC ==8.4.3, GHC ==8.6.1
2828
2929source-repository head
3030 type: git
@@ -46,8 +46,8 @@ library
4646 GeneralizedNewtypeDeriving,
4747 DeriveTraversable,
4848 DeriveDataTypeable
49− build-depends: base >=4.7 && <4.16,
50− aeson >=1.0 && <1.6,
49+ build-depends: base >=4.5 && <4.13,
50+ aeson >=1.0 && <1.5,
5151 containers >=0.5 && <0.7,
5252 deepseq >=1.3 && <1.5,
5353 unordered-containers >= 0.2 && < 0.3,
@@ -57,8 +57,9 @@ library
5757 semigroups >= 0.18 && < 0.20
5858
5959 if flag(split-these)
60− build-depends: these >= 1 && <1.2,
61− semialign >=1 && <1.2
60+ build-depends: these >= 1 && <1.1,
61+ semialign >=1 && <1.1
62+
6263 else
6364 build-depends: these >= 0.7 && <0.9
6465
src/Data/HashMap/Monoidal.hs+24−43
@@ -20,7 +20,6 @@ module Data.HashMap.Monoidal
2020 -- * Often-needed functions
2121 , toList
2222 , fromList
23− , fromListWith
2423 , singleton
2524 , size
2625 , member
@@ -32,7 +31,7 @@ module Data.HashMap.Monoidal
3231 , delete
3332 , mapKeys
3433 , insert
35− , insertWith
34+ , insertOrReplace
3635 , modify
3736 , modifyDef
3837 , map
@@ -60,12 +59,6 @@ import Data.Hashable.Lifted (Hashable1)
6059import Control.Lens
6160import Control.Newtype
6261import Data.Align
63−#ifdef MIN_VERSION_semialign
64−import Data.Semialign (Unalign)
65−#if MIN_VERSION_semialign(1,1,0)
66−import Data.Zip (Zip)
67−#endif
68−#endif
6962
7063-- | A 'HashMap' with monoidal accumulation
7164newtype MonoidalHashMap k a = MonoidalHashMap { getMonoidalHashMap :: M.HashMap k a }
@@ -76,12 +69,6 @@ newtype MonoidalHashMap k a = MonoidalHashMap { getMonoidalHashMap :: M.HashMap
7669#endif
7770#if MIN_VERSION_these(0,8,0)
7871 , Semialign
79−#endif
80−#ifdef MIN_VERSION_semialign
81− , Unalign
82−#if MIN_VERSION_semialign(1,1,0)
83− , Zip
84−#endif
8572#endif
8673 )
8774
@@ -138,7 +125,7 @@ instance Newtype (MonoidalHashMap k a) (M.HashMap k a) where
138125#if MIN_VERSION_base(4,7,0)
139126instance (Eq k, Hashable k, Semigroup a) => Exts.IsList (MonoidalHashMap k a) where
140127 type Item (MonoidalHashMap k a) = (k, a)
141− fromList = MonoidalHashMap . M.fromList
128+ fromList = MonoidalHashMap . M.fromListWith (<>)
142129 {-# INLINE fromList #-}
143130 toList = M.toList . unpack
144131 {-# INLINE toList #-}
@@ -195,45 +182,39 @@ keys = M.keys . unpack
195182{-# INLINE keys #-}
196183
197184-- | /O(n*log n)/. Construct a map with the supplied mappings. If the list
198−-- contains duplicate mappings, values will be replaced.
199−fromList :: (Eq k, Hashable k) => [(k,a)] -> MonoidalHashMap k a
200−fromList = pack . M.fromList
185+-- contains duplicate mappings, values will be merged using (mappend newVal oldVal).
186+fromList :: (Eq k, Hashable k, Semigroup a) => [(k,a)] -> MonoidalHashMap k a
187+fromList = pack . M.fromListWith (<>)
201188{-# INLINE fromList #-}
202189
203−-- | /O(n*log n)/. Construct a map with the supplied mappings. If the list
204−-- contains duplicate mappings, values will be merged using the provided combining function.
205−fromListWith :: (Eq k, Hashable k) => (a -> a -> a) -> [(k,a)] -> MonoidalHashMap k a
206−fromListWith f = pack . M.fromListWith f
207−{-# INLINE fromListWith #-}
208−
209−
210190-- | /O(n*log n)/. Return a list of this map's elements. The list is produced
211191-- lazily. The order of its elements is unspecified.
212192toList :: MonoidalHashMap k a -> [(k,a)]
213193toList = M.toList . unpack
214194{-# INLINE toList #-}
215195
216−-- | /O(log n)/. Insert a value on some key, if it exists replace the value.
217−insert :: (Hashable k, Eq k)
218− => k
219− -> a
220− -> MonoidalHashMap k a
221− -> MonoidalHashMap k a
222−insert k x = pack
223− . M.insert k x
224− . unpack
225−
226−-- | /O(log n)/. Insert a value on some key, if it exists apply the combining function.
227−insertWith :: (Hashable k, Eq k)
228− => (a -> a -> a)
196+-- | /O(log n)/. Insert a value on some key, if it exists -- mappend
197+-- to the existing one.
198+insert :: (Semigroup a, Hashable k, Eq k)
199+ => a
229200 -> k
230− -> a
231201 -> MonoidalHashMap k a
232202 -> MonoidalHashMap k a
233−insertWith f k x = pack
234− . M.insertWith f k x
203+insert x k = pack
204+ . M.insertWith (<>) k x
235205 . unpack
236206
207+-- | /O(log n)/. Insert a value on some key with a function, if value
208+-- under key exists -- replace it.
209+insertOrReplace :: (Semigroup a, Hashable k, Eq k)
210+ => a
211+ -> k
212+ -> MonoidalHashMap k a
213+ -> MonoidalHashMap k a
214+insertOrReplace x k = pack
215+ . M.insert k x
216+ . unpack
217+
237218-- | /O(log n)/. Modify a value on some key with a function, if value
238219-- under key doesn't exist -- use mempty.
239220modify :: (Monoid a, Hashable k, Eq k)
@@ -247,7 +228,7 @@ modify f k = pack
247228
248229-- | /O(log n)/. Modify a value on some key with a function, providing
249230-- a default value if that key doesn't exist.
250−modifyDef :: (Hashable k, Eq k)
231+modifyDef :: (Semigroup a, Hashable k, Eq k)
251232 => a -> (a -> a)
252233 -> k -> MonoidalHashMap k a
253234 -> MonoidalHashMap k a
@@ -258,7 +239,7 @@ modifyDef d f k = pack
258239
259240-- | /O(n)/. Map a function to each key of a map, if it will result
260241-- in duplicated mappings, their values will be merged in unspecified order
261−mapKeys :: (Hashable k, Eq k, Hashable k', Eq k')
242+mapKeys :: (Semigroup a, Hashable k, Eq k, Hashable k', Eq k')
262243 => (k -> k') -> MonoidalHashMap k a -> MonoidalHashMap k' a
263244mapKeys f = fromList
264245 . fmap (\(k, v) -> (f k, v))
src/Data/IntMap/Monoidal.hs+8−20
@@ -151,12 +151,6 @@ import Data.Aeson(FromJSON, ToJSON, FromJSON1, ToJSON1)
151151import Data.Functor.Classes
152152#endif
153153import Data.Align
154−#ifdef MIN_VERSION_semialign
155−import Data.Semialign (Unalign)
156−#if MIN_VERSION_semialign(1,1,0)
157−import Data.Zip (Zip)
158−#endif
159−#endif
160154
161155-- | An 'IntMap' with monoidal accumulation
162156newtype MonoidalIntMap a = MonoidalIntMap { getMonoidalIntMap :: M.IntMap a }
@@ -166,12 +160,6 @@ newtype MonoidalIntMap a = MonoidalIntMap { getMonoidalIntMap :: M.IntMap a }
166160 Data, Typeable, Align
167161#if MIN_VERSION_these(0,8,0)
168162 , Semialign
169−#endif
170−#ifdef MIN_VERSION_semialign
171− , Unalign
172−#if MIN_VERSION_semialign(1,1,0)
173− , Zip
174−#endif
175163#endif
176164 )
177165
@@ -333,8 +321,8 @@ empty :: forall a. MonoidalIntMap a
333321empty = coerce (M.empty :: M.IntMap a)
334322{-# INLINE empty #-}
335323
336−insert :: forall a. Int -> a -> MonoidalIntMap a -> MonoidalIntMap a
337−insert = coerce (M.insert :: Int -> a -> M.IntMap a -> M.IntMap a)
324+insert :: forall a. Semigroup a => Int -> a -> MonoidalIntMap a -> MonoidalIntMap a
325+insert = coerce (M.insertWith (<>) :: Int -> a -> M.IntMap a -> M.IntMap a)
338326{-# INLINE insert #-}
339327
340328insertWith :: forall a. (a -> a -> a) -> Int -> a -> MonoidalIntMap a -> MonoidalIntMap a
@@ -433,8 +421,8 @@ mapAccumRWithKey :: forall a b c. (a -> Int -> b -> (a, c)) -> a -> MonoidalIntM
433421mapAccumRWithKey = coerce (M.mapAccumRWithKey :: (a -> Int -> b -> (a, c)) -> a -> M.IntMap b -> (a, M.IntMap c))
434422{-# INLINE mapAccumRWithKey #-}
435423
436−mapKeys :: forall a. (Int -> Int) -> MonoidalIntMap a -> MonoidalIntMap a
437−mapKeys = coerce (M.mapKeys :: (Int -> Int) -> M.IntMap a -> M.IntMap a)
424+mapKeys :: forall a. Semigroup a => (Int -> Int) -> MonoidalIntMap a -> MonoidalIntMap a
425+mapKeys = coerce (M.mapKeysWith (<>) :: (Int -> Int) -> M.IntMap a -> M.IntMap a)
438426{-# INLINE mapKeys #-}
439427
440428mapKeysWith :: forall a. (a -> a -> a) -> (Int -> Int) -> MonoidalIntMap a -> MonoidalIntMap a
@@ -493,8 +481,8 @@ toList :: forall a. MonoidalIntMap a -> [(Int, a)]
493481toList = coerce (M.toList :: M.IntMap a -> [(Int, a)])
494482{-# INLINE toList #-}
495483
496−fromList :: forall a. [(Int, a)] -> MonoidalIntMap a
497−fromList = coerce (M.fromList :: [(Int, a)] -> M.IntMap a)
484+fromList :: forall a. Semigroup a => [(Int, a)] -> MonoidalIntMap a
485+fromList = fromListWith (<>)
498486{-# INLINE fromList #-}
499487
500488fromListWith :: forall a. (a -> a -> a) -> [(Int, a)] -> MonoidalIntMap a
@@ -513,8 +501,8 @@ toDescList :: forall a. MonoidalIntMap a -> [(Int, a)]
513501toDescList = coerce (M.toDescList :: M.IntMap a -> [(Int, a)])
514502{-# INLINE toDescList #-}
515503
516−fromAscList :: forall a. [(Int, a)] -> MonoidalIntMap a
517−fromAscList = coerce (M.fromAscList :: [(Int, a)] -> M.IntMap a)
504+fromAscList :: forall a. Semigroup a => [(Int, a)] -> MonoidalIntMap a
505+fromAscList = fromAscListWith (<>)
518506{-# INLINE fromAscList #-}
519507
520508fromAscListWith :: forall a. (a -> a -> a) -> [(Int, a)] -> MonoidalIntMap a
src/Data/IntMap/Monoidal/Strict.hs+9−21
@@ -151,12 +151,6 @@ import Data.Aeson(FromJSON, ToJSON, FromJSON1, ToJSON1)
151151import Data.Functor.Classes
152152#endif
153153import Data.Align
154−#ifdef MIN_VERSION_semialign
155−import Data.Semialign (Unalign)
156−#if MIN_VERSION_semialign(1,1,0)
157−import Data.Zip (Zip)
158−#endif
159−#endif
160154
161155-- | An 'IntMap' with monoidal accumulation
162156newtype MonoidalIntMap a = MonoidalIntMap { getMonoidalIntMap :: M.IntMap a }
@@ -165,13 +159,7 @@ newtype MonoidalIntMap a = MonoidalIntMap { getMonoidalIntMap :: M.IntMap a }
165159 FromJSON, ToJSON, FromJSON1, ToJSON1,
166160 Data, Typeable, Align
167161#if MIN_VERSION_these(0,8,0)
168− , Semialign
169−#endif
170−#ifdef MIN_VERSION_semialign
171− , Unalign
172−#if MIN_VERSION_semialign(1,1,0)
173− , Zip
174−#endif
162+ , Semialign
175163#endif
176164 )
177165
@@ -333,8 +321,8 @@ empty :: forall a. MonoidalIntMap a
333321empty = coerce (M.empty :: M.IntMap a)
334322{-# INLINE empty #-}
335323
336−insert :: forall a. Int -> a -> MonoidalIntMap a -> MonoidalIntMap a
337−insert = coerce (M.insert :: Int -> a -> M.IntMap a -> M.IntMap a)
324+insert :: forall a. Semigroup a => Int -> a -> MonoidalIntMap a -> MonoidalIntMap a
325+insert = coerce (M.insertWith (<>) :: Int -> a -> M.IntMap a -> M.IntMap a)
338326{-# INLINE insert #-}
339327
340328insertWith :: forall a. (a -> a -> a) -> Int -> a -> MonoidalIntMap a -> MonoidalIntMap a
@@ -433,8 +421,8 @@ mapAccumRWithKey :: forall a b c. (a -> Int -> b -> (a, c)) -> a -> MonoidalIntM
433421mapAccumRWithKey = coerce (M.mapAccumRWithKey :: (a -> Int -> b -> (a, c)) -> a -> M.IntMap b -> (a, M.IntMap c))
434422{-# INLINE mapAccumRWithKey #-}
435423
436−mapKeys :: forall a. (Int -> Int) -> MonoidalIntMap a -> MonoidalIntMap a
437−mapKeys = coerce (M.mapKeys :: (Int -> Int) -> M.IntMap a -> M.IntMap a)
424+mapKeys :: forall a. Semigroup a => (Int -> Int) -> MonoidalIntMap a -> MonoidalIntMap a
425+mapKeys = coerce (M.mapKeysWith (<>) :: (Int -> Int) -> M.IntMap a -> M.IntMap a)
438426{-# INLINE mapKeys #-}
439427
440428mapKeysWith :: forall a. (a -> a -> a) -> (Int -> Int) -> MonoidalIntMap a -> MonoidalIntMap a
@@ -493,8 +481,8 @@ toList :: forall a. MonoidalIntMap a -> [(Int, a)]
493481toList = coerce (M.toList :: M.IntMap a -> [(Int, a)])
494482{-# INLINE toList #-}
495483
496−fromList :: forall a. [(Int, a)] -> MonoidalIntMap a
497−fromList = coerce (M.fromList :: [(Int, a)] -> M.IntMap a)
484+fromList :: forall a. Semigroup a => [(Int, a)] -> MonoidalIntMap a
485+fromList = fromListWith (<>)
498486{-# INLINE fromList #-}
499487
500488fromListWith :: forall a. (a -> a -> a) -> [(Int, a)] -> MonoidalIntMap a
@@ -513,8 +501,8 @@ toDescList :: forall a. MonoidalIntMap a -> [(Int, a)]
513501toDescList = coerce (M.toDescList :: M.IntMap a -> [(Int, a)])
514502{-# INLINE toDescList #-}
515503
516−fromAscList :: forall a. [(Int, a)] -> MonoidalIntMap a
517−fromAscList = coerce (M.fromAscList :: [(Int, a)] -> M.IntMap a)
504+fromAscList :: forall a. Semigroup a => [(Int, a)] -> MonoidalIntMap a
505+fromAscList = fromAscListWith (<>)
518506{-# INLINE fromAscList #-}
519507
520508fromAscListWith :: forall a. (a -> a -> a) -> [(Int, a)] -> MonoidalIntMap a
src/Data/Map/Monoidal.hs+8−20
@@ -151,12 +151,6 @@ import Data.Aeson(FromJSON, ToJSON, FromJSON1, ToJSON1)
151151import Data.Functor.Classes
152152#endif
153153import Data.Align
154−#ifdef MIN_VERSION_semialign
155−import Data.Semialign (Unalign)
156−#if MIN_VERSION_semialign(1,1,0)
157−import Data.Zip (Zip)
158−#endif
159−#endif
160154
161155-- | A 'Map' with monoidal accumulation
162156newtype MonoidalMap k a = MonoidalMap { getMonoidalMap :: M.Map k a }
@@ -166,12 +160,6 @@ newtype MonoidalMap k a = MonoidalMap { getMonoidalMap :: M.Map k a }
166160 , Data, Typeable, Align
167161#if MIN_VERSION_these(0,8,0)
168162 , Semialign
169−#endif
170−#ifdef MIN_VERSION_semialign
171− , Unalign
172−#if MIN_VERSION_semialign(1,1,0)
173− , Zip
174−#endif
175163#endif
176164 )
177165
@@ -335,8 +323,8 @@ empty :: forall k a. MonoidalMap k a
335323empty = coerce (M.empty :: M.Map k a)
336324{-# INLINE empty #-}
337325
338−insert :: forall k a. Ord k => k -> a -> MonoidalMap k a -> MonoidalMap k a
339−insert = coerce (M.insert :: k -> a -> M.Map k a -> M.Map k a)
326+insert :: forall k a. (Ord k, Semigroup a) => k -> a -> MonoidalMap k a -> MonoidalMap k a
327+insert = insertWith (<>)
340328{-# INLINE insert #-}
341329
342330insertWith :: forall k a. Ord k => (a -> a -> a) -> k -> a -> MonoidalMap k a -> MonoidalMap k a
@@ -435,8 +423,8 @@ mapAccumRWithKey :: forall k a b c. (a -> k -> b -> (a, c)) -> a -> MonoidalMap
435423mapAccumRWithKey = coerce (M.mapAccumRWithKey :: (a -> k -> b -> (a, c)) -> a -> M.Map k b -> (a, M.Map k c))
436424{-# INLINE mapAccumRWithKey #-}
437425
438−mapKeys :: forall k1 k2 a. Ord k2 => (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
439−mapKeys = coerce (M.mapKeys :: (k1 -> k2) -> M.Map k1 a -> M.Map k2 a)
426+mapKeys :: forall k1 k2 a. (Ord k2, Semigroup a) => (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
427+mapKeys = mapKeysWith (<>)
440428{-# INLINE mapKeys #-}
441429
442430mapKeysWith :: forall k1 k2 a. Ord k2 => (a -> a -> a) -> (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
@@ -513,8 +501,8 @@ toList :: forall k a. MonoidalMap k a -> [(k, a)]
513501toList = coerce (M.toList :: M.Map k a -> [(k, a)])
514502{-# INLINE toList #-}
515503
516−fromList :: forall k a. Ord k => [(k, a)] -> MonoidalMap k a
517−fromList = coerce (M.fromList :: [(k, a)] -> M.Map k a)
504+fromList :: forall k a. (Ord k, Semigroup a) => [(k, a)] -> MonoidalMap k a
505+fromList = fromListWith (<>)
518506{-# INLINE fromList #-}
519507
520508fromListWith :: forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> MonoidalMap k a
@@ -533,8 +521,8 @@ toDescList :: forall k a. MonoidalMap k a -> [(k, a)]
533521toDescList = coerce (M.toDescList :: M.Map k a -> [(k, a)])
534522{-# INLINE toDescList #-}
535523
536−fromAscList :: forall k a. Eq k => [(k, a)] -> MonoidalMap k a
537−fromAscList = coerce (M.fromAscList :: [(k, a)] -> M.Map k a)
524+fromAscList :: forall k a. (Eq k, Semigroup a) => [(k, a)] -> MonoidalMap k a
525+fromAscList = fromAscListWith (<>)
538526{-# INLINE fromAscList #-}
539527
540528fromAscListWith :: forall k a. Eq k => (a -> a -> a) -> [(k, a)] -> MonoidalMap k a
src/Data/Map/Monoidal/Strict.hs+4−14
@@ -151,12 +151,6 @@ import Data.Aeson(FromJSON, ToJSON, FromJSON1, ToJSON1)
151151import Data.Functor.Classes
152152#endif
153153import Data.Align
154−#ifdef MIN_VERSION_semialign
155−import Data.Semialign (Unalign)
156−#if MIN_VERSION_semialign(1,1,0)
157−import Data.Zip (Zip)
158−#endif
159−#endif
160154
161155-- | A 'Map' with monoidal accumulation
162156newtype MonoidalMap k a = MonoidalMap { getMonoidalMap :: M.Map k a }
@@ -166,12 +160,6 @@ newtype MonoidalMap k a = MonoidalMap { getMonoidalMap :: M.Map k a }
166160 , Data, Typeable, Align
167161#if MIN_VERSION_these(0,8,0)
168162 , Semialign
169−#endif
170−#ifdef MIN_VERSION_semialign
171− , Unalign
172−#if MIN_VERSION_semialign(1,1,0)
173− , Zip
174−#endif
175163#endif
176164 )
177165
@@ -334,8 +322,8 @@ empty :: forall k a. MonoidalMap k a
334322empty = coerce (M.empty :: M.Map k a)
335323{-# INLINE empty #-}
336324
337−insert :: forall k a. Ord k => k -> a -> MonoidalMap k a -> MonoidalMap k a
338−insert = coerce (M.insert :: k -> a -> M.Map k a -> M.Map k a)
325+insert :: forall k a. (Ord k, Semigroup a) => k -> a -> MonoidalMap k a -> MonoidalMap k a
326+insert = insertWith (<>)
339327{-# INLINE insert #-}
340328
341329insertWith :: forall k a. Ord k => (a -> a -> a) -> k -> a -> MonoidalMap k a -> MonoidalMap k a
@@ -699,3 +687,5 @@ maxViewWithKey = coerce (M.maxViewWithKey :: M.Map k a -> Maybe ((k, a), M.Map k
699687valid :: forall k a. Ord k => MonoidalMap k a -> Bool
700688valid = coerce (M.valid :: Ord k => M.Map k a -> Bool)
701689{-# INLINE valid #-}
690+
691+