summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2021-02-14 14:46:06 +0100
committerEugen Wissner <belka@caraus.de>2021-02-14 14:46:06 +0100
commit90d36f66b9b5a4cae2fb9f15826856e6f4649bf4 (patch)
tree1ab1dd1a91ee706115d5232b1160227efd0762fb
parentc1a1b47aeae5846661a83a43c05e4b4a1e24266a (diff)
downloadgraphql-90d36f66b9b5a4cae2fb9f15826856e6f4649bf4.tar.gz
Combine value inserted into the OrderedMap
-rw-r--r--src/Language/GraphQL/Execute/OrderedMap.hs55
-rw-r--r--tests/Language/GraphQL/Execute/OrderedMapSpec.hs13
2 files changed, 52 insertions, 16 deletions
diff --git a/src/Language/GraphQL/Execute/OrderedMap.hs b/src/Language/GraphQL/Execute/OrderedMap.hs
index ae50dd3..566a551 100644
--- a/src/Language/GraphQL/Execute/OrderedMap.hs
+++ b/src/Language/GraphQL/Execute/OrderedMap.hs
@@ -3,16 +3,25 @@
obtain one at https://mozilla.org/MPL/2.0/. -}
{-# LANGUAGE ExplicitForAll #-}
+
+-- | This module contains a map data structure, that preserves insertion order.
module Language.GraphQL.Execute.OrderedMap
( OrderedMap
+ , elems
+ , insert
+ , keys
+ , lookup
, singleton
+ , size
) where
+import qualified Data.Foldable as Foldable
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.Text (Text)
import Data.Vector (Vector)
import qualified Data.Vector as Vector
+import Prelude hiding (lookup)
data OrderedMap v = OrderedMap (Vector Text) (HashMap Text v)
@@ -27,16 +36,10 @@ instance Show v => Show (OrderedMap v) where
showsPrec precedence map' = showParen (precedence > 10)
$ showString "fromList " . shows (toList map')
-instance Semigroup (OrderedMap v) where
- (<>) = foldrWithKey go
- where
- go key value accumulator@(OrderedMap vector hashMap)
- | Nothing <- HashMap.lookup key hashMap
- = OrderedMap (Vector.snoc vector key)
- $ HashMap.insert key value hashMap
- | otherwise = accumulator
+instance Semigroup v => Semigroup (OrderedMap v) where
+ (<>) = foldrWithKey insert
-instance Monoid (OrderedMap v) where
+instance Monoid v => Monoid (OrderedMap v) where
mempty = OrderedMap mempty mempty
-- * Construction
@@ -53,12 +56,38 @@ singleton key value = OrderedMap (Vector.singleton key)
foldrWithKey :: forall v a. (Text -> v -> a -> a) -> a -> OrderedMap v -> a
foldrWithKey f initial (OrderedMap vector hashMap) = foldr go initial vector
where
- go key accumulator = f key (hashMap HashMap.! key) accumulator
+ go key = f key (hashMap HashMap.! key)
-- * Lists
-- | Converts this map to the list of key-value pairs.
toList :: forall v. OrderedMap v -> [(Text, v)]
-toList = foldrWithKey f []
- where
- f key value accumulator = (key, value) : accumulator
+toList = foldrWithKey ((.) (:) . (,)) []
+
+-- | Returns a list with all keys in this map.
+keys :: forall v. OrderedMap v -> [Text]
+keys (OrderedMap vector _) = Foldable.toList vector
+
+-- | Returns a list with all elements in this map.
+elems :: forall v. OrderedMap v -> [v]
+elems = fmap snd . toList
+
+-- * Basic interface
+
+-- | Associates the specified value with the specified key in this map. If this
+-- map previously contained a mapping for the key, the existing and new values
+-- are combined.
+insert :: Semigroup v => Text -> v -> OrderedMap v -> OrderedMap v
+insert key value (OrderedMap vector hashMap)
+ | Just available <- HashMap.lookup key hashMap = OrderedMap vector
+ $ HashMap.insert key (available <> value) hashMap
+ | otherwise = OrderedMap (Vector.snoc vector key)
+ $ HashMap.insert key value hashMap
+
+-- | Gives the size of this map, i.e. number of elements in it.
+size :: forall v. OrderedMap v -> Int
+size (OrderedMap vector _) = Vector.length vector
+
+-- | Looks up a value in this map by key.
+lookup :: forall v. Text -> OrderedMap v -> Maybe v
+lookup key (OrderedMap _ hashMap) = HashMap.lookup key hashMap
diff --git a/tests/Language/GraphQL/Execute/OrderedMapSpec.hs b/tests/Language/GraphQL/Execute/OrderedMapSpec.hs
index 35d311c..8221b92 100644
--- a/tests/Language/GraphQL/Execute/OrderedMapSpec.hs
+++ b/tests/Language/GraphQL/Execute/OrderedMapSpec.hs
@@ -3,15 +3,22 @@
obtain one at https://mozilla.org/MPL/2.0/. -}
{-# LANGUAGE OverloadedStrings #-}
+
module Language.GraphQL.Execute.OrderedMapSpec
( spec
) where
import Language.GraphQL.Execute.OrderedMap (OrderedMap)
-import Test.Hspec (Spec, describe, it, shouldSatisfy)
+import qualified Language.GraphQL.Execute.OrderedMap as OrderedMap
+import Test.Hspec (Spec, describe, it, shouldBe, shouldSatisfy)
spec :: Spec
spec =
- describe "OrderedMap" $
+ describe "OrderedMap" $ do
it "creates an empty map" $
- (mempty :: OrderedMap Int) `shouldSatisfy` null
+ (mempty :: OrderedMap String) `shouldSatisfy` null
+
+ it "creates a singleton" $
+ let value :: String
+ value = "value"
+ in OrderedMap.size (OrderedMap.singleton "key" value) `shouldBe` 1