packages feed

monoidmap-aeson (empty) → 0.0.0.0

raw patch · 11 files changed

+911/−0 lines, 11 filesdep +QuickCheckdep +aesondep +base

Dependencies added: QuickCheck, aeson, base, containers, hspec, hspec-golden-aeson, monoid-subclasses, monoidmap, monoidmap-aeson, quickcheck-classes, quickcheck-quid, text

Files

+ CHANGELOG.md view
@@ -0,0 +1,3 @@+# 0.0.0.0++- Initial release.
+ LICENSE view
@@ -0,0 +1,201 @@+                                 Apache License+                           Version 2.0, January 2004+                        http://www.apache.org/licenses/++   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION++   1. Definitions.++      "License" shall mean the terms and conditions for use, reproduction,+      and distribution as defined by Sections 1 through 9 of this document.++      "Licensor" shall mean the copyright owner or entity authorized by+      the copyright owner that is granting the License.++      "Legal Entity" shall mean the union of the acting entity and all+      other entities that control, are controlled by, or are under common+      control with that entity. For the purposes of this definition,+      "control" means (i) the power, direct or indirect, to cause the+      direction or management of such entity, whether by contract or+      otherwise, or (ii) ownership of fifty percent (50%) or more of the+      outstanding shares, or (iii) beneficial ownership of such entity.++      "You" (or "Your") shall mean an individual or Legal Entity+      exercising permissions granted by this License.++      "Source" form shall mean the preferred form for making modifications,+      including but not limited to software source code, documentation+      source, and configuration files.++      "Object" form shall mean any form resulting from mechanical+      transformation or translation of a Source form, including but+      not limited to compiled object code, generated documentation,+      and conversions to other media types.++      "Work" shall mean the work of authorship, whether in Source or+      Object form, made available under the License, as indicated by a+      copyright notice that is included in or attached to the work+      (an example is provided in the Appendix below).++      "Derivative Works" shall mean any work, whether in Source or Object+      form, that is based on (or derived from) the Work and for which the+      editorial revisions, annotations, elaborations, or other modifications+      represent, as a whole, an original work of authorship. For the purposes+      of this License, Derivative Works shall not include works that remain+      separable from, or merely link (or bind by name) to the interfaces of,+      the Work and Derivative Works thereof.++      "Contribution" shall mean any work of authorship, including+      the original version of the Work and any modifications or additions+      to that Work or Derivative Works thereof, that is intentionally+      submitted to Licensor for inclusion in the Work by the copyright owner+      or by an individual or Legal Entity authorized to submit on behalf of+      the copyright owner. For the purposes of this definition, "submitted"+      means any form of electronic, verbal, or written communication sent+      to the Licensor or its representatives, including but not limited to+      communication on electronic mailing lists, source code control systems,+      and issue tracking systems that are managed by, or on behalf of, the+      Licensor for the purpose of discussing and improving the Work, but+      excluding communication that is conspicuously marked or otherwise+      designated in writing by the copyright owner as "Not a Contribution."++      "Contributor" shall mean Licensor and any individual or Legal Entity+      on behalf of whom a Contribution has been received by Licensor and+      subsequently incorporated within the Work.++   2. Grant of Copyright License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      copyright license to reproduce, prepare Derivative Works of,+      publicly display, publicly perform, sublicense, and distribute the+      Work and such Derivative Works in Source or Object form.++   3. Grant of Patent License. Subject to the terms and conditions of+      this License, each Contributor hereby grants to You a perpetual,+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable+      (except as stated in this section) patent license to make, have made,+      use, offer to sell, sell, import, and otherwise transfer the Work,+      where such license applies only to those patent claims licensable+      by such Contributor that are necessarily infringed by their+      Contribution(s) alone or by combination of their Contribution(s)+      with the Work to which such Contribution(s) was submitted. If You+      institute patent litigation against any entity (including a+      cross-claim or counterclaim in a lawsuit) alleging that the Work+      or a Contribution incorporated within the Work constitutes direct+      or contributory patent infringement, then any patent licenses+      granted to You under this License for that Work shall terminate+      as of the date such litigation is filed.++   4. Redistribution. You may reproduce and distribute copies of the+      Work or Derivative Works thereof in any medium, with or without+      modifications, and in Source or Object form, provided that You+      meet the following conditions:++      (a) You must give any other recipients of the Work or+          Derivative Works a copy of this License; and++      (b) You must cause any modified files to carry prominent notices+          stating that You changed the files; and++      (c) You must retain, in the Source form of any Derivative Works+          that You distribute, all copyright, patent, trademark, and+          attribution notices from the Source form of the Work,+          excluding those notices that do not pertain to any part of+          the Derivative Works; and++      (d) If the Work includes a "NOTICE" text file as part of its+          distribution, then any Derivative Works that You distribute must+          include a readable copy of the attribution notices contained+          within such NOTICE file, excluding those notices that do not+          pertain to any part of the Derivative Works, in at least one+          of the following places: within a NOTICE text file distributed+          as part of the Derivative Works; within the Source form or+          documentation, if provided along with the Derivative Works; or,+          within a display generated by the Derivative Works, if and+          wherever such third-party notices normally appear. The contents+          of the NOTICE file are for informational purposes only and+          do not modify the License. You may add Your own attribution+          notices within Derivative Works that You distribute, alongside+          or as an addendum to the NOTICE text from the Work, provided+          that such additional attribution notices cannot be construed+          as modifying the License.++      You may add Your own copyright statement to Your modifications and+      may provide additional or different license terms and conditions+      for use, reproduction, or distribution of Your modifications, or+      for any such Derivative Works as a whole, provided Your use,+      reproduction, and distribution of the Work otherwise complies with+      the conditions stated in this License.++   5. Submission of Contributions. Unless You explicitly state otherwise,+      any Contribution intentionally submitted for inclusion in the Work+      by You to the Licensor shall be under the terms and conditions of+      this License, without any additional terms or conditions.+      Notwithstanding the above, nothing herein shall supersede or modify+      the terms of any separate license agreement you may have executed+      with Licensor regarding such Contributions.++   6. Trademarks. This License does not grant permission to use the trade+      names, trademarks, service marks, or product names of the Licensor,+      except as required for reasonable and customary use in describing the+      origin of the Work and reproducing the content of the NOTICE file.++   7. Disclaimer of Warranty. Unless required by applicable law or+      agreed to in writing, Licensor provides the Work (and each+      Contributor provides its Contributions) on an "AS IS" BASIS,+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+      implied, including, without limitation, any warranties or conditions+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+      PARTICULAR PURPOSE. You are solely responsible for determining the+      appropriateness of using or redistributing the Work and assume any+      risks associated with Your exercise of permissions under this License.++   8. Limitation of Liability. In no event and under no legal theory,+      whether in tort (including negligence), contract, or otherwise,+      unless required by applicable law (such as deliberate and grossly+      negligent acts) or agreed to in writing, shall any Contributor be+      liable to You for damages, including any direct, indirect, special,+      incidental, or consequential damages of any character arising as a+      result of this License or out of the use or inability to use the+      Work (including but not limited to damages for loss of goodwill,+      work stoppage, computer failure or malfunction, or any and all+      other commercial damages or losses), even if such Contributor+      has been advised of the possibility of such damages.++   9. Accepting Warranty or Additional Liability. While redistributing+      the Work or Derivative Works thereof, You may choose to offer,+      and charge a fee for, acceptance of support, warranty, indemnity,+      or other liability obligations and/or rights consistent with this+      License. However, in accepting such obligations, You may act only+      on Your own behalf and on Your sole responsibility, not on behalf+      of any other Contributor, and only if You agree to indemnify,+      defend, and hold each Contributor harmless for any liability+      incurred by, or claims asserted against, such Contributor by reason+      of your accepting any such warranty or additional liability.++   END OF TERMS AND CONDITIONS++   APPENDIX: How to apply the Apache License to your work.++      To apply the Apache License to your work, attach the following+      boilerplate notice, with the fields enclosed by brackets "[]"+      replaced with your own identifying information. (Don't include+      the brackets!)  The text should be enclosed in the appropriate+      comment syntax for the file format. We also recommend that a+      file or class name and description of purpose be included on the+      same "printed page" as the copyright notice for easier+      identification within third-party archives.++   Copyright © 2022–2025 Jonathan Knowles++   Licensed under the Apache License, Version 2.0 (the "License");+   you may not use this file except in compliance with the License.+   You may obtain a copy of the License at++       http://www.apache.org/licenses/LICENSE-2.0++   Unless required by applicable law or agreed to in writing, software+   distributed under the License is distributed on an "AS IS" BASIS,+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+   See the License for the specific language governing permissions and+   limitations under the License.
+ README.md view
@@ -0,0 +1,6 @@+# `monoidmap-aeson`
+<a href="https://jonathanknowles.github.io/monoidmap-aeson/"><img src="https://img.shields.io/badge/API-Documentation-227755" /></a>
+
+## Overview
+
+This package provides JSON serialisation support for the [`monoidmap`](https://hackage.haskell.org/package/monoidmap) package with [`aeson`](https://hackage.haskell.org/package/aeson).
+ components/monoidmap-aeson-test/Data/MonoidMap/JSONSpec.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-- |+-- Copyright: © 2022–2025 Jonathan Knowles+-- License: Apache-2.0+--+module Data.MonoidMap.JSONSpec+    ( spec+    )+where++import Prelude++import Control.Monad+    ( forM_+    )+import Data.MonoidMap+    ( MonoidMap+    )+import Data.MonoidMap.JSON+    (+    )+import Data.Proxy+    ( Proxy (Proxy)+    )+import Data.Text+    ( Text+    )+import Test.Aeson.Internal.GoldenSpecs+    ( goldenSpecs+    )+import Test.Common+    ( Test+    , TestKey+    , TestValueType (TestValueType)+    , makeSpec+    , testValueTypesAll+    )+import Test.Hspec+    ( Spec+    , describe+    )+import Test.QuickCheck.Classes+    ( jsonLaws+    )+import Test.QuickCheck.Classes.Hspec+    ( testLaws+    )++import qualified Test.Aeson.Internal.Utils as Golden++spec :: Spec+spec = do+    describe "JSON"+        $ forM_ testKeyValueTypes+        $ \(TestKeyType k, TestValueType v) -> specForTypes k v+  where+    testKeyValueTypes =+        [(kt, vt) | kt <- testKeyTypes, vt <- testValueTypesAll]++specForTypes :: forall k v. (Test k v) => Proxy k -> Proxy v -> Spec+specForTypes = makeSpec $ do+    testLaws @(MonoidMap k v) jsonLaws+    goldenSpecs goldenSettings (Proxy @(MonoidMap k v))++goldenSettings :: Golden.Settings+goldenSettings =+    Golden.defaultSettings+        { Golden.goldenDirectoryOption =+            Golden.CustomDirectoryName "golden"+        , Golden.comparisonFile =+            Golden.OverwriteGoldenFile+        , Golden.randomMismatchOption =+            Golden.RandomMismatchError+        , Golden.useModuleNameAsSubDirectory =+            False+        , Golden.sampleSize =+            10+        }++data TestKeyType = forall k. (TestKey k) => TestKeyType (Proxy k)++testKeyTypes :: [TestKeyType]+testKeyTypes =+    mconcat [testKeyTypes_textual, testKeyTypes_nonTextual]+  where+    -- A selection of key types for which keys are encoded as JSON strings.+    -- For these types, 'MonoidMap' objects are encoded as JSON objects.+    testKeyTypes_textual =+        [ TestKeyType (Proxy @Int)+        , TestKeyType (Proxy @Text)+        ]+    -- A selection of key types for which keys are NOT encoded as JSON strings.+    -- For these types, 'MonoidMap' objects are encoded as JSON arrays.+    testKeyTypes_nonTextual =+        [ TestKeyType (Proxy @[Int])+        , TestKeyType (Proxy @(Int, Int))+        ]
+ components/monoidmap-aeson-test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ components/monoidmap-aeson-test/SpecHook.hs view
@@ -0,0 +1,6 @@+module SpecHook where++import Test.Hspec++hook :: Spec -> Spec+hook = parallel
+ components/monoidmap-aeson-test/Test/Common.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{- HLINT ignore "Redundant bracket" -}+{- HLINT ignore "Use camelCase" -}+{- HLINT ignore "Use null" -}++-- |+-- Copyright: © 2022–2025 Jonathan Knowles+-- License: Apache-2.0+--+module Test.Common+    ( Key+    , Test+    , TestKey+    , TestValueType (..)+    , testValueTypesAll+    , TestValue+    , makeSpec+    , property+    ) where++import Prelude++import Data.Aeson+    ( FromJSON+    , FromJSONKey+    , ToJSON+    , ToJSONKey+    )+import Data.Kind+    ( Constraint, Type )+import Data.Monoid+    ( Dual, Product, Sum )+import Data.Monoid.Null+    ( MonoidNull )+import Data.MonoidMap+    ( MonoidMap )+import Data.MonoidMap.JSON+    ()+import Data.Proxy+    ( Proxy (Proxy) )+import Data.Set+    ( Set )+import Data.Text+    ( Text )+import Data.Typeable+    ( Typeable, typeRep )+import GHC.Exts+    ( IsList (..) )+import Numeric.Natural+    ( Natural )+import Test.Hspec+    ( Spec, describe )+import Test.Key+    ( Key2, Key4 )+import Test.QuickCheck+    ( Arbitrary (..)+    , CoArbitrary (..)+    , Function (..)+    , Property+    , Testable+    , arbitrarySizedIntegral+    , checkCoverage+    , coarbitraryIntegral+    , coarbitraryShow+    , frequency+    , functionIntegral+    , functionMap+    , functionShow+    , listOf+    , scale+    , shrinkIntegral+    , shrinkMapBy+    )++import qualified Data.MonoidMap as MonoidMap+import qualified Data.Text as Text+import qualified Test.QuickCheck as QC++--------------------------------------------------------------------------------+-- Arbitrary instances+--------------------------------------------------------------------------------++instance (Arbitrary k, Ord k, Arbitrary v, MonoidNull v) =>+    Arbitrary (MonoidMap k v)+  where+    arbitrary =+        fromList <$> scale (`mod` 16) (listOf ((,) <$> arbitrary <*> arbitrary))+    shrink =+        shrinkMapBy MonoidMap.fromMap MonoidMap.toMap shrink++instance (CoArbitrary k, CoArbitrary v) =>+    CoArbitrary (MonoidMap k v)+  where+    coarbitrary = coarbitrary . MonoidMap.toMap++instance (Function k, Function v, Ord k, MonoidNull v) =>+    Function (MonoidMap k v)+  where+    function = functionMap MonoidMap.toMap MonoidMap.fromMap++instance Arbitrary Natural where+    arbitrary = arbitrarySizedIntegral+    shrink = shrinkIntegral++instance CoArbitrary Natural where+    coarbitrary = coarbitraryIntegral++instance Function Natural where+    function = functionIntegral++instance Arbitrary Text where+    arbitrary = Text.pack <$> listOf genChar+      where+        genChar = frequency+            [ (64, pure 'a')+            , (16, pure 'b')+            , ( 4, pure 'c')+            , ( 1, pure 'd')+            ]++instance CoArbitrary Text where+    coarbitrary = coarbitraryShow++instance Function Text where+    function = functionShow++--------------------------------------------------------------------------------+-- Test keys+--------------------------------------------------------------------------------++type SmallKey = Key2+type Key = Key4++--------------------------------------------------------------------------------+-- Test constraints+--------------------------------------------------------------------------------++type Test k v = (TestKey k, TestValue v)++type TestKey k =+    ( Arbitrary k+    , CoArbitrary k+    , Function k+    , Ord k+    , Show k+    , Typeable k+    , ToJSONKey k+    , FromJSONKey k+    )++type TestValue v =+    ( Arbitrary v+    , CoArbitrary v+    , Eq v+    , Function v+    , MonoidNull v+    , Show v+    , Typeable v+    , ToJSON v+    , FromJSON v+    )++--------------------------------------------------------------------------------+-- Test value types+--------------------------------------------------------------------------------++data TestValueType (c :: Type -> Constraint) =+    forall v. (TestValue v, c v) => TestValueType (Proxy v)++testValueTypesAll :: [TestValueType MonoidNull]+testValueTypesAll =+    [ TestValueType (Proxy @(Dual Text))+    , TestValueType (Proxy @(Dual [Int]))+    , TestValueType (Proxy @(Dual [Natural]))+    , TestValueType (Proxy @(Product Int))+    , TestValueType (Proxy @(Product Natural))+    , TestValueType (Proxy @(Set Int))+    , TestValueType (Proxy @(Set Natural))+    , TestValueType (Proxy @(Sum Int))+    , TestValueType (Proxy @(Sum Natural))+    , TestValueType (Proxy @(Text))+    , TestValueType (Proxy @[Int])+    , TestValueType (Proxy @[Natural])+    , TestValueType (Proxy @(MonoidMap SmallKey (Sum Int)))+    , TestValueType (Proxy @(MonoidMap SmallKey (Sum Natural)))+    ]++--------------------------------------------------------------------------------+-- Utilities+--------------------------------------------------------------------------------++makeSpec :: forall k v. Test k v => Spec -> Proxy k -> Proxy v -> Spec+makeSpec spec _k _v = describe (show $ typeRep (Proxy @(MonoidMap k v))) spec++property :: Testable t => t -> Property+property = checkCoverage . QC.property
+ components/monoidmap-aeson-test/Test/Key.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}++-- |+-- Copyright: © 2022–2025 Jonathan Knowles+-- License: Apache-2.0+--+-- Quasi-unique keys.+--+module Test.Key+    ( Key1+    , Key2+    , Key4+    , Key8+    )+where++import Prelude++import Data.Aeson.Types+    ( FromJSON (parseJSON)+    , FromJSONKey (fromJSONKey)+    , FromJSONKeyFunction (FromJSONKeyTextParser)+    , Parser+    , ToJSON (toEncoding, toJSON)+    , ToJSONKey (toJSONKey)+    , toJSONKeyText+    , withText+    )+import Data.Text+    ( Text+    )+import GHC.Generics+    ( Generic+    )+import GHC.TypeLits+    ( Nat+    )+import Test.QuickCheck+    ( Arbitrary+    , CoArbitrary+    , Function+    )+import Test.QuickCheck.Quid+    ( Latin (Latin)+    , Quid+    , Size (Size)+    )+import Text.Read+    ( readMaybe+    )++import qualified Data.Text as Text++newtype Key (size :: Nat) = Key Quid+    deriving stock (Eq, Generic, Ord)+    deriving (Read, Show) via Latin Quid+    deriving (Arbitrary) via Size size Quid+    deriving (CoArbitrary) via Quid+    deriving anyclass (Function)++type Key1 = Key 1+type Key2 = Key 2+type Key4 = Key 4+type Key8 = Key 8++instance ToJSON (Key size) where+    toEncoding = toEncoding . toText+    toJSON = toJSON . toText++instance ToJSONKey (Key size) where+    toJSONKey = toJSONKeyText toText++instance FromJSON (Key size) where+    parseJSON = withText "Key" parseFromText++instance FromJSONKey (Key size) where+    fromJSONKey = FromJSONKeyTextParser parseFromText++toText :: Key size -> Text+toText = Text.dropAround (== '\"') . Text.pack . show++maybeFromText :: Text -> Maybe (Key size)+maybeFromText = readMaybe . show . Text.unpack++parseFromText :: Text -> Parser (Key size)+parseFromText =+    maybe (fail failureMessage) pure . maybeFromText+  where+    failureMessage = "Failed to parse key from JSON"
+ components/monoidmap-aeson-test/Test/QuickCheck/Classes/Hspec.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE PolyKinds #-}++-- |+-- Copyright: © 2022–2025 Jonathan Knowles+-- License: Apache-2.0+--+-- Provides testing functions to check that type class instances obey laws.+--+module Test.QuickCheck.Classes.Hspec+    ( testLaws+    , testLawsMany+    ) where++import Prelude++import Control.Monad+    ( forM_ )+import Data.Proxy+    ( Proxy (..) )+import Data.Typeable+    ( Typeable, typeRep )+import Test.Hspec+    ( Spec, describe, it, parallel )+import Test.QuickCheck.Classes+    ( Laws (..) )++-- | Constructs a test to check that the given type class instance obeys the+--   given set of laws.+--+-- Example usage:+--+-- >>> testLaws @Natural ordLaws+-- >>> testLaws @(Map Int) functorLaws+--+testLaws+    :: forall a. Typeable a+    => (Proxy a -> Laws)+    -> Spec+testLaws getLaws =+    parallel $ describe description $+        forM_ (lawsProperties laws) $ uncurry it+  where+    description = mconcat+        [ "Testing "+        , lawsTypeclass laws+        , " laws for type "+        , show (typeRep $ Proxy @a)+        ]+    laws = getLaws $ Proxy @a++-- | Calls `testLaws` with multiple sets of laws.+--+-- Example usage:+--+-- >>> testLawsMany @Natural [eqLaws, ordLaws]+-- >>> testLawsMany @(Map Int) [foldableLaws, functorLaws]+--+testLawsMany+    :: forall a. Typeable a+    => [Proxy a -> Laws]+    -> Spec+testLawsMany getLawsMany =+    testLaws @a `mapM_` getLawsMany
+ components/monoidmap-aeson/Data/MonoidMap/JSON.hs view
@@ -0,0 +1,131 @@+{-# OPTIONS_GHC -Wno-orphans #-}++-- |+-- Copyright: © 2022–2025 Jonathan Knowles+-- License: Apache-2.0+--+module Data.MonoidMap.JSON+    (+    -- * Introduction+    -- $_introduction++    -- * Examples+    -- $_examples++    -- * Laws+    -- $_laws+    )+    where++import Prelude++import Data.Aeson+    ( FromJSON (parseJSON)+    , FromJSONKey+    , ToJSON (toEncoding, toJSON)+    , ToJSONKey+    , encode+    )+import Data.Map.Strict+    ( Map+    )+import Data.Monoid+    ( Sum+    )+import Data.Monoid.Null+    ( MonoidNull+    )+import Data.MonoidMap+    ( MonoidMap+    , fromList+    , fromMap+    , toMap+    )++-- $_introduction+-- #_introduction#+--+-- This module provides instances of 'ToJSON' and 'FromJSON' for 'MonoidMap'.+--+-- These instances provide objects of type 'MonoidMap' __@k@__ __@v@__ with a+-- JSON encoding that is /identical/ to objects of type 'Map' __@k@__ __@v@__,+-- which are serialised as either JSON /objects/ or /arrays/ depending on the+-- key type __@k@__.++-- $_examples+-- #_examples#+--+-- === Encoding as JSON objects+--+-- @+-- >>> 'encode' '$' 'MonoidMap'.'fromList' [("abc", 'Sum' 1), ("def", 'Sum' 2)]+--+-- "{\\"abc\\":1,\\"def\\":2}"+-- @+--+-- === Encoding as JSON arrays+--+-- @+-- >>> 'encode' '$' 'MonoidMap'.'fromList' [((1,2), 'Sum' 3), ((2,3), 'Sum' 5)]+--+-- "[[[1,2],3],[[2,3],5]]"+-- @++-- $_laws+-- #_laws#+--+-- === Encoding to JSON+--+-- The 'ToJSON' instance satisfies the following laws:+--+-- @+-- 'toEncoding' '==' 'toEncoding' '.' 'MonoidMap'.'toMap'+-- 'toJSON'     '==' 'toJSON'     '.' 'MonoidMap'.'toMap'+-- @+--+-- === Decoding from JSON+--+-- The 'FromJSON' instance satisfies the following law:+--+-- @+-- 'parseJSON' '==' 'fmap' ('fmap' 'MonoidMap'.'fromMap') 'parseJSON'+-- @+--+-- Mappings from keys to values that decode to 'mempty' are __not__ included in+-- decoded 'MonoidMap' objects.++_importsRequiredForDocumentation :: ()+_importsRequiredForDocumentation = ()+  where+    _encode = encode ()++    _fromList :: (Ord k, MonoidNull v) => [(k, v)] -> MonoidMap k v+    _fromList = fromList++    _fromMap :: (Ord k, MonoidNull v) => Map k v -> MonoidMap k v+    _fromMap = fromMap++    _toMap :: (Ord k, MonoidNull v) => MonoidMap k v -> Map k v+    _toMap = toMap++    _Sum :: Sum ()+    _Sum = undefined++instance+    ( ToJSONKey k+    , ToJSON v+    )+    => ToJSON (MonoidMap k v)+  where+    toEncoding = toEncoding . toMap+    toJSON = toJSON . toMap++instance+    ( FromJSONKey k+    , Ord k+    , FromJSON v+    , MonoidNull v+    )+    => FromJSON (MonoidMap k v)+  where+    parseJSON = fmap (fmap fromMap) parseJSON
+ monoidmap-aeson.cabal view
@@ -0,0 +1,113 @@+cabal-version:  3.0+name:           monoidmap-aeson+version:        0.0.0.0+bug-reports:    https://github.com/jonathanknowles/monoidmap-aeson/issues+license:        Apache-2.0+license-file:   LICENSE+author:         Jonathan Knowles+maintainer:     mail@jonathanknowles.net+copyright:      2022–2025 Jonathan Knowles+category:       Data Structures+synopsis:       JSON support for monoidmap.+description:    JSON support for the monoidmap package, compatible with aeson.++extra-doc-files:+    CHANGELOG.md+    README.md++common dependency-aeson+    build-depends:aeson                         >= 2.2.3.0    && < 2.3+common dependency-base+    build-depends:base                          >= 4.14.3.0   && < 4.22+common dependency-containers+    build-depends:containers                    >= 0.6.5.1    && < 0.8+common dependency-hspec+    build-depends:hspec                         >= 2.10.9     && < 2.12+common dependency-hspec-golden-aeson+    build-depends:hspec-golden-aeson            >= 0.9.0.0    && < 0.10+common dependency-monoid-subclasses+    build-depends:monoid-subclasses             >= 1.2.3      && < 1.3+common dependency-monoidmap+    build-depends:monoidmap                     >= 0.0.3.0    && < 0.1+common dependency-QuickCheck+    build-depends:QuickCheck                    >= 2.14.2     && < 2.16+common dependency-quickcheck-classes+    build-depends:quickcheck-classes            >= 0.6.5.0    && < 0.7+common dependency-quickcheck-quid+    build-depends:quickcheck-quid               >= 0.0.1.7    && < 0.1+common dependency-text+    build-depends:text                          >= 1.2.4.1    && < 2.2++common extensions+    default-extensions:+        BangPatterns+        ConstraintKinds+        DerivingStrategies+        DerivingVia+        FlexibleContexts+        FlexibleInstances+        GeneralizedNewtypeDeriving+        LambdaCase+        MultiParamTypeClasses+        NoImplicitPrelude+        NumericUnderscores+        ScopedTypeVariables+        TupleSections+        TypeApplications+        TypeFamilies+        TypeOperators+        ViewPatterns++source-repository head+    type: git+    location: https://github.com/jonathanknowles/monoidmap-aeson++library+    import:+      , dependency-aeson+      , dependency-base+      , dependency-containers+      , dependency-monoid-subclasses+      , dependency-monoidmap+      , extensions+    hs-source-dirs:+        components/monoidmap-aeson+    exposed-modules:+        Data.MonoidMap.JSON+    default-language:+        Haskell2010++test-suite monoidmap-aeson-test+    import:+      , dependency-aeson+      , dependency-base+      , dependency-containers+      , dependency-hspec+      , dependency-hspec-golden-aeson+      , dependency-monoid-subclasses+      , dependency-monoidmap+      , dependency-QuickCheck+      , dependency-quickcheck-classes+      , dependency-quickcheck-quid+      , dependency-text+      , extensions+    build-depends:+      , monoidmap-aeson+    ghc-options:+        -threaded -with-rtsopts=-N+    main-is:+        Spec.hs+    hs-source-dirs:+        components/monoidmap-aeson-test+    other-modules:+        SpecHook+        Data.MonoidMap.JSONSpec+        Test.Common+        Test.QuickCheck.Classes.Hspec+        Test.Key+    type:+        exitcode-stdio-1.0+    default-language:+        Haskell2010+    build-tool-depends:+        hspec-discover:hspec-discover ==2.*