diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-09-25 23:14:30 -0600 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-09-25 23:14:30 -0600 |
commit | 3a59cfb59b3339e13bdc9dfd1696ae2c554fcd9a (patch) | |
tree | 22ca47a8dec86c561e26f1ca07b4eb0a94d39bdd /src/Language/Fiddle/Internal | |
parent | 9b6a5f836680c95ce65390ba24a4c1390306fa75 (diff) | |
download | fiddle-3a59cfb59b3339e13bdc9dfd1696ae2c554fcd9a.tar.gz fiddle-3a59cfb59b3339e13bdc9dfd1696ae2c554fcd9a.tar.bz2 fiddle-3a59cfb59b3339e13bdc9dfd1696ae2c554fcd9a.zip |
Don't allow duplicate types.
Diffstat (limited to 'src/Language/Fiddle/Internal')
-rw-r--r-- | src/Language/Fiddle/Internal/Scopes.hs | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/src/Language/Fiddle/Internal/Scopes.hs b/src/Language/Fiddle/Internal/Scopes.hs index 280945d..302eab2 100644 --- a/src/Language/Fiddle/Internal/Scopes.hs +++ b/src/Language/Fiddle/Internal/Scopes.hs @@ -43,20 +43,26 @@ instance Semigroup (ScopePath k) where instance Monoid (ScopePath k) where mempty = ScopePath mempty mempty --- | 'insertScope' inserts a value 'v' into the scope at the specified --- key path ('NonEmpty k'). If the key path does not exist, it is created. -insertScope :: (Ord k) => NonEmpty k -> t -> Scope k t -> Scope k t -insertScope (s :| []) v (Scope ss sv) = Scope ss (Map.insert s v sv) -insertScope (s :| (a : as)) v (Scope ss sv) = - Scope - ( Map.alter - ( \case - (fromMaybe mempty -> mp) -> Just (insertScope (a :| as) v mp) - ) - s - ss - ) - sv +-- | 'upsertScope' attempts to insert a value 'v' into the 'Scope' at the given +-- key path ('NonEmpty k'). If the key path already exists, the value at the +-- final key is replaced, and the original value is returned in the result. +-- If the key path does not exist, it is created. The function returns a tuple +-- containing the previous value (if any) and the updated scope. +-- +-- This function effectively performs an "insert-or-update" operation, allowing +-- you to upsert values into nested scopes while tracking any existing value +-- that was replaced. +upsertScope :: (Ord k) => NonEmpty k -> t -> Scope k t -> (Maybe t, Scope k t) +upsertScope (s :| []) v (Scope ss sv) = + Scope ss <$> Map.insertLookupWithKey (\_ n _ -> n) s v sv +upsertScope (s :| (a : as)) v (Scope ss sv) = + let subscope = fromMaybe mempty (Map.lookup s ss) + (replaced, subscope') = upsertScope (a :| as) v subscope + in (replaced, Scope (Map.insert s subscope' ss) sv) + +-- insertScope :: (Ord k) => NonEmpty k -> t -> Scope k t -> Scope k t +-- insertScope a b = snd . upsertScope a b + -- | 'lookupScope' performs a lookup of a value in the scope using a key path -- ('NonEmpty k'). It traverses through sub-scopes as defined by the path. |