Skip to content

Commit

Permalink
Added optimized SortedMap.lookup/member/delete . NOT TESTED
Browse files Browse the repository at this point in the history
  • Loading branch information
bezirg committed Feb 28, 2024
1 parent fd8345c commit 81ff187
Showing 1 changed file with 28 additions and 7 deletions.
35 changes: 28 additions & 7 deletions plutus-tx/src/PlutusTx/SortedMap.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-| This is like `PlutusTx.AssocMap` but with the extra invariant that the entries are kept
sorted on the KEYS upon construction, insertion, and deletion.
As with "PlutusTx.AssocMap", using the unsafe API may lead to duplicate entries, whereas using the
Expand All @@ -18,6 +19,7 @@ module PlutusTx.SortedMap
, insert
, delete
, lookup
, member
, minViewWithKey
, isSortedDeDuped
, isValid
Expand Down Expand Up @@ -126,14 +128,33 @@ empty :: SortedMap k v
empty = SortedMap AssocMap.empty

{-# INLINABLE delete #-}
-- OPTIMIZE: Using AssocMap.delete works, but a version that stops earlier would be better
delete :: (Eq k) => k -> SortedMap k v -> SortedMap k v
delete k = fromMapUnsafe . AssocMap.delete k . toMap
delete :: forall k v. (Ord k) => k -> SortedMap k v -> SortedMap k v
delete c (toList -> alist) = fromListUnsafe (go alist)
where
go [] = []
go ms@(hd@(c', _) : rest) = case c `compare` c' of
LT -> hd : go rest
EQ -> rest
GT -> ms

{-# INLINABLE member #-}
-- | Is the key a member of the map?
member :: forall k v. (Ord k) => k -> SortedMap k v -> Bool
member k m = isJust (lookup k m)

{-# INLINABLE lookup #-}
-- OPTIMIZE: a manual implementation can stop earlier than AssocMap.lookup, upon missing keys only
lookup :: (Eq k) => k -> SortedMap k v -> Haskell.Maybe v
lookup k = AssocMap.lookup k . toMap
-- | Find an entry in a 'SortedMap'.
lookup :: forall k v. (Tx.Ord k) => k -> SortedMap k v -> Haskell.Maybe v
lookup c (toList -> alist) =
let
go :: [(k, v)] -> Maybe v
go [] = Nothing
go ((c', i) : xs') = case c `compare` c' of
LT -> go xs'
EQ -> Just i
GT -> Nothing
in
go alist

{-# INLINABLE minViewWithKey #-}
-- | Assumes that the SortedMap is valid.
Expand All @@ -154,8 +175,8 @@ insertInternal (k,v) = go
go = \case
[] -> [(k,v)]
ms@((k',v'):ms') -> case k `compare` k' of
EQ -> (k,v) : ms'
LT -> (k,v) : ms
EQ -> (k,v) : ms'
GT -> (k',v') : go ms'

{-# INLINABLE isSortedDeDuped #-}
Expand Down

0 comments on commit 81ff187

Please sign in to comment.