git.iko.soy/monoidal-containers
on master help sign in
Monoidal map
commit6755153fd69afb469aad843c86f0fcf8ee3a03f5 authorBen Gamari <bgamari.foss@gmail.com> dateTue 20 Jan 2015, 11:12 (12 years ago)
4 files changed+114
LICENSE+30 Setup.hs+2 monoidal-containers.cabal+25 src/Data/Map/Monoidal.hs+57
LICENSEnew file+30
@@ -0,0 +1,30 @@
1+Copyright (c) 2015, Ben Gamari
2+
3+All rights reserved.
4+
5+Redistribution and use in source and binary forms, with or without
6+modification, are permitted provided that the following conditions are met:
7+
8+ * Redistributions of source code must retain the above copyright
9+ notice, this list of conditions and the following disclaimer.
10+
11+ * Redistributions in binary form must reproduce the above
12+ copyright notice, this list of conditions and the following
13+ disclaimer in the documentation and/or other materials provided
14+ with the distribution.
15+
16+ * Neither the name of Ben Gamari nor the names of other
17+ contributors may be used to endorse or promote products derived
18+ from this software without specific prior written permission.
19+
20+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
monoidal-containers.cabalnew file+25
@@ -0,0 +1,25 @@
1+-- Initial monoidal-containers.cabal generated by cabal init. For further
2+-- documentation, see http://haskell.org/cabal/users-guide/
3+
4+name: monoidal-containers
5+version: 0.1.0.0
6+synopsis: Containers with monoidal accumulation
7+-- description:
8+homepage: http://github.com/bgamari/monoidal-containers
9+license: BSD3
10+license-file: LICENSE
11+author: Ben Gamari
12+maintainer: ben@smart-cactus.org
13+-- copyright:
14+category: Data
15+build-type: Simple
16+-- extra-source-files:
17+cabal-version: >=1.10
18+
19+library
20+ exposed-modules: Data.Map.Monoidal
21+ -- other-modules:
22+ other-extensions: CPP, MultiParamTypeClasses, GeneralizedNewtypeDeriving, DeriveTraversable, DeriveDataTypeable
23+ build-depends: base >=4.7 && <4.8, deepseq >=1.3 && <1.4, containers >=0.5 && <0.6, lens >=4.4 && <4.5, newtype >=0.2 && <0.3
24+ hs-source-dirs: src
25+ default-language: Haskell2010
src/Data/Map/Monoidal.hsnew file+57
@@ -0,0 +1,57 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE MultiParamTypeClasses #-}
3+{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5+{-# LANGUAGE DeriveTraversable #-}
6+{-# LANGUAGE DeriveDataTypeable #-}
7+
8+module Data.Map.Monoidal ( MonoidalMap ) where
9+
10+import Data.Monoid
11+import Data.Foldable (Foldable)
12+import Data.Traversable (Traversable)
13+import Control.Applicative (Applicative, pure)
14+import Data.Data (Data)
15+import Data.Typeable (Typeable)
16+
17+#if MIN_VERSION_base(4,7,0)
18+import GHC.Exts (IsList(..))
19+#endif
20+
21+import Control.DeepSeq
22+import qualified Data.Map as M
23+import Control.Lens
24+import Control.Newtype
25+
26+-- | A 'Map' with monoidal accumulation
27+newtype MonoidalMap k a = MM (M.Map k a)
28+ deriving (Show, Read, Functor, Eq, Ord, NFData,
29+ Foldable, Traversable,
30+ Data, Typeable)
31+
32+type instance Index (MonoidalMap k a) = k
33+type instance IxValue (MonoidalMap k a) = a
34+instance Ord k => Ixed (MonoidalMap k a) where
35+ ix k f (MM m) = case M.lookup k m of
36+ Just v -> f v <&> \v' -> MM (M.insert k v' m)
37+ Nothing -> pure (MM m)
38+ {-# INLINE ix #-}
39+
40+instance (Ord k, Monoid a) => Monoid (MonoidalMap k a) where
41+ mempty = MM mempty
42+ {-# INLINE mempty #-}
43+ MM a `mappend` MM b = MM $ M.unionWith mappend a b
44+ {-# INLINE mappend #-}
45+
46+instance Newtype (MonoidalMap k a) (M.Map k a) where
47+ pack = MM
48+ {-# INLINE pack #-}
49+ unpack (MM a) = a
50+ {-# INLINE unpack #-}
51+
52+#if MIN_VERSION_base(4,7,0)
53+instance Ord k => IsList (MonoidalMap k a) where
54+ type Item (MonoidalMap k a) = (k, a)
55+ fromList = MM . M.fromList
56+ toList = M.toList . unpack
57+#endif