diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 882a341..42f6430 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,15 +10,15 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - ghc: ["8.6.5", "8.8.4", "8.10.7", "9.0.2", "9.2.8", "9.4.8", "9.6.4", "9.8.1", "9.10.1"] + ghc: ["8.10.7", "9.0.2", "9.2.8", "9.4.8", "9.6.4", "9.8.1", "9.10.1"] cabal: ["3.12.1.0"] - os: [ubuntu-latest, macOS-latest] + os: [ubuntu-latest, macos-latest] fail-fast: false name: build and test (cabal) steps: - uses: actions/checkout@v2 - name: Run Haskell - uses: haskell/actions/setup@v1 + uses: haskell-actions/setup@v2 with: ghc-version: ${{ matrix.ghc }} cabal-version: ${{ matrix.cabal }} @@ -30,13 +30,13 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macOS-latest] + os: [ubuntu-latest, macos-latest] fail-fast: false steps: - uses: actions/checkout@v2 - - uses: haskell/actions/setup@v1 + - uses: haskell-actions/setup@v2 with: - ghc-version: "9.2.8" + ghc-version: "9.12.4" enable-stack: true stack-version: "latest" - run: | diff --git a/src/Data/HashMap/Strict/InsOrd/Compat.hs b/src/Data/HashMap/Strict/InsOrd/Compat.hs new file mode 100644 index 0000000..862e065 --- /dev/null +++ b/src/Data/HashMap/Strict/InsOrd/Compat.hs @@ -0,0 +1,442 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE DeriveTraversable #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE MultiParamTypeClasses #-} +-- | +-- Module: Data.HashMap.Strict.InsOrd.Compat +-- Maintainer: Nickolay Kudasov +-- Stability: experimental +-- +-- Compatibility wrapper around @insert-ordered-containers@ to mitigate the +-- breaking changes introduced in @insert-ordered-containers-0.3.0@: +-- . +-- +-- That change fixed 'Eq' and Aeson instances in the upstream package, but it is +-- a behavioral break for @swagger2@ where we need stable Swagger Schema +-- generation and JSON object-like encoding. +-- +-- This module keeps the old @swagger2@ expectations: +-- +-- * 'InsOrdHashMap' values are encoded as JSON objects (not arrays of key/value +-- tuples), so field names remain first-class object keys. +-- * Equality intentionally ignores insertion order (compares as plain hash +-- maps), which matches how many tests currently assert JSON equality. +-- +-- Simple encoding examples: +-- +-- >>> import Data.Aeson (encode, eitherDecode) +-- >>> import qualified Data.ByteString.Lazy.Char8 as BSL8 +-- >>> import qualified Data.HashMap.Strict as HM +-- >>> import qualified Data.HashMap.Strict.InsOrd.Compat as IOHM +-- >>> let decodeIOHM s = either error id (eitherDecode (BSL8.pack s) :: Either String (IOHM.InsOrdHashMap String Int)) +-- +-- A regular hash map has no insertion order guarantee: +-- +-- >>> encode (HM.fromList [("a", 1 :: Int), ("b", 2)]) +-- "{\"a\":1,\"b\":2}" +-- >>> encode (HM.fromList [("b", 1 :: Int), ("a", 2)]) +-- "{\"a\":2,\"b\":1}" +-- +-- Our compat 'InsOrdHashMap' encodes to a JSON object as well, but preserves insertion order: +-- +-- >>> encode (IOHM.fromList [("a", 1 :: Int), ("b", 2)]) +-- "{\"a\":1,\"b\":2}" +-- >>> encode (IOHM.fromList [("b", 1 :: Int), ("a", 2)]) +-- "{\"b\":1,\"a\":2}" +-- +-- Round-tripping through decode/encode demonstrates the caveat: encoding +-- preserves insertion order, but decoded object key order is not guaranteed. +-- +-- >>> encode (decodeIOHM "{\"a\":1,\"b\":2}") +-- "{\"a\":1,\"b\":2}" +-- >>> encode (decodeIOHM "{\"b\":1,\"a\":2}") +-- "{\"a\":2,\"b\":1}" +-- +-- This object encoding is what @swagger2@ wants for generated Swagger +-- definitions/properties because it keeps emitted schemas easy to consume and +-- stable in practice. +-- +-- Important caveat: decoding cannot be fully stable with respect to insertion +-- order due to @aeson@ limitations. In particular, object parsing goes through +-- structures that do not preserve all ordering guarantees end-to-end. We accept +-- this trade-off for now because the primary requirement is deterministic +-- /encoding/ for generated Swagger Schema artifacts. +-- +-- Many tests rely on @aesonQQ@-style JSON equality, where semantic object +-- equality matters more than insertion order. Comparing via plain hash maps +-- makes those tests robust under benign key-order variation. This is a weaker +-- notion of equality and hopefully will be revisited later. +module Data.HashMap.Strict.InsOrd.Compat ( + InsOrdHashMap, + -- * Construction + empty, + singleton, + -- * Basic interface + null, + size, + member, + lookup, + lookupDefault, + insert, + insertWith, + delete, + adjust, + update, + alter, + -- * Combine + union, + unionWith, + unionWithKey, + unions, + -- * Transformations + map, + mapKeys, + traverseKeys, + mapWithKey, + traverseWithKey, + -- ** Unordered + unorderedTraverse, + unorderedTraverseWithKey, + -- * Difference and intersection + difference, + intersection, + intersectionWith, + intersectionWithKey, + -- * Folds + foldl', + foldlWithKey', + foldr, + foldrWithKey, + foldMapWithKey, + -- ** Unordered + unorderedFoldMap, + unorderedFoldMapWithKey, + -- * Filter + filter, + filterWithKey, + mapMaybe, + mapMaybeWithKey, + -- * Conversions + keys, + elems, + toList, + toRevList, + fromList, + toHashMap, + fromHashMap, + -- * Lenses + hashMap, + unorderedTraversal, + -- * Debugging + valid, + ) where + +#if !MIN_VERSION_insert_ordered_containers(0,3,0) +import Data.HashMap.Strict.InsOrd +#else +import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap + +import Prelude hiding (null, size, member, lookup, lookupDefault, map, foldl', filter) +import qualified Prelude + +import qualified Data.Aeson as A +import qualified Data.Aeson.Encoding as E +import Data.HashMap.Strict (HashMap) +import qualified Data.HashMap.Strict as HashMap + +import qualified GHC.Exts as Exts + +import Data.Data (Data) +import Data.Foldable (Foldable (foldMap)) +import Data.Hashable (Hashable (..)) + +import qualified Control.Lens as Lens +import Control.Lens + (At (..), Index, Iso, IxValue, Ixed (..), Traversal, _1, _2, iso, (<&>)) + +import qualified Optics.Core as Optics + +newtype InsOrdHashMap k v = InsOrdHashMap { unCompatInsOrdHashMap :: InsOrdHashMap.InsOrdHashMap k v } + deriving (Show, Read, Data, Functor, Foldable, Traversable, Semigroup, Monoid) + +instance (Eq k, Eq v) => Eq (InsOrdHashMap k v) where + a == b = toHashMap a == toHashMap b + +instance (Eq k, Hashable k) => Exts.IsList (InsOrdHashMap k v) where + type Item (InsOrdHashMap k v) = Exts.Item (InsOrdHashMap.InsOrdHashMap k v) + fromList = InsOrdHashMap . InsOrdHashMap.fromList + toList = InsOrdHashMap.toList . unCompatInsOrdHashMap + +------------------------------------------------------------------------------- +-- Aeson +------------------------------------------------------------------------------- + +instance (A.ToJSONKey k) => A.ToJSON1 (InsOrdHashMap k) where + liftToJSON _ t _ = case A.toJSONKey :: A.ToJSONKeyFunction k of + A.ToJSONKeyText f _ -> A.object . fmap (\(k, v) -> (f k, t v)) . toList + A.ToJSONKeyValue f _ -> A.toJSON . fmap (\(k,v) -> A.toJSON (f k, t v)) . toList + + liftToEncoding o t _ = case A.toJSONKey :: A.ToJSONKeyFunction k of + A.ToJSONKeyText _ f -> E.dict f t foldrWithKey + A.ToJSONKeyValue _ f -> E.list (A.liftToEncoding2 (const False) f (E.list f) o t (E.list t)) . toList + +instance (A.ToJSONKey k, A.ToJSON v) => A.ToJSON (InsOrdHashMap k v) where + toJSON = A.toJSON1 + toEncoding = A.toEncoding1 + +------------------------------------------------------------------------------- + +instance (Eq k, Hashable k, A.FromJSONKey k) => A.FromJSON1 (InsOrdHashMap k) where + liftParseJSON o p pl v = fromList . HashMap.toList <$> A.liftParseJSON o p pl v + +instance (Eq k, Hashable k, A.FromJSONKey k, A.FromJSON v) => A.FromJSON (InsOrdHashMap k v) where + parseJSON = A.parseJSON1 + +------------------------------------------------------------------------------- +-- indexed-traversals +------------------------------------------------------------------------------- + +instance (Eq k, Hashable k) => Optics.FunctorWithIndex k (InsOrdHashMap k) where + imap = mapWithKey +instance (Eq k, Hashable k) => Optics.FoldableWithIndex k (InsOrdHashMap k) where + ifoldMap = foldMapWithKey + ifoldr = foldrWithKey +instance (Eq k, Hashable k) => Optics.TraversableWithIndex k (InsOrdHashMap k) where + itraverse = traverseWithKey + +------------------------------------------------------------------------------- +-- Lens +------------------------------------------------------------------------------- + +type instance Index (InsOrdHashMap k v) = k +type instance IxValue (InsOrdHashMap k v) = v + +instance (Eq k, Hashable k) => Ixed (InsOrdHashMap k v) where + ix k f m = ixImpl k pure f m + {-# INLINABLE ix #-} + +ixImpl + :: (Eq k, Hashable k, Functor f) + => k + -> (InsOrdHashMap k v -> f (InsOrdHashMap k v)) + -> (v -> f v) + -> InsOrdHashMap k v + -> f (InsOrdHashMap k v) +ixImpl k point f m = case lookup k m of + Just v -> f v <&> \v' -> insert k v' m + Nothing -> point m +{-# INLINE ixImpl #-} + +instance (Eq k, Hashable k) => At (InsOrdHashMap k a) where + at k f m = f mv <&> \r -> case r of + Nothing -> maybe m (const (delete k m)) mv + Just v' -> insert k v' m + where mv = lookup k m + {-# INLINABLE at #-} + +------------------------------------------------------------------------------- +-- Optics +------------------------------------------------------------------------------- + +type instance Optics.Index (InsOrdHashMap k v) = k +type instance Optics.IxValue (InsOrdHashMap k v) = v + +instance (Eq k, Hashable k) => Optics.Ixed (InsOrdHashMap k v) where + ix k = Optics.atraversalVL $ \point f m -> ixImpl k point f m + {-# INLINE ix #-} + +instance (Eq k, Hashable k) => Optics.At (InsOrdHashMap k a) where + at k = Optics.lensVL $ \f m -> Lens.at k f m + {-# INLINE at #-} + +------------------------------------------------------------------------------- + +-- | This is a slight lie, as roundtrip doesn't preserve ordering. +hashMap :: Iso (InsOrdHashMap k a) (InsOrdHashMap k b) (HashMap k a) (HashMap k b) +hashMap = iso toHashMap fromHashMap + +unorderedTraversal :: Traversal (InsOrdHashMap k a) (InsOrdHashMap k b) a b +unorderedTraversal = hashMap . traverse + +------------------------------------------------------------------------------- +-- * Construction +------------------------------------------------------------------------------- + +empty :: InsOrdHashMap k v +empty = InsOrdHashMap InsOrdHashMap.empty + +singleton :: Hashable k => k -> v -> InsOrdHashMap k v +singleton k v = InsOrdHashMap (InsOrdHashMap.singleton k v) + +------------------------------------------------------------------------------- +-- * Basic interface +------------------------------------------------------------------------------- + +null :: InsOrdHashMap k v -> Bool +null = InsOrdHashMap.null . unCompatInsOrdHashMap + +size :: InsOrdHashMap k v -> Int +size = InsOrdHashMap.size . unCompatInsOrdHashMap + +insert :: Hashable k => k -> v -> InsOrdHashMap k v -> InsOrdHashMap k v +insert k v = InsOrdHashMap . InsOrdHashMap.insert k v . unCompatInsOrdHashMap + +insertWith :: Hashable k => (v -> v -> v) -> k -> v -> InsOrdHashMap k v -> InsOrdHashMap k v +insertWith f k v = InsOrdHashMap . InsOrdHashMap.insertWith f k v . unCompatInsOrdHashMap + +delete :: Hashable k => k -> InsOrdHashMap k v -> InsOrdHashMap k v +delete k = InsOrdHashMap . InsOrdHashMap.delete k . unCompatInsOrdHashMap + +adjust :: Hashable k => (v -> v) -> k -> InsOrdHashMap k v -> InsOrdHashMap k v +adjust f k = InsOrdHashMap . InsOrdHashMap.adjust f k . unCompatInsOrdHashMap + +update :: Hashable k => (v -> Maybe v) -> k -> InsOrdHashMap k v -> InsOrdHashMap k v +update f k = InsOrdHashMap . InsOrdHashMap.update f k . unCompatInsOrdHashMap + +alter :: Hashable k => (Maybe v -> Maybe v) -> k -> InsOrdHashMap k v -> InsOrdHashMap k v +alter f k = InsOrdHashMap . InsOrdHashMap.alter f k . unCompatInsOrdHashMap + +member :: Hashable k => k -> InsOrdHashMap k v -> Bool +member k = InsOrdHashMap.member k . unCompatInsOrdHashMap + +lookup :: Hashable k => k -> InsOrdHashMap k v -> Maybe v +lookup k = InsOrdHashMap.lookup k . unCompatInsOrdHashMap + +lookupDefault :: Hashable k => v -> k -> InsOrdHashMap k v -> v +lookupDefault k def = InsOrdHashMap.lookupDefault k def . unCompatInsOrdHashMap + +-- * Combine + +union :: Hashable k => InsOrdHashMap k v -> InsOrdHashMap k v -> InsOrdHashMap k v +union m1 m2 = InsOrdHashMap (InsOrdHashMap.union (unCompatInsOrdHashMap m1) (unCompatInsOrdHashMap m2)) + +unionWith :: Hashable k => (v -> v -> v) -> InsOrdHashMap k v -> InsOrdHashMap k v -> InsOrdHashMap k v +unionWith f m1 m2 = InsOrdHashMap (InsOrdHashMap.unionWith f (unCompatInsOrdHashMap m1) (unCompatInsOrdHashMap m2)) + +unionWithKey :: Hashable k => (k -> v -> v -> v) -> InsOrdHashMap k v -> InsOrdHashMap k v -> InsOrdHashMap k v +unionWithKey f m1 m2 = InsOrdHashMap (InsOrdHashMap.unionWithKey f (unCompatInsOrdHashMap m1) (unCompatInsOrdHashMap m2)) + +unions :: Hashable k => [InsOrdHashMap k v] -> InsOrdHashMap k v +unions = InsOrdHashMap . InsOrdHashMap.unions . Prelude.map unCompatInsOrdHashMap + +------------------------------------------------------------------------------- +-- * Transformations +------------------------------------------------------------------------------- + +map :: (v -> v) -> InsOrdHashMap k v -> InsOrdHashMap k v +map f = InsOrdHashMap . InsOrdHashMap.map f . unCompatInsOrdHashMap + +mapKeys :: Hashable k => (k -> k) -> InsOrdHashMap k v -> InsOrdHashMap k v +mapKeys f = InsOrdHashMap . InsOrdHashMap.mapKeys f . unCompatInsOrdHashMap + +traverseKeys :: (Applicative f, Hashable k) => (k -> f k) -> InsOrdHashMap k v -> f (InsOrdHashMap k v) +traverseKeys f = fmap InsOrdHashMap . InsOrdHashMap.traverseKeys f . unCompatInsOrdHashMap + +mapWithKey :: (k -> v1 -> v2) -> InsOrdHashMap k v1 -> InsOrdHashMap k v2 +mapWithKey f = InsOrdHashMap . InsOrdHashMap.mapWithKey f . unCompatInsOrdHashMap + +traverseWithKey :: (Applicative f, Hashable k) => (k -> v1 -> f v2) -> InsOrdHashMap k v1 -> f (InsOrdHashMap k v2) +traverseWithKey f = fmap InsOrdHashMap . InsOrdHashMap.traverseWithKey f . unCompatInsOrdHashMap + +-- ** Unordered + +unorderedTraverse :: (Applicative f, Hashable k) => (v -> f v) -> InsOrdHashMap k v -> f (InsOrdHashMap k v) +unorderedTraverse f = fmap InsOrdHashMap . InsOrdHashMap.unorderedTraverse f . unCompatInsOrdHashMap + +unorderedTraverseWithKey :: (Applicative f, Hashable k) => (k -> v -> f v) -> InsOrdHashMap k v -> f (InsOrdHashMap k v) +unorderedTraverseWithKey f = fmap InsOrdHashMap . InsOrdHashMap.unorderedTraverseWithKey f . unCompatInsOrdHashMap + +------------------------------------------------------------------------------- +-- * Difference and intersection +------------------------------------------------------------------------------- + +difference :: Hashable k => InsOrdHashMap k v -> InsOrdHashMap k v -> InsOrdHashMap k v +difference m1 m2 = InsOrdHashMap (InsOrdHashMap.difference (unCompatInsOrdHashMap m1) (unCompatInsOrdHashMap m2)) + +intersection :: Hashable k => InsOrdHashMap k v -> InsOrdHashMap k v -> InsOrdHashMap k v +intersection m1 m2 = InsOrdHashMap (InsOrdHashMap.intersection (unCompatInsOrdHashMap m1) (unCompatInsOrdHashMap m2)) + +intersectionWith :: Hashable k => (v -> v -> v) -> InsOrdHashMap k v -> InsOrdHashMap k v -> InsOrdHashMap k v +intersectionWith f m1 m2 = InsOrdHashMap (InsOrdHashMap.intersectionWith f (unCompatInsOrdHashMap m1) (unCompatInsOrdHashMap m2)) + +intersectionWithKey :: Hashable k => (k -> v -> v -> v) -> InsOrdHashMap k v -> InsOrdHashMap k v -> InsOrdHashMap k v +intersectionWithKey f m1 m2 = InsOrdHashMap (InsOrdHashMap.intersectionWithKey f (unCompatInsOrdHashMap m1) (unCompatInsOrdHashMap m2)) + +------------------------------------------------------------------------------- +-- * Folds +------------------------------------------------------------------------------- + +foldl' :: (a -> v -> a) -> a -> InsOrdHashMap k v -> a +foldl' f z = InsOrdHashMap.foldl' f z . unCompatInsOrdHashMap + +foldlWithKey' :: (a -> k -> v -> a) -> a -> InsOrdHashMap k v -> a +foldlWithKey' f z = InsOrdHashMap.foldlWithKey' f z . unCompatInsOrdHashMap + +foldMapWithKey :: Monoid m => (k -> v -> m) -> InsOrdHashMap k v -> m +foldMapWithKey f = InsOrdHashMap.foldMapWithKey f . unCompatInsOrdHashMap + +foldrWithKey :: (k -> v -> a -> a) -> a -> InsOrdHashMap k v -> a +foldrWithKey f z = InsOrdHashMap.foldrWithKey f z . unCompatInsOrdHashMap + +-- ** Unordered + +unorderedFoldMap :: Monoid m => (v -> m) -> InsOrdHashMap k v -> m +unorderedFoldMap f = InsOrdHashMap.unorderedFoldMap f . unCompatInsOrdHashMap + +unorderedFoldMapWithKey :: Monoid m => (k -> v -> m) -> InsOrdHashMap k v -> m +unorderedFoldMapWithKey f = InsOrdHashMap.unorderedFoldMapWithKey f . unCompatInsOrdHashMap + +------------------------------------------------------------------------------- +-- * Filter +------------------------------------------------------------------------------- + +filter :: (v -> Bool) -> InsOrdHashMap k v -> InsOrdHashMap k v +filter f = InsOrdHashMap . InsOrdHashMap.filter f . unCompatInsOrdHashMap + +filterWithKey :: (k -> v -> Bool) -> InsOrdHashMap k v -> InsOrdHashMap k v +filterWithKey f = InsOrdHashMap . InsOrdHashMap.filterWithKey f . unCompatInsOrdHashMap + +mapMaybe :: (v -> Maybe v) -> InsOrdHashMap k v -> InsOrdHashMap k v +mapMaybe f = InsOrdHashMap . InsOrdHashMap.mapMaybe f . unCompatInsOrdHashMap + +mapMaybeWithKey :: (k -> v -> Maybe v) -> InsOrdHashMap k v -> InsOrdHashMap k v +mapMaybeWithKey f = InsOrdHashMap . InsOrdHashMap.mapMaybeWithKey f . unCompatInsOrdHashMap + +------------------------------------------------------------------------------- +-- * Conversions +------------------------------------------------------------------------------- + +keys :: InsOrdHashMap k v -> [k] +keys = InsOrdHashMap.keys . unCompatInsOrdHashMap + +elems :: InsOrdHashMap k v -> [v] +elems = InsOrdHashMap.elems . unCompatInsOrdHashMap + +toRevList :: InsOrdHashMap k v -> [(k, v)] +toRevList = InsOrdHashMap.toRevList . unCompatInsOrdHashMap + +fromList :: Hashable k => [(k, v)] -> InsOrdHashMap k v +fromList = InsOrdHashMap . InsOrdHashMap.fromList + +toList :: InsOrdHashMap k v -> [(k, v)] +toList = InsOrdHashMap.toList . unCompatInsOrdHashMap + +toHashMap :: InsOrdHashMap k v -> HashMap k v +toHashMap = InsOrdHashMap.toHashMap . unCompatInsOrdHashMap + +fromHashMap :: HashMap k v -> InsOrdHashMap k v +fromHashMap = InsOrdHashMap . InsOrdHashMap.fromHashMap + +------------------------------------------------------------------------------- +-- * Debugging +------------------------------------------------------------------------------- + +valid :: (Eq k, Hashable k) => InsOrdHashMap k v -> Bool +valid = InsOrdHashMap.valid . unCompatInsOrdHashMap + +#endif \ No newline at end of file diff --git a/src/Data/Swagger.hs b/src/Data/Swagger.hs index 9e1d29b..8e81eaa 100644 --- a/src/Data/Swagger.hs +++ b/src/Data/Swagger.hs @@ -124,7 +124,7 @@ import Data.Swagger.Internal -- $setup -- >>> import Control.Lens -- >>> import Data.Aeson --- >>> import qualified Data.HashMap.Strict.InsOrd as IOHM +-- >>> import qualified Data.HashMap.Strict.InsOrd.Compat as IOHM -- >>> import Data.Monoid -- >>> import Data.Proxy -- >>> import GHC.Generics diff --git a/src/Data/Swagger/Internal.hs b/src/Data/Swagger/Internal.hs index 10bd06b..90119d9 100644 --- a/src/Data/Swagger/Internal.hs +++ b/src/Data/Swagger/Internal.hs @@ -44,8 +44,8 @@ import Network.Socket (HostName, PortNumber) import Network.HTTP.Media (MediaType) import Text.Read (readMaybe) -import Data.HashMap.Strict.InsOrd (InsOrdHashMap) -import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap +import Data.HashMap.Strict.InsOrd.Compat (InsOrdHashMap) +import qualified Data.HashMap.Strict.InsOrd.Compat as InsOrdHashMap import qualified Data.Aeson.Key as K import qualified Data.Aeson.KeyMap as KM diff --git a/src/Data/Swagger/Internal/AesonUtils.hs b/src/Data/Swagger/Internal/AesonUtils.hs index 196ce73..6d45a65 100644 --- a/src/Data/Swagger/Internal/AesonUtils.hs +++ b/src/Data/Swagger/Internal/AesonUtils.hs @@ -45,7 +45,7 @@ import Generics.SOP import qualified Data.Text as T import qualified Data.HashMap.Strict as HM import qualified Data.Set as Set -import qualified Data.HashMap.Strict.InsOrd as InsOrd +import qualified Data.HashMap.Strict.InsOrd.Compat as InsOrd import qualified Data.HashSet.InsOrd as InsOrdHS ------------------------------------------------------------------------------- diff --git a/src/Data/Swagger/Internal/Schema.hs b/src/Data/Swagger/Internal/Schema.hs index 9aa7b18..23a3ad1 100644 --- a/src/Data/Swagger/Internal/Schema.hs +++ b/src/Data/Swagger/Internal/Schema.hs @@ -36,7 +36,7 @@ import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap import "unordered-containers" Data.HashSet (HashSet) import qualified "unordered-containers" Data.HashSet as HashSet -import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap +import qualified Data.HashMap.Strict.InsOrd.Compat as InsOrdHashMap import Data.Int import Data.IntSet (IntSet) import Data.IntMap (IntMap) diff --git a/src/Data/Swagger/Internal/Schema/Validation.hs b/src/Data/Swagger/Internal/Schema/Validation.hs index ea750e2..c68f67b 100644 --- a/src/Data/Swagger/Internal/Schema/Validation.hs +++ b/src/Data/Swagger/Internal/Schema/Validation.hs @@ -35,7 +35,7 @@ import Data.Foldable (for_, sequenceA_, traverse_) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap -import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap +import qualified Data.HashMap.Strict.InsOrd.Compat as InsOrdHashMap import qualified "unordered-containers" Data.HashSet as HashSet import Data.Proxy import Data.Scientific (Scientific, isInteger) diff --git a/src/Data/Swagger/Internal/Utils.hs b/src/Data/Swagger/Internal/Utils.hs index ca91d7b..2b106bf 100644 --- a/src/Data/Swagger/Internal/Utils.hs +++ b/src/Data/Swagger/Internal/Utils.hs @@ -18,8 +18,8 @@ import Data.Data import Data.Hashable (Hashable) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap -import Data.HashMap.Strict.InsOrd (InsOrdHashMap) -import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap +import Data.HashMap.Strict.InsOrd.Compat (InsOrdHashMap) +import qualified Data.HashMap.Strict.InsOrd.Compat as InsOrdHashMap import Data.Map (Map) import Data.Set (Set) import Data.Text (Text) diff --git a/src/Data/Swagger/Operation.hs b/src/Data/Swagger/Operation.hs index 3724bbf..60da4b7 100644 --- a/src/Data/Swagger/Operation.hs +++ b/src/Data/Swagger/Operation.hs @@ -51,13 +51,13 @@ import Data.Swagger.Internal import Data.Swagger.Lens import Data.Swagger.Schema -import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap -import Data.HashMap.Strict.InsOrd (InsOrdHashMap) +import qualified Data.HashMap.Strict.InsOrd.Compat as InsOrdHashMap +import Data.HashMap.Strict.InsOrd.Compat (InsOrdHashMap) import qualified Data.HashSet.InsOrd as InsOrdHS -- $setup -- >>> import Data.Aeson --- >>> import qualified Data.HashMap.Strict.InsOrd as IOHM +-- >>> import qualified Data.HashMap.Strict.InsOrd.Compat as IOHM -- >>> import Data.Proxy -- >>> import Data.Time diff --git a/src/Data/Swagger/Optics.hs b/src/Data/Swagger/Optics.hs index 211df96..03744e7 100644 --- a/src/Data/Swagger/Optics.hs +++ b/src/Data/Swagger/Optics.hs @@ -15,7 +15,7 @@ -- library. -- -- >>> import Data.Aeson --- >>> import qualified Data.HashMap.Strict.InsOrd as IOHM +-- >>> import qualified Data.HashMap.Strict.InsOrd.Compat as IOHM -- >>> import Optics.Core -- >>> :set -XOverloadedLabels -- diff --git a/src/Data/Swagger/Schema/Generator.hs b/src/Data/Swagger/Schema/Generator.hs index 32f5480..fb4ffbe 100644 --- a/src/Data/Swagger/Schema/Generator.hs +++ b/src/Data/Swagger/Schema/Generator.hs @@ -12,7 +12,7 @@ import Control.Monad (filterM) import Data.Aeson import qualified Data.Aeson.KeyMap as KM import Data.Aeson.Types -import qualified Data.HashMap.Strict.InsOrd as M +import qualified Data.HashMap.Strict.InsOrd.Compat as M import Data.Maybe import Data.Proxy import Data.Scientific diff --git a/stack.yaml b/stack.yaml index 9a90f32..f73044c 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: lts-19.11 +resolver: nightly-2026-04-19 packages: - "." diff --git a/swagger2.cabal b/swagger2.cabal index b47ba84..ab417dc 100644 --- a/swagger2.cabal +++ b/swagger2.cabal @@ -41,6 +41,7 @@ custom-setup library hs-source-dirs: src exposed-modules: + Data.HashMap.Strict.InsOrd.Compat Data.Swagger Data.Swagger.Declare Data.Swagger.Lens @@ -84,7 +85,7 @@ library , generics-sop >=0.5.1.0 && <0.6 , hashable >=1.2.7.0 && <1.6 , http-media >=0.8.0.0 && <0.9 - , insert-ordered-containers >=0.2.3 && <0.3 + , insert-ordered-containers >=0.2.3 && <0.4 , lens >=4.16.1 && <5.4 , network >=2.6.3.5 && <3.3 , optics-core >=0.2 && <0.5 @@ -93,7 +94,7 @@ library , unordered-containers >=0.2.9.0 && <0.3 , uuid-types >=1.0.3 && <1.1 , vector >=0.12.0.1 && <0.14 - , QuickCheck >=2.10.1 && <2.16 + , QuickCheck >=2.10.1 && <2.17 default-language: Haskell2010 @@ -131,7 +132,7 @@ test-suite spec -- https://github.com/haskell/cabal/issues/3708 build-tool-depends: - hspec-discover:hspec-discover >=2.5.5 && <2.9 + hspec-discover:hspec-discover >=2.5.5 && <2.12 other-modules: SpecCommon diff --git a/test/Data/Swagger/SchemaSpec.hs b/test/Data/Swagger/SchemaSpec.hs index 9750d1c..2e37a3c 100644 --- a/test/Data/Swagger/SchemaSpec.hs +++ b/test/Data/Swagger/SchemaSpec.hs @@ -9,7 +9,7 @@ import Prelude.Compat import Control.Lens ((^.)) import Data.Aeson (Value) -import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap +import qualified Data.HashMap.Strict.InsOrd.Compat as InsOrdHashMap import Data.Proxy import Data.Set (Set) import qualified Data.Text as Text diff --git a/test/Data/SwaggerSpec.hs b/test/Data/SwaggerSpec.hs index b0d25e9..4a7e99d 100644 --- a/test/Data/SwaggerSpec.hs +++ b/test/Data/SwaggerSpec.hs @@ -12,7 +12,7 @@ import Control.Lens import Data.Aeson import Data.Aeson.QQ.Simple import Data.HashMap.Strict (HashMap) -import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap +import qualified Data.HashMap.Strict.InsOrd.Compat as InsOrdHashMap import qualified Data.HashSet.InsOrd as InsOrdHS import Data.Text (Text)