monoid-map (empty) → 0.1.0.0
raw patch · 5 files changed
+131/−0 lines, 5 filesdep +appendmapdep +basedep +monoidal-containers
Dependencies added: appendmap, base, monoidal-containers, reflex, witherable
Files
- CHANGELOG.md +4/−0
- LICENSE +30/−0
- README.md +5/−0
- monoid-map.cabal +37/−0
- src/Data/MonoidMap.hs +55/−0
+ CHANGELOG.md view
@@ -0,0 +1,4 @@+# Revision history for monoid-map++## 2021-11-17+* Added the code for Data.MonoidMap.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2021, Obsidian Systems LLC++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Obsidian Systems LLC nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,5 @@+# monoid-map+[](https://haskell.org) [](https://hackage.haskell.org/package/monoid-map) [](https://matrix.hackage.haskell.org/#/package/monoid-map) [](https://github.com/obsidiansystems/monoid-map/actions) [](https://github.com/obsidiansystems/monoid-map/blob/master/LICENSE)+++Newtype wrapper around 'Data.Map.Monoidal.MonoidalMap' that has a correct 'Group' instance.
+ monoid-map.cabal view
@@ -0,0 +1,37 @@+cabal-version: 2.4+name: monoid-map+version: 0.1.0.0+synopsis: Newtype wrapper around 'Data.Map.Monoidal.MonoidalMap' that has a correct 'Group' instance.+description:+ The 'Group' instance for Data.MonoidMap has a unique neutral element,+ as compared to 'Data.Map.Monoidal.MonoidalMap'.++homepage: https://github.com/obsidiansystems/monoid-map+bug-reports:+ https://github.com/obsidiansystems/monoid-map/issues++license: BSD-3-Clause+license-file: LICENSE+author: Obsidian Systems LLC+maintainer: maintainer@obsidian.systems+copyright: (c) 2021 Obsidian Systems LLC+category: Data+extra-source-files: CHANGELOG.md README.md++library+ exposed-modules: Data.MonoidMap+ other-extensions:+ DeriveTraversable+ FlexibleContexts+ GeneralizedNewtypeDeriving+ TypeFamilies+ UndecidableInstances++ build-depends:+ appendmap+ , base >= 4 && < 5+ , monoidal-containers+ , reflex+ , witherable+ hs-source-dirs: src+ default-language: Haskell2010
+ src/Data/MonoidMap.hs view
@@ -0,0 +1,55 @@+-- | This module contains a newtype wrapper around 'Data.Map.Map' that has a+-- correct 'Group' instance compared to the one for+-- 'Data.Map.Monoidal.MonoidalMap', in that it has a unique neutral element.+-- This comes with different constraints on the parameters (check the instances+-- for 'Semigroup' and 'Monoid' of the corresponding data structures if you're+-- interested).+--+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE UndecidableInstances #-} -- For (Eq (QueryResult q), Ord k, Query q) => Query (MonoidMap k q)+{-# LANGUAGE StandaloneDeriving #-}+module Data.MonoidMap where++import Data.Witherable+import Data.AppendMap+import Data.Map.Monoidal (MonoidalMap)+import Data.Map.Monoidal as Map+import Data.Semigroup (Semigroup, (<>))+import Reflex (Query, QueryResult, crop, Group(..), Additive)++-- | Newtype wrapper around Data.Map.Monoidal.MonoidalMap+newtype MonoidMap k v = MonoidMap { unMonoidMap :: MonoidalMap k v }+ deriving (Show, Eq, Ord, Foldable, Functor, Traversable)++deriving instance Filterable (MonoidalMap k) => Filterable (MonoidMap k)++-- | Convert a MonoidalMap into a MonoidMap+monoidMap :: (Ord k, Eq v, Monoid v) => MonoidalMap k v -> MonoidMap k v+monoidMap = MonoidMap . Map.filter (/= mempty)++instance (Eq (QueryResult q), Ord k, Query q) => Query (MonoidMap k q) where+ type QueryResult (MonoidMap k q) = MonoidMap k (QueryResult q)+ crop (MonoidMap q) (MonoidMap qr) =+ -- This assumes that the query result of a null query should be null+ monoidMap $ Map.intersectionWith crop q qr++instance (Monoid a, Eq a, Ord k) => Semigroup (MonoidMap k a) where+ MonoidMap a <> MonoidMap b =+ let combine _ a' b' =+ let c = a' `mappend` b'+ in if c == mempty+ then Nothing+ else Just c+ in MonoidMap $ Map.mergeWithKey combine id id a b++instance (Ord k, Monoid a, Eq a) => Monoid (MonoidMap k a) where+ mempty = MonoidMap Map.empty+ mappend = (<>)++instance (Ord k, Monoid a, Eq a, Group a) => Group (MonoidMap k a) where+ negateG = fmap negateG++instance (Ord k, Monoid a, Eq a, Group a, Additive a) => Additive (MonoidMap k a)