Combine value inserted into the OrderedMap
This commit is contained in:
parent
c1a1b47aea
commit
90d36f66b9
@ -3,16 +3,25 @@
|
|||||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||||
|
|
||||||
{-# LANGUAGE ExplicitForAll #-}
|
{-# LANGUAGE ExplicitForAll #-}
|
||||||
|
|
||||||
|
-- | This module contains a map data structure, that preserves insertion order.
|
||||||
module Language.GraphQL.Execute.OrderedMap
|
module Language.GraphQL.Execute.OrderedMap
|
||||||
( OrderedMap
|
( OrderedMap
|
||||||
|
, elems
|
||||||
|
, insert
|
||||||
|
, keys
|
||||||
|
, lookup
|
||||||
, singleton
|
, singleton
|
||||||
|
, size
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import qualified Data.Foldable as Foldable
|
||||||
import Data.HashMap.Strict (HashMap)
|
import Data.HashMap.Strict (HashMap)
|
||||||
import qualified Data.HashMap.Strict as HashMap
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Data.Vector (Vector)
|
import Data.Vector (Vector)
|
||||||
import qualified Data.Vector as Vector
|
import qualified Data.Vector as Vector
|
||||||
|
import Prelude hiding (lookup)
|
||||||
|
|
||||||
data OrderedMap v = OrderedMap (Vector Text) (HashMap Text v)
|
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)
|
showsPrec precedence map' = showParen (precedence > 10)
|
||||||
$ showString "fromList " . shows (toList map')
|
$ showString "fromList " . shows (toList map')
|
||||||
|
|
||||||
instance Semigroup (OrderedMap v) where
|
instance Semigroup v => Semigroup (OrderedMap v) where
|
||||||
(<>) = foldrWithKey go
|
(<>) = foldrWithKey insert
|
||||||
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 Monoid (OrderedMap v) where
|
instance Monoid v => Monoid (OrderedMap v) where
|
||||||
mempty = OrderedMap mempty mempty
|
mempty = OrderedMap mempty mempty
|
||||||
|
|
||||||
-- * Construction
|
-- * 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 :: forall v a. (Text -> v -> a -> a) -> a -> OrderedMap v -> a
|
||||||
foldrWithKey f initial (OrderedMap vector hashMap) = foldr go initial vector
|
foldrWithKey f initial (OrderedMap vector hashMap) = foldr go initial vector
|
||||||
where
|
where
|
||||||
go key accumulator = f key (hashMap HashMap.! key) accumulator
|
go key = f key (hashMap HashMap.! key)
|
||||||
|
|
||||||
-- * Lists
|
-- * Lists
|
||||||
|
|
||||||
-- | Converts this map to the list of key-value pairs.
|
-- | Converts this map to the list of key-value pairs.
|
||||||
toList :: forall v. OrderedMap v -> [(Text, v)]
|
toList :: forall v. OrderedMap v -> [(Text, v)]
|
||||||
toList = foldrWithKey f []
|
toList = foldrWithKey ((.) (:) . (,)) []
|
||||||
where
|
|
||||||
f key value accumulator = (key, value) : accumulator
|
-- | 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
|
||||||
|
@ -3,15 +3,22 @@
|
|||||||
obtain one at https://mozilla.org/MPL/2.0/. -}
|
obtain one at https://mozilla.org/MPL/2.0/. -}
|
||||||
|
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module Language.GraphQL.Execute.OrderedMapSpec
|
module Language.GraphQL.Execute.OrderedMapSpec
|
||||||
( spec
|
( spec
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Language.GraphQL.Execute.OrderedMap (OrderedMap)
|
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 :: Spec
|
||||||
spec =
|
spec =
|
||||||
describe "OrderedMap" $
|
describe "OrderedMap" $ do
|
||||||
it "creates an empty map" $
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user