0 | ||| A module describing the dependent map (`DMap`).
   1 | ||| Copied from haskell's "dependent-map" package.
   2 | module Data.DMap
   3 |
   4 | import Control.Monad.State
   5 | import Data.Maybe
   6 |
   7 | import public Data.DFunctor
   8 | import public Data.DFoldable
   9 | import public Data.DSum
  10 | import public Data.DOrd
  11 | import public Data.DEq
  12 | import public Data.Some
  13 |
  14 | import Hedgehog
  15 |
  16 | error : String -> a
  17 | error msg = assert_total $ idris_crash msg
  18 |
  19 | ||| A copy of Haskells `ShowS` type
  20 | public export
  21 | ShowS : Type
  22 | ShowS = String -> String
  23 |
  24 | ||| A copy of Haskells `GHC.Show.showString` function
  25 | showString : String -> ShowS
  26 | showString = (++)
  27 |
  28 | {--------------------------------------------------------------------
  29 | ---------------------------------------------------------------------
  30 |   Data.Dependent.Map.Intenal
  31 | ---------------------------------------------------------------------
  32 | --------------------------------------------------------------------}
  33 |
  34 |
  35 | ||| Dependent maps: 'k' is a GADT-like thing with a facility for
  36 | ||| rediscovering its type parameter, elements of which function as identifiers
  37 | ||| tagged with the type of the thing they identify.  Real GADTs are one
  38 | ||| useful instantiation of `k`, as are 'Tag's from "Data.Unique.Tag" in the
  39 | ||| 'prim-uniq' package.
  40 | |||
  41 | ||| Semantically, `'DMap' k f` is equivalent to a set of `'DSum' k f` where no two
  42 | ||| elements have the same tag.
  43 | |||
  44 | ||| More informally, 'DMap' is to dependent products as 'M.Map' is to `(->)`.
  45 | ||| Thus it could also be thought of as a partial (in the sense of \"partial
  46 | ||| function\") dependent product.
  47 | export
  48 | data DMap : (k : a -> Type) -> (f : a -> Type) -> Type where
  49 |     Tip : DMap k f
  50 |     Bin : (sz    : Int)
  51 |        -> (key   : k v)
  52 |        -> (value : f v)
  53 |        -> (left  : DMap k f)
  54 |        -> (right : DMap k f)
  55 |        -> DMap k f
  56 |
  57 | {--------------------------------------------------------------------
  58 |   Construction
  59 | --------------------------------------------------------------------}
  60 |
  61 | ||| *O(1)*. The empty map.
  62 | |||
  63 | ||| ```
  64 | ||| empty      == fromList []
  65 | ||| size empty == 0
  66 | ||| ```
  67 | export
  68 | empty : DMap k f
  69 | empty = Tip
  70 |
  71 | ||| *O(1)*. A map with a single element.
  72 | |||
  73 | ||| ```
  74 | ||| singleton k v        == fromList [k :=> v]
  75 | ||| size (singleton k v) == 1
  76 | ||| ```
  77 | export
  78 | singleton : {0 v : a} -> k v -> f v -> DMap k f
  79 | singleton k x = Bin 1 k x Tip Tip
  80 |
  81 | {--------------------------------------------------------------------
  82 |   Query
  83 | --------------------------------------------------------------------}
  84 |
  85 | ||| *O(1)*. Is the map empty?
  86 | export
  87 | null : DMap k f -> Bool
  88 | null Tip              = True
  89 | null (Bin _ _ _ _ _)  = False
  90 |
  91 | ||| *O(1)*. The number of elements in the map.
  92 | export
  93 | size : DMap k f -> Int
  94 | size Tip                = 0
  95 | size (Bin n _ _ _ _)    = n
  96 |
  97 | ||| *O(log n)*. Lookup the value at a key in the map.
  98 | |||
  99 | ||| The function will return the corresponding value as `('Just' value)`,
 100 | ||| or 'Nothing' if the key isn't in the map.
 101 | export
 102 | lookup : (impl : DOrd k) => k v -> DMap k f -> Maybe (f v)
 103 | lookup k Tip = Nothing
 104 | lookup k (Bin _ kx x l r) = case dcompare k kx @{impl} of
 105 |   DLT => lookup k l
 106 |   DGT => lookup k r
 107 |   DEQ => Just x
 108 |
 109 | private
 110 | lookupAssoc : (impl : DOrd k) => Some k -> DMap k f -> Maybe (DSum k f)
 111 | lookupAssoc sk = withSome sk $ \key =>
 112 |   let
 113 |     go : DMap k f -> Maybe (DSum k f)
 114 |     go Tip = Nothing
 115 |     go (Bin _ kx x l r) =
 116 |         case dcompare key kx @{impl} of
 117 |             DLT => go l
 118 |             DGT => go r
 119 |             DEQ => Just (kx :=> x)
 120 |   in go
 121 |
 122 | {--------------------------------------------------------------------
 123 |   Utility functions that maintain the balance properties of the tree.
 124 |   All constructors assume that all values in [l] < [k] and all values
 125 |   in [r] > [k], and that [l] and [r] are valid trees.
 126 |
 127 |   In order of sophistication:
 128 |     [Bin sz k x l r]  The type constructor.
 129 |     [bin k x l r]     Maintains the correct size, assumes that both [l]
 130 |                       and [r] are balanced with respect to each other.
 131 |     [balance k x l r] Restores the balance and size.
 132 |                       Assumes that the original tree was balanced and
 133 |                       that [l] or [r] has changed by at most one element.
 134 |     [combine k x l r] Restores balance and size.
 135 |
 136 |   Furthermore, we can construct a new tree from two trees. Both operations
 137 |   assume that all values in [l] < all values in [r] and that [l] and [r]
 138 |   are valid:
 139 |     [glue l r]        Glues [l] and [r] together. Assumes that [l] and
 140 |                       [r] are already balanced with respect to each other.
 141 |     [merge l r]       Merges two trees and restores balance.
 142 |
 143 |   Note: in contrast to Adam's paper, we use (<=) comparisons instead
 144 |   of (<) comparisons in [combine], [merge] and [balance].
 145 |   Quickcheck (on [difference]) showed that this was necessary in order
 146 |   to maintain the invariants. It is quite unsatisfactory that I haven't
 147 |   been able to find out why this is actually the case! Fortunately, it
 148 |   doesn't hurt to be a bit more conservative.
 149 | --------------------------------------------------------------------}
 150 | private
 151 | delta, ratio : Int
 152 | delta = 4
 153 | ratio = 2
 154 |
 155 |
 156 | {--------------------------------------------------------------------
 157 |   The bin constructor maintains the size of the tree
 158 | --------------------------------------------------------------------}
 159 | private
 160 | bin : {0 v : a} -> k v -> f v -> DMap k f -> DMap k f -> DMap k f
 161 | bin k x l r
 162 |   = Bin (size l + size r + 1) k x l r
 163 |
 164 |
 165 |
 166 | -- basic rotations
 167 | private
 168 | singleL, singleR : {0 v : a} -> k v -> f v -> DMap k f -> DMap k f -> DMap k f
 169 | singleL k1 x1 t1 (Bin _ k2 x2 t2 t3)  = bin k2 x2 (bin k1 x1 t1 t2) t3
 170 | singleL _ _ _ Tip = error "error: singleL Tip"
 171 | singleR k1 x1 (Bin _ k2 x2 t1 t2) t3  = bin k2 x2 t1 (bin k1 x1 t2 t3)
 172 | singleR _ _ Tip _ = error "error: singleR Tip"
 173 |
 174 | private
 175 | doubleL, doubleR : {0 v : a} -> k v -> f v -> DMap k f -> DMap k f -> DMap k f
 176 | doubleL k1 x1 t1 (Bin _ k2 x2 (Bin _ k3 x3 t2 t3) t4) = bin k3 x3 (bin k1 x1 t1 t2) (bin k2 x2 t3 t4)
 177 | doubleL _ _ _ _ = error "error: doubleL"
 178 | doubleR k1 x1 (Bin _ k2 x2 t1 (Bin _ k3 x3 t2 t3)) t4 = bin k3 x3 (bin k2 x2 t1 t2) (bin k1 x1 t3 t4)
 179 | doubleR _ _ _ _ = error "error: doubleR"
 180 |
 181 |
 182 | -- rotate
 183 | private
 184 | rotateL : {0 v : a} -> k v -> f v -> DMap k f -> DMap k f -> DMap k f
 185 | rotateL k x l r@(Bin _ _ _ ly ry)
 186 |   = if size ly < ratio*size ry then singleL k x l r
 187 |                                else doubleL k x l r
 188 | rotateL _ _ _ Tip = error "error: rotateL Tip"
 189 |
 190 | private
 191 | rotateR : {0 v : a} -> k v -> f v -> DMap k f -> DMap k f -> DMap k f
 192 | rotateR k x l@(Bin _ _ _ ly ry) r
 193 |   = if size ry < ratio*size ly then singleR k x l r
 194 |                                else doubleR k x l r
 195 | rotateR _ _ Tip _ = error "error: rotateR Tip"
 196 |
 197 |
 198 | {--------------------------------------------------------------------
 199 |   [balance l x r] balances two trees with value x.
 200 |   The sizes of the trees should balance after decreasing the
 201 |   size of one of them. (a rotation).
 202 |
 203 |   [delta] is the maximal relative difference between the sizes of
 204 |           two trees, it corresponds with the [w] in Adams' paper.
 205 |   [ratio] is the ratio between an outer and inner sibling of the
 206 |           heavier subtree in an unbalanced setting. It determines
 207 |           whether a double or single rotation should be performed
 208 |           to restore balance. It corresponds with the inverse
 209 |           of $\alpha$ in Adam's article.
 210 |
 211 |   Note that:
 212 |   - [delta] should be larger than 4.646 with a [ratio] of 2.
 213 |   - [delta] should be larger than 3.745 with a [ratio] of 1.534.
 214 |
 215 |   - A lower [delta] leads to a more 'perfectly' balanced tree.
 216 |   - A higher [delta] performs less rebalancing.
 217 |
 218 |   - Balancing is automatic for random data and a balancing
 219 |     scheme is only necessary to avoid pathological worst cases.
 220 |     Almost any choice will do, and in practice, a rather large
 221 |     [delta] may perform better than smaller one.
 222 |
 223 |   Note: in contrast to Adam's paper, we use a ratio of (at least) [2]
 224 |   to decide whether a single or double rotation is needed. Although
 225 |   he actually proves that this ratio is needed to maintain the
 226 |   invariants, his implementation uses an invalid ratio of [1].
 227 | --------------------------------------------------------------------}
 228 | private
 229 | balance : {0 v : a} -> k v -> f v -> DMap k f -> DMap k f -> DMap k f
 230 | balance k x l r
 231 |   =    if sizeL + sizeR <= 1   then Bin sizeX k x l r
 232 |   else if sizeR >= delta*sizeL then rotateL k x l r
 233 |   else if sizeL >= delta*sizeR then rotateR k x l r
 234 |   else                              Bin sizeX k x l r
 235 |
 236 |   where
 237 |     sizeL, sizeR, sizeX : Int
 238 |     sizeL = size l
 239 |     sizeR = size r
 240 |     sizeX = sizeL + sizeR + 1
 241 |
 242 |
 243 | {--------------------------------------------------------------------
 244 |   Combine
 245 | --------------------------------------------------------------------}
 246 |
 247 | -- insertMin and insertMax don't perform potentially expensive comparisons.
 248 | private
 249 | insertMax, insertMin : {0 v : a} -> k v -> f v -> DMap k f -> DMap k f
 250 | insertMax kx x t
 251 |   = case t of
 252 |       Tip => singleton kx x
 253 |       Bin _ ky y l r
 254 |           => balance ky y l (insertMax kx x r)
 255 |
 256 | insertMin kx x t
 257 |   = case t of
 258 |       Tip => singleton kx x
 259 |       Bin _ ky y l r
 260 |           => balance ky y (insertMin kx x l) r
 261 |
 262 | private
 263 | combine : DOrd k => k v -> f v -> DMap k f -> DMap k f -> DMap k f
 264 | combine kx x Tip r  = insertMin kx x r
 265 | combine kx x l Tip  = insertMax kx x l
 266 | combine kx x l@(Bin sizeL ky y ly ry) r@(Bin sizeR kz z lz rz)
 267 |   =    if delta*sizeL <= sizeR then balance kz z (combine kx x l lz) rz
 268 |   else if delta*sizeR <= sizeL then balance ky y ly (combine kx x ry r)
 269 |   else                              bin kx x l r
 270 |
 271 | ||| *O(log n)*. Retrieves the minimal (key :=> value) entry of the map, and
 272 | ||| the map stripped of that element, or 'Nothing' if passed an empty map.
 273 | export
 274 | minViewWithKey : DMap k f -> Maybe (DSum k f, DMap k f)
 275 | minViewWithKey Tip = Nothing
 276 | minViewWithKey (Bin _ k0 x0 l0 r0) = Just $ go k0 x0 l0 r0
 277 |   where
 278 |     go : {0 k, f : a -> Type} -> k v -> f v -> DMap k f -> DMap k f -> (DSum k f, DMap k f)
 279 |     go k x Tip r = (k :=> x, r)
 280 |     go k x (Bin _ kl xl ll lr) r =
 281 |       let (km, l') = go kl xl ll lr
 282 |       in (km, balance k x l' r)
 283 |
 284 | ||| *O(log n)*. Retrieves the maximal (key :=> value) entry of the map, and
 285 | ||| the map stripped of that element, or 'Nothing' if passed an empty map.
 286 | export
 287 | maxViewWithKey : DMap k f -> Maybe (DSum k f, DMap k f)
 288 | maxViewWithKey Tip = Nothing
 289 | maxViewWithKey (Bin _ k0 x0 l0 r0) = Just $ go k0 x0 l0 r0
 290 |   where
 291 |     go : k v -> f v -> DMap k f -> DMap k f -> (DSum k f, DMap k f)
 292 |     go k x l Tip = (k :=> x, l)
 293 |     go k x l (Bin _ kr xr rl rr) =
 294 |       let (km, r') = go kr xr rl rr
 295 |       in (km, balance k x l r')
 296 |
 297 | ||| *O(log n)*. Delete and find the maximal element.
 298 | |||
 299 | ||| Given `k1, k2 < k3`
 300 | ||| ```
 301 | ||| deleteFindMax (fromList [k1 :=> v1, k2 :=> v2, k3 :=> v3]) == (k3 :=> v3, fromList [k1 :=> v1, k2 :=> v2])
 302 | ||| deleteFindMax empty                                            Error: can not return the maximal element of an empty map
 303 | ||| ```
 304 | export
 305 | deleteFindMax : DMap k f -> (DSum k f, DMap k f)
 306 | deleteFindMax t
 307 |   = case t of
 308 |       Bin _ k x l Tip => (k :=> x,l)
 309 |       Bin _ k x l r   => let (km,r') = deleteFindMax r in (km,balance k x l r')
 310 |       Tip             => (error "DMap.deleteFindMax: can not return the maximal element of an empty map", Tip)
 311 |
 312 | ||| *O(log n)*. Delete and find the minimal element.
 313 | |||
 314 | ||| Given `k2 > k1, k3`
 315 | ||| ```
 316 | ||| deleteFindMin (fromList [k1 :=> v1, k2 :=> v2, k3 :=> v3]) == (k2 :=> v2, fromList [k1 :=> v1, k3 :=> v3])
 317 | ||| deleteFindMin                                                  Error: can not return the minimal element of an empty map
 318 | ||| ```
 319 | export
 320 | deleteFindMin : DMap k f -> (DSum k f, DMap k f)
 321 | deleteFindMin t = case minViewWithKey t of
 322 |   Nothing => (error "DMap.deleteFindMin: can not return the minimal element of an empty map", Tip)
 323 |   Just p => p
 324 |
 325 | {--------------------------------------------------------------------
 326 |   [glue l r]: glues two trees together.
 327 |   Assumes that [l] and [r] are already balanced with respect to each other.
 328 | --------------------------------------------------------------------}
 329 | private
 330 | glue : DMap k f -> DMap k f -> DMap k f
 331 | glue Tip r = r
 332 | glue l Tip = l
 333 | glue l r =
 334 |   if size l > size r then case deleteFindMax l of (km :=> m, l') => balance km m l' r
 335 |                      else case deleteFindMin r of (km :=> m, r') => balance km m l r'
 336 |
 337 | {--------------------------------------------------------------------
 338 |   [merge l r]: merges two trees.
 339 | --------------------------------------------------------------------}
 340 | private
 341 | merge : DMap k f -> DMap k f -> DMap k f
 342 | merge Tip r   = r
 343 | merge l Tip   = l
 344 | merge l@(Bin sizeL kx x lx rx) r@(Bin sizeR ky y ly ry)
 345 |   =    if delta*sizeL <= sizeR then balance ky y (merge l ly) ry
 346 |   else if delta*sizeR <= sizeL then balance kx x lx (merge rx r)
 347 |   else                              glue l r
 348 |
 349 |
 350 | {--------------------------------------------------------------------
 351 |   Utility functions that return sub-ranges of the original
 352 |   tree. Some functions take a comparison function as argument to
 353 |   allow comparisons against infinite values. A function [cmplo k]
 354 |   should be read as [compare lo k].
 355 |
 356 |   [trim cmplo cmphi t]  A tree that is either empty or where [cmplo k == LT]
 357 |                         and [cmphi k == GT] for the key [k] of the root.
 358 |   [filterGt cmp t]      A tree where for all keys [k]. [cmp k == LT]
 359 |   [filterLt cmp t]      A tree where for all keys [k]. [cmp k == GT]
 360 |
 361 |   [split k t]           Returns two trees [l] and [r] where all keys
 362 |                         in [l] are <[k] and all keys in [r] are >[k].
 363 |   [splitLookup k t]     Just like [split] but also returns whether [k]
 364 |                         was found in the tree.
 365 | --------------------------------------------------------------------}
 366 |
 367 | {--------------------------------------------------------------------
 368 |   [trim lo hi t] trims away all subtrees that surely contain no
 369 |   values between the range [lo] to [hi]. The returned tree is either
 370 |   empty or the key of the root is between @lo@ and @hi@.
 371 | --------------------------------------------------------------------}
 372 | private
 373 | trim : (Some k -> Ordering) -> (Some k -> Ordering) -> DMap k f -> DMap k f
 374 | trim _     _     Tip = Tip
 375 | trim cmplo cmphi t@(Bin _ kx _ l r)
 376 |   = case cmplo (MkSome kx) of
 377 |       LT => case cmphi (MkSome kx) of
 378 |               GT => t
 379 |               _  => trim cmplo cmphi l
 380 |       _  => trim cmplo cmphi r
 381 |
 382 | private
 383 | trimLookupLo : DOrd k => Some k -> (Some k -> Ordering) -> DMap k f -> (Maybe (DSum k f), DMap k f)
 384 | trimLookupLo _  _     Tip = (Nothing,Tip)
 385 | trimLookupLo lo cmphi t@(Bin _ kx x l r)
 386 |   = case compare lo (MkSome kx) of
 387 |       LT => case cmphi (MkSome kx) of
 388 |               GT => (lookupAssoc lo t, t)
 389 |               _  => trimLookupLo lo cmphi l
 390 |       GT => trimLookupLo lo cmphi r
 391 |       EQ => (Just (kx :=> x), trim (compare lo) cmphi r)
 392 |
 393 | {--------------------------------------------------------------------
 394 |   [filterGt k t] filter all keys >[k] from tree [t]
 395 |   [filterLt k t] filter all keys <[k] from tree [t]
 396 | --------------------------------------------------------------------}
 397 | private
 398 | filterGt : DOrd k => (Some k -> Ordering) -> DMap k f -> DMap k f
 399 | filterGt cmp = go
 400 |   where
 401 |     go : DMap k f -> DMap k f
 402 |     go Tip              = Tip
 403 |     go (Bin _ kx x l r) = case cmp (MkSome kx) of
 404 |               LT => combine kx x (go l) r
 405 |               GT => go r
 406 |               EQ => r
 407 |
 408 | private
 409 | filterLt : DOrd k => (Some k -> Ordering) -> DMap k f -> DMap k f
 410 | filterLt cmp = go
 411 |   where
 412 |     go : DMap k f -> DMap k f
 413 |     go Tip              = Tip
 414 |     go (Bin _ kx x l r) = case cmp (MkSome kx) of
 415 |           LT => go l
 416 |           GT => combine kx x l (go r)
 417 |           EQ => l
 418 |
 419 | {--------------------------------------------------------------------
 420 | ---------------------------------------------------------------------
 421 |   Data.Dependent.Map
 422 | ---------------------------------------------------------------------
 423 | --------------------------------------------------------------------}
 424 |
 425 | {--------------------------------------------------------------------
 426 |   Query
 427 | --------------------------------------------------------------------}
 428 |
 429 | ||| *O(log n)*. Is the key a member of the map? See also 'notMember'.
 430 | export
 431 | member : DOrd k => k a -> DMap k f -> Bool
 432 | member k = isJust . lookup k
 433 |
 434 | ||| *O(log n)*. Is the key not a member of the map? See also 'member'.
 435 | export
 436 | notMember : DOrd k => k v -> DMap k f -> Bool
 437 | notMember k m = not (member k m)
 438 |
 439 | ||| *O(log n)*. Find the value at a key.
 440 | ||| Calls 'error' when the element can not be found.
 441 | ||| Consider using 'lookup' when elements may not be present.
 442 | private
 443 | find : DOrd k => k v -> DMap k f -> f v
 444 | find k m = case lookup k m of
 445 |     Nothing => error "DMap.find: element not in the map"
 446 |     Just v  => v
 447 |
 448 | ||| *O(log n)*. The expression `('findWithDefault' def k map)` returns
 449 | ||| the value at key `k` or returns default value `def`
 450 | ||| when the key is not in the map.
 451 | export
 452 | findWithDefault : DOrd k => f v -> k v -> DMap k f -> f v
 453 | findWithDefault def k m = case lookup k m of
 454 |     Nothing => def
 455 |     Just v  => v
 456 |
 457 | {--------------------------------------------------------------------
 458 |   Insertion
 459 | --------------------------------------------------------------------}
 460 |
 461 | ||| *O(log n)*. Insert a new key and value in the map.
 462 | ||| If the key is already present in the map, the associated value is
 463 | ||| replaced with the supplied value. 'insert' is equivalent to
 464 | ||| `'insertWith' 'const'`.
 465 | export
 466 | insert : (impl : DOrd k) => k v -> f v -> DMap k f -> DMap k f
 467 | insert kx x = evalState False . go
 468 |   where
 469 |     go : DMap k f -> State Bool (DMap k f)
 470 |     go Tip = put True >> pure (singleton kx x)
 471 |     go t@(Bin sz ky y l r) = case dcompare kx ky @{impl} of
 472 |       DLT => do
 473 |         l' <- go l
 474 |         sizeChange <- get
 475 |         -- originally pointer equality was used to see if the tree was modified
 476 |         if sizeChange then pure (balance ky y l' r)
 477 |                       else pure (Bin sz ky y l' r)
 478 |       DGT => do
 479 |         r' <- go r
 480 |         sizeChange <- get
 481 |         -- as above
 482 |         if sizeChange then pure (balance ky y l r')
 483 |                       else pure (Bin sz ky y l r')
 484 |       DEQ => pure (Bin sz kx x l r)
 485 |
 486 | ||| *O(log n)*. Insert a new key and value in the map if the key
 487 | ||| is not already present. If the key is already present, `insertR`
 488 | ||| does nothing.
 489 | private
 490 | insertR : (impl : DOrd k) => k v -> f v -> DMap k f -> DMap k f
 491 | insertR kx x = go
 492 |     where
 493 |         go : DMap k f -> DMap k f
 494 |         go Tip = singleton kx x
 495 |         go (Bin sz ky y l r) = case dcompare kx ky @{impl} of
 496 |             DLT => let l' = go l
 497 |                    -- pointer equality used before on trees
 498 |                    in if size l' == size l
 499 |                       then Bin sz ky y l' r
 500 |                       else balance ky y l' r
 501 |             DGT => let r' = go r
 502 |                    -- as above
 503 |                    in if size r' == size r
 504 |                    then Bin sz ky y l r'
 505 |                    else balance ky y l r'
 506 |             DEQ => Bin sz ky y l r
 507 |
 508 | ||| *O(log n)*. Insert with a function, combining key, new value and old value.
 509 | ||| `'insertWithKey' f key value mp`
 510 | ||| will insert the entry `key :=> value` into `mp` if key does
 511 | ||| not exist in the map. If the key does exist, the function will
 512 | ||| insert the entry `key :=> f key new_value old_value`.
 513 | ||| Note that the key passed to f is the same key passed to 'insertWithKey'.
 514 | export
 515 | insertWithKey : (impl : DOrd k) => (k v -> f v -> f v -> f v) -> k v -> f v -> DMap k f -> DMap k f
 516 | insertWithKey func kx x = go
 517 |   where
 518 |     go : DMap k f -> DMap k f
 519 |     go Tip = singleton kx x
 520 |     go (Bin sy ky y l r) =
 521 |         case dcompare kx ky @{impl} of
 522 |             DLT => balance ky y (go l) r
 523 |             DGT => balance ky y l (go r)
 524 |             DEQ => Bin sy kx (func kx x y) l r
 525 |
 526 | ||| *O(log n)*. Insert with a function, combining new value and old value.
 527 | ||| `'insertWith' f key value mp`
 528 | ||| will insert the entry `key :=> value` into `mp` if key does
 529 | ||| not exist in the map. If the key does exist, the function will
 530 | ||| insert the entry `key :=> f new_value old_value`.
 531 | export
 532 | insertWith : DOrd k => (f v -> f v -> f v) -> k v -> f v -> DMap k f -> DMap k f
 533 | insertWith f = insertWithKey (\_ => \x' => \y' => f x' y')
 534 |
 535 | ||| *O(log n)*. Combines insert operation with old value retrieval.
 536 | ||| The expression (`'insertLookupWithKey' f k x map`)
 537 | ||| is a pair where the first element is equal to (`'lookup' k map`)
 538 | export
 539 | insertLookupWithKey : (impl : DOrd k)
 540 |                    => (k v -> f v -> f v -> f v)
 541 |                    -> k v
 542 |                    -> f v
 543 |                    -> DMap k f
 544 |                    -> (Maybe (f v), DMap k f)
 545 | insertLookupWithKey func kx x = go
 546 |   where
 547 |     go : DMap k f -> (Maybe (f v), DMap k f)
 548 |     go Tip = (Nothing, singleton kx x)
 549 |     go (Bin sy ky y l r) =
 550 |         case dcompare kx ky @{impl} of
 551 |             DLT => let (found, l') = go l
 552 |                   in (found, balance ky y l' r)
 553 |             DGT => let (found, r') = go r
 554 |                   in (found, balance ky y l r')
 555 |             DEQ => (Just y, Bin sy kx (func kx x y) l r)
 556 |
 557 | {--------------------------------------------------------------------
 558 |   Deletion
 559 |   [delete] is the inlined version of [deleteWith (\k x -> Nothing)]
 560 | --------------------------------------------------------------------}
 561 |
 562 | ||| *O(log n)*. Delete a key and its value from the map. When the key is not
 563 | ||| a member of the map, the original map is returned.
 564 | --delete :: forall k f v. GCompare k => k v -> DMap k f -> DMap k f
 565 | export
 566 | delete : (impl : DOrd k) => k v -> DMap k f -> DMap k f
 567 | delete k' = go
 568 |   where
 569 |     go : DMap k f -> DMap k f
 570 |     go Tip = Tip
 571 |     go (Bin _ kx x l r) =
 572 |         case dcompare k' kx @{impl} of
 573 |             DLT => balance kx x (go l) r
 574 |             DGT => balance kx x l (go r)
 575 |             DEQ => glue l r
 576 |
 577 | ||| *O(log n)*. Adjust a value at a specific key. When the key is not
 578 | ||| a member of the map, the original map is returned.
 579 | adjustWithKey : (impl : DOrd k) => (k v -> f v -> f v) -> k v -> DMap k f -> DMap k f
 580 | adjustWithKey f0 k0 = go f0 k0
 581 |   where
 582 |     go : (k v -> f v -> f v) -> k v -> DMap k f -> DMap k f
 583 |     go f k Tip = Tip
 584 |     go f k (Bin sx kx x l r) =
 585 |       case dcompare k kx @{impl} of
 586 |         DLT => Bin sx kx x (go f k l) r
 587 |         DGT => Bin sx kx x l (go f k r)
 588 |         DEQ => Bin sx kx (f kx x) l r
 589 |
 590 | ||| *O(log n)*. Update a value at a specific key with the result of the provided function.
 591 | ||| When the key is not
 592 | ||| a member of the map, the original map is returned.
 593 | adjust : DOrd k => (f v -> f v) -> k v -> DMap k f -> DMap k f
 594 | adjust f = adjustWithKey (\_ => \x => f x)
 595 |
 596 | ||| *O(log n)*. The expression (`'updateWithKey' f k map`) updates the
 597 | ||| value `x` at `k` (if it is in the map). If (`f k x`) is 'Nothing',
 598 | ||| the element is deleted. If it is (`'Just' y`), the key `k` is bound
 599 | ||| to the new value `y`.
 600 | export
 601 | updateWithKey : (impl : DOrd k) => (k v -> f v -> Maybe (f v)) -> k v -> DMap k f -> DMap k f
 602 | updateWithKey func key = go
 603 |   where
 604 |     go : DMap k f -> DMap k f
 605 |     go Tip = Tip
 606 |     go (Bin sx kx x l r) =
 607 |         case dcompare key kx @{impl} of
 608 |            DLT => balance kx x (go l) r
 609 |            DGT => balance kx x l (go r)
 610 |            DEQ => case func kx x of
 611 |                    Just x' => Bin sx kx x' l r
 612 |                    Nothing => glue l r
 613 |
 614 | ||| *O(log n)*. The expression (`'update' f k map`) updates the value `x`
 615 | ||| at `k` (if it is in the map). If (`f x`) is 'Nothing', the element is
 616 | ||| deleted. If it is (`'Just' y`), the key `k` is bound to the new value `y`.
 617 | export
 618 | update : DOrd k => (f v -> Maybe (f v)) -> k v -> DMap k f -> DMap k f
 619 | update f = updateWithKey (\_ => \x => f x)
 620 |
 621 | ||| *O(log n)*. Lookup and update. See also 'updateWithKey'.
 622 | ||| The function returns changed value, if it is updated.
 623 | ||| Returns the original key value if the map entry is deleted.
 624 | export
 625 | updateLookupWithKey : (impl : DOrd k) => (k v -> f v -> Maybe (f v)) -> k v -> DMap k f -> (Maybe (f v), DMap k f)
 626 | updateLookupWithKey func key = go
 627 |  where
 628 |    go : DMap k f -> (Maybe (f v), DMap k f)
 629 |    go Tip = (Nothing,Tip)
 630 |    go (Bin sx kx x l r) =
 631 |           case dcompare key kx @{impl} of
 632 |                DLT => let (found,l') = go l in (found,balance kx x l' r)
 633 |                DGT => let (found,r') = go r in (found,balance kx x l r')
 634 |                DEQ => case func kx x of
 635 |                        Just x' => (Just x',Bin sx kx x' l r)
 636 |                        Nothing => (Just x,glue l r)
 637 |
 638 | ||| *O(log n)*. The expression (`'alter' f k map`) alters the value `x` at `k`, or absence thereof.
 639 | ||| 'alter' can be used to insert, delete, or update a value in a 'Map'.
 640 | ||| In short : `'lookup' k ('alter' f k m) = f ('lookup' k m)`.
 641 | export
 642 | alter : (impl : DOrd k) => (Maybe (f v) -> Maybe (f v)) -> k v -> DMap k f -> DMap k f
 643 | alter func key = go
 644 |   where
 645 |     go : DMap k f -> DMap k f
 646 |     go Tip = case func Nothing of
 647 |                Nothing => Tip
 648 |                Just x  => singleton key x
 649 |
 650 |     go (Bin sx kx x l r) = case dcompare key kx @{impl} of
 651 |                DLT => balance kx x (go l) r
 652 |                DGT => balance kx x l (go r)
 653 |                DEQ => case func (Just x) of
 654 |                        Just x' => Bin sx kx x' l r
 655 |                        Nothing => glue l r
 656 |
 657 | ||| Works the same as 'alter' except the new value is returned in some 'Functor' `f`.
 658 | ||| In short : `(\v' -> alter (const v') k dm) <$> f (lookup k dm)`
 659 | export
 660 | alterF : (impl : DOrd k) => Functor f => k v -> (Maybe (g v) -> f (Maybe (g v))) -> DMap k g -> f (DMap k g)
 661 | alterF key func = go
 662 |   where
 663 |     go : DMap k g -> f (DMap k g)
 664 |     go Tip = maybe Tip (singleton key) <$> func Nothing
 665 |
 666 |     go (Bin sx kx x l r) = case dcompare key kx @{impl} of
 667 |       DLT => (\l' => balance kx x l' r) <$> go l
 668 |       DGT => (\r' => balance kx x l r') <$> go r
 669 |       DEQ => maybe (glue l r) (\x' => Bin sx kx x' l r) <$> func (Just x)
 670 |
 671 | {--------------------------------------------------------------------
 672 |   Indexing
 673 | --------------------------------------------------------------------}
 674 |
 675 | ||| *O(log n)*. Lookup the *index* of a key. The index is a number from
 676 | ||| *0* up to, but not including, the 'size' of the map.
 677 | export
 678 | lookupIndex : (impl : DOrd k) => k v -> DMap k f -> Maybe Int
 679 | lookupIndex key = go 0
 680 |   where
 681 |     go : Int -> DMap k f -> Maybe Int
 682 |     go idx Tip  = Nothing
 683 |     go idx (Bin _ kx _ l r)
 684 |       = case dcompare key kx @{impl} of
 685 |           DLT => go idx l
 686 |           DGT => go (idx + size l + 1) r
 687 |           DEQ => Just (idx + size l)
 688 |
 689 | ||| *O(log n)*. Return the *index* of a key. The index is a number from
 690 | ||| *0* up to, but not including, the 'size' of the map. Calls 'error' when
 691 | ||| the key is not a 'member' of the map.
 692 | export
 693 | findIndex : DOrd k => k v -> DMap k f -> Int
 694 | findIndex k t
 695 |   = case lookupIndex k t of
 696 |       Nothing  => error "DMap.findIndex: element is not in the map"
 697 |       Just idx => idx
 698 |
 699 | ||| *O(log n)*. Retrieve an element by *index*. Calls 'error' when an
 700 | ||| invalid index is used.
 701 | export
 702 | elemAt : Int -> DMap k f -> DSum k f
 703 | elemAt _ Tip = error "DMap.elemAt: index out of range"
 704 | elemAt i (Bin _ kx x l r)
 705 |   = case compare i sizeL of
 706 |       LT => elemAt i l
 707 |       GT => elemAt (i - sizeL - 1) r
 708 |       EQ => kx :=> x
 709 |   where
 710 |     sizeL : Int
 711 |     sizeL = size l
 712 |
 713 | ||| *O(log n)*. Update the element at *index*. Does nothing when an
 714 | ||| invalid index is used.
 715 | export
 716 | updateAt : ({0 v : a} -> k v -> f v -> Maybe (f v)) -> Int -> DMap k f -> DMap k f
 717 | updateAt func i0 t = go i0 t
 718 |  where
 719 |     go : Int -> DMap k f -> DMap k f
 720 |     go _ Tip  = Tip
 721 |     go i (Bin sx kx x l r) = case compare i sizeL of
 722 |       LT => balance kx x (go i l) r
 723 |       GT => balance kx x l (go (i-sizeL-1) r)
 724 |       EQ => case func kx x of
 725 |               Just x' => Bin sx kx x' l r
 726 |               Nothing => glue l r
 727 |       where
 728 |         sizeL : Int
 729 |         sizeL = size l
 730 |
 731 | ||| *O(log n)*. Delete the element at *index*.
 732 | ||| Defined as (`'deleteAt' i map = 'updateAt' (\k x -> 'Nothing') i map`).
 733 | export
 734 | deleteAt : Int -> DMap k f -> DMap k f
 735 | deleteAt i m
 736 |   = updateAt (\_ => \_ => Nothing) i m
 737 |
 738 | {--------------------------------------------------------------------
 739 |   Minimal, Maximal
 740 | --------------------------------------------------------------------}
 741 |
 742 | export
 743 | lookupMin : DMap k f -> Maybe (DSum k f)
 744 | lookupMin m = case m of
 745 |       Tip => Nothing
 746 |       Bin _ kx x l _ => Just $ go kx x l
 747 |   where
 748 |     go : k v -> f v -> DMap k f -> DSum k f
 749 |     go kx x Tip = kx :=> x
 750 |     go _  _ (Bin _ kx x l _) = go kx x l
 751 |
 752 | ||| *O(log n)*. The minimal key of the map. Calls 'error' if the map is empty.
 753 | export
 754 | findMin : DMap k f -> DSum k f
 755 | findMin m = case lookupMin m of
 756 |   Just x => x
 757 |   Nothing => error "DMap.findMin: empty map has no minimal element"
 758 |
 759 | export
 760 | lookupMax : DMap k f -> Maybe (DSum k f)
 761 | lookupMax m = case m of
 762 |       Tip => Nothing
 763 |       Bin _ kx x _ r => Just $ go kx x r
 764 |   where
 765 |     go : k v -> f v -> DMap k f -> DSum k f
 766 |     go kx x Tip = kx :=> x
 767 |     go _  _ (Bin _ kx x _ r) = go kx x r
 768 |
 769 | ||| *O(log n)*. The maximal key of the map. Calls 'error' if the map is empty.
 770 | export
 771 | findMax : DMap k f -> DSum k f
 772 | findMax m = case lookupMax m of
 773 |   Just x => x
 774 |   Nothing => error "DMap.findMax: empty map has no maximal element"
 775 |
 776 | ||| *O(log n)*. Delete the minimal key. Returns an empty map if the map is empty.
 777 | export
 778 | deleteMin : DMap k f -> DMap k f
 779 | deleteMin (Bin _ _  _ Tip r)  = r
 780 | deleteMin (Bin _ kx x l r)    = balance kx x (deleteMin l) r
 781 | deleteMin Tip                 = Tip
 782 |
 783 | ||| *O(log n)*. Delete the maximal key. Returns an empty map if the map is empty.
 784 | export
 785 | deleteMax : DMap k f -> DMap k f
 786 | deleteMax (Bin _ _  _ l Tip)  = l
 787 | deleteMax (Bin _ kx x l r)    = balance kx x l (deleteMax r)
 788 | deleteMax Tip                 = Tip
 789 |
 790 | ||| *O(log n)*. Update the value at the minimal key.
 791 | export
 792 | updateMinWithKey : ({0 v : a} -> k v -> f v -> Maybe (f v)) -> DMap k f -> DMap k f
 793 | updateMinWithKey func = go
 794 |  where
 795 |   go : DMap k f -> DMap k f
 796 |   go (Bin sx kx x Tip r) = case func kx x of
 797 |                             Nothing => r
 798 |                             Just x' => Bin sx kx x' Tip r
 799 |   go (Bin _ kx x l r)    = balance kx x (go l) r
 800 |   go Tip                 = Tip
 801 |
 802 | ||| *O(log n)*. Update the value at the maximal key.
 803 | export
 804 | updateMaxWithKey : ({0 v : a} -> k v -> f v -> Maybe (f v)) -> DMap k f -> DMap k f
 805 | updateMaxWithKey func = go
 806 |  where
 807 |   go : DMap k f -> DMap k f
 808 |   go (Bin sx kx x l Tip) = case func kx x of
 809 |                             Nothing => l
 810 |                             Just x' => Bin sx kx x' l Tip
 811 |   go (Bin _ kx x l r)    = balance kx x l (go r)
 812 |   go Tip                 = Tip
 813 |
 814 | {--------------------------------------------------------------------
 815 |   Split
 816 | --------------------------------------------------------------------}
 817 |
 818 | ||| *O(log n)*. The expression (`'split' k map`) is a pair `(map1,map2)` where
 819 | ||| the keys in `map1` are smaller than `k` and the keys in `map2` larger than `k`.
 820 | ||| Any key equal to `k` is found in neither `map1` nor `map2`.
 821 | export
 822 | split : (impl : DOrd k) => k v -> DMap k f -> (DMap k f, DMap k f)
 823 | split key = go
 824 |   where
 825 |     go : DMap k f -> (DMap k f, DMap k f)
 826 |     go Tip              = (Tip, Tip)
 827 |     go (Bin _ kx x l r) = case dcompare key kx @{impl} of
 828 |           DLT => let (lt, gt) = go l in (lt, combine kx x gt r)
 829 |           DGT => let (lt, gt) = go r in (combine kx x l lt, gt)
 830 |           DEQ => (l, r)
 831 |
 832 | ||| *O(log n)*. The expression (`'splitLookup' k map`) splits a map just
 833 | ||| like 'split' but also returns `'lookup' k map`.
 834 | export
 835 | splitLookup : (impl : DOrd k) => k v -> DMap k f -> (DMap k f, Maybe (f v), DMap k f)
 836 | splitLookup key = go
 837 |   where
 838 |     go : DMap k f -> (DMap k f, Maybe (f v), DMap k f)
 839 |     go Tip              = (Tip, Nothing, Tip)
 840 |     go (Bin _ kx x l r) = case dcompare key kx @{impl} of
 841 |       DLT => let (lt, z, gt) = go l in (lt, z, combine kx x gt r)
 842 |       DGT => let (lt, z, gt) = go r in (combine kx x l lt, z, gt)
 843 |       DEQ => (l, Just x, r)
 844 |
 845 | ||| *O(log n)*. The expression (`'splitMember' k map`) splits a map just
 846 | ||| like 'split' but also returns `'member' k map`.
 847 | private
 848 | splitMember : (impl : DOrd k) => k v -> DMap k f -> (DMap k f, Bool, DMap k f)
 849 | splitMember key = go
 850 |   where
 851 |     go : DMap k f -> (DMap k f, Bool, DMap k f)
 852 |     go Tip              = (Tip, False, Tip)
 853 |     go (Bin _ kx x l r) = case dcompare key kx @{impl} of
 854 |       DLT => let (lt, z, gt) = go l in (lt, z, combine kx x gt r)
 855 |       DGT => let (lt, z, gt) = go r in (combine kx x l lt, z, gt)
 856 |       DEQ => (l, True, r)
 857 |
 858 | ||| *O(log n)*.
 859 | private
 860 | splitLookupWithKey : (impl : DOrd k) => k v -> DMap k f -> (DMap k f, Maybe (k v, f v), DMap k f)
 861 | splitLookupWithKey key = go
 862 |   where
 863 |     go : DMap k f -> (DMap k f, Maybe (k v, f v), DMap k f)
 864 |     go Tip              = (Tip, Nothing, Tip)
 865 |     go (Bin _ kx x l r) = case dcompare key kx @{impl} of
 866 |       DLT => let (lt, z, gt) = go l in (lt, z, combine kx x gt r)
 867 |       DGT => let (lt, z, gt) = go r in (combine kx x l lt, z, gt)
 868 |       DEQ => (l, Just (kx, x), r)
 869 |
 870 | {--------------------------------------------------------------------
 871 |   Union.
 872 | --------------------------------------------------------------------}
 873 |
 874 | ||| *O(m*log(n/m + 1)), m <= n*.
 875 | ||| The expression (`'union' t1 t2`) takes the left-biased union of `t1` and `t2`.
 876 | ||| It prefers `t1` when duplicate keys are encountered,
 877 | ||| i.e. (`'union' == 'unionWith' 'const'`).
 878 | export
 879 | union : DOrd k => DMap k f -> DMap k f -> DMap k f
 880 | union t1 Tip  = t1
 881 | union t1 (Bin _ kx x Tip Tip) = insertR kx x t1
 882 | union Tip t2  = t2
 883 | union (Bin _ kx x Tip Tip) t2 = insert kx x t2
 884 | union t1@(Bin _ k1 x1 l1 r1) t2 = case split k1 t2 of
 885 |   (l2, r2) => combine k1 x1 (l1 `union` l2) (r1 `union` r2)
 886 |
 887 | ||| The union of a list of maps:
 888 | |||   (`'unions' == 'Prelude.foldl' 'union' 'empty'`).
 889 | export
 890 | unions : DOrd k => List (DMap k f) -> DMap k f
 891 | unions ts = foldl union empty ts
 892 |
 893 | {--------------------------------------------------------------------
 894 |   Semigroup, Monoid
 895 | --------------------------------------------------------------------}
 896 |
 897 | export
 898 | implementation (DOrd k) => Semigroup (DMap k f) where
 899 |   (<+>) = union
 900 |
 901 | export
 902 | implementation (DOrd k) => Monoid (DMap k f) where
 903 |     neutral = empty
 904 |
 905 | {--------------------------------------------------------------------
 906 |   Union with a combining function
 907 | --------------------------------------------------------------------}
 908 |
 909 | ||| *O(n+m)*.
 910 | ||| Union with a combining function.
 911 | export
 912 | unionWithKey : DOrd k => ({0 v : a} -> k v -> f v -> f v -> f v) -> DMap k f -> DMap k f -> DMap k f
 913 | unionWithKey _ t1 Tip  = t1
 914 | unionWithKey _ Tip t2  = t2
 915 | unionWithKey f (Bin _ k1 x1 l1 r1) t2 = case splitLookup k1 t2 of
 916 |   (l2, mx2, r2) => let
 917 |       l1l2 = unionWithKey f l1 l2
 918 |       r1r2 = unionWithKey f r1 r2
 919 |     in case mx2 of
 920 |       Nothing => combine k1 x1 l1l2 r1r2
 921 |       Just x2 => combine k1 (f k1 x1 x2) l1l2 r1r2
 922 |
 923 | ||| The union of a list of maps, with a combining operation:
 924 | |||   (`'unionsWithKey' f == 'Prelude.foldl' ('unionWithKey' f) 'empty'`).
 925 | export
 926 | unionsWithKey : DOrd k => ({0 v : a} -> k v -> f v -> f v -> f v) -> List (DMap k f) -> DMap k f
 927 | unionsWithKey f ts = foldl (unionWithKey f) empty ts
 928 |
 929 | {--------------------------------------------------------------------
 930 |   Difference
 931 | --------------------------------------------------------------------}
 932 |
 933 | ||| *O(m * log (n/m + 1)), m <= n*. Difference of two maps.
 934 | ||| Return elements of the first map not existing in the second map.
 935 | export
 936 | difference : DOrd k => DMap k f -> DMap k g -> DMap k f
 937 | difference Tip _   = Tip
 938 | difference t1 Tip  = t1
 939 | difference t1 (Bin _ k2 x2 l2 r2) = case split k2 t1 of
 940 |   (l1, r1) => let
 941 |       l1l2 = l1 `difference` l2
 942 |       r1r2 = r1 `difference` r2
 943 |     in if size t1 == size l1l2 + size r1r2 then t1
 944 |                                            else merge l1l2 r1r2
 945 |
 946 | ||| *O(n+m)*. Difference with a combining function. When two equal keys are
 947 | ||| encountered, the combining function is applied to the key and both values.
 948 | ||| If it returns 'Nothing', the element is discarded (proper set difference). If
 949 | ||| it returns (`'Just' y`), the element is updated with a new value `y`.
 950 | export
 951 | differenceWithKey : (impl : DOrd k)
 952 |                  => ({0 v : a} -> k v -> f v -> g v -> Maybe (f v))
 953 |                  -> DMap k f
 954 |                  -> DMap k g
 955 |                  -> DMap k f
 956 | differenceWithKey _ Tip _   = Tip
 957 | differenceWithKey _ t1 Tip  = t1
 958 | differenceWithKey f (Bin _ k1 x1 l1 r1) t2 = case splitLookup k1 t2 of
 959 |   (l2, mx2, r2) => let
 960 |       l1l2 = differenceWithKey f l1 l2
 961 |       r1r2 = differenceWithKey f r1 r2
 962 |     in case mx2 of
 963 |       Nothing => combine k1 x1 l1l2 r1r2
 964 |       Just x2 => case f k1 x1 x2 of
 965 |         Nothing   => merge l1l2 r1r2
 966 |         Just x1x2 => combine k1 x1x2 l1l2 r1r2
 967 |
 968 |
 969 | {--------------------------------------------------------------------
 970 |   Intersection
 971 | --------------------------------------------------------------------}
 972 |
 973 | ||| *O(m * log (n/m + 1), m <= n*. Intersection of two maps.
 974 | ||| Return data in the first map for the keys existing in both maps.
 975 | ||| (`'intersection' m1 m2 == 'intersectionWith' 'const' m1 m2`).
 976 | export
 977 | intersection : DOrd k => DMap k f -> DMap k f -> DMap k f
 978 | intersection Tip _ = Tip
 979 | intersection _ Tip = Tip
 980 | intersection t1@(Bin s1 k1 x1 l1 r1) t2 =
 981 |   let (l2, found, r2) = splitMember k1 t2
 982 |       l1l2 = intersection l1 l2
 983 |       r1r2 = intersection r1 r2
 984 |   in if found
 985 |      then if size l1l2 == size l1 && size r1r2 == size r1
 986 |           then t1
 987 |           else combine k1 x1 l1l2 r1r2
 988 |      else merge l1l2 r1r2
 989 |
 990 |
 991 | ||| *O(m * log (n/m + 1), m <= n*. Intersection with a combining function.
 992 | export
 993 | intersectionWithKey : DOrd k => ({0 v : a} -> k v -> f v -> g v -> h v) -> DMap k f -> DMap k g -> DMap k h
 994 | intersectionWithKey _ Tip _ = Tip
 995 | intersectionWithKey _ _ Tip = Tip
 996 | intersectionWithKey f (Bin s1 k1 x1 l1 r1) t2 =
 997 |   let (l2, found, r2) = splitLookup k1 t2
 998 |       l1l2 = intersectionWithKey f l1 l2
 999 |       r1r2 = intersectionWithKey f r1 r2
1000 |   in case found of
1001 |        Nothing => merge l1l2 r1r2
1002 |        Just x2 => combine k1 (f k1 x1 x2) l1l2 r1r2
1003 |
1004 | {--------------------------------------------------------------------
1005 |   Submap
1006 | --------------------------------------------------------------------}
1007 | private
1008 | submap' : DOrd k => ({0 v : a} -> k v -> k v -> f v -> g v -> Bool) -> DMap k f -> DMap k g -> Bool
1009 | submap' _ Tip _ = True
1010 | submap' _ _ Tip = False
1011 | submap' f (Bin _ kx x l r) t
1012 |   = let
1013 |       (lt, found, gt) = splitLookupWithKey kx t
1014 |     in case found of
1015 |       Nothing => False
1016 |       Just (ky, y) => f kx ky x y && submap' f l lt && submap' f r gt
1017 |
1018 | ||| *O(n+m)*.
1019 | ||| The expression (`'isSubmapOfBy' f t1 t2`) returns 'True' if
1020 | ||| all keys in `t1` are in tree `t2`, and when `f` returns 'True' when
1021 | ||| applied to their respective keys and values.
1022 | export
1023 | isSubmapOfBy : DOrd k => ({0 v : a} -> k v -> k v -> f v -> g v -> Bool) -> DMap k f -> DMap k g -> Bool
1024 | isSubmapOfBy f t1 t2 = (size t1 <= size t2) && (submap' f t1 t2)
1025 |
1026 | {-
1027 | ||| *O(n+m)*.
1028 | ||| This function is defined as (`'isSubmapOf' = 'isSubmapOfBy' 'eqTagged')`).
1029 | |||
1030 | export
1031 | isSubmapOf
1032 |   :: forall k f
1033 |   .  (GCompare k, Has' Eq k f)
1034 |   => DMap k f -> DMap k f -> Bool
1035 | isSubmapOf m1 m2 = isSubmapOfBy (\k _ x0 x1 -> has' @Eq @f k (x0 == x1)) m1 m2
1036 | -}
1037 |
1038 | ||| *O(n+m)*. Is this a proper submap? (ie. a submap but not equal).
1039 | ||| The expression (`'isProperSubmapOfBy' f m1 m2`) returns 'True' when
1040 | ||| `m1` and `m2` are not equal,
1041 | ||| all keys in `m1` are in `m2`, and when `f` returns 'True' when
1042 | ||| applied to their respective keys and values.
1043 | export
1044 | isProperSubmapOfBy : DOrd k => ({0 v : a} -> k v -> k v -> f v -> g v -> Bool) -> DMap k f -> DMap k g -> Bool
1045 | isProperSubmapOfBy f t1 t2 = (size t1 < size t2) && (submap' f t1 t2)
1046 |
1047 | {-
1048 | ||| *O(n+m)*. Is this a proper submap? (ie. a submap but not equal).
1049 | ||| Defined as (`'isProperSubmapOf' = 'isProperSubmapOfBy' 'eqTagged'`).
1050 | export
1051 | isProperSubmapOf
1052 |   :: forall k f
1053 |   .  (GCompare k, Has' Eq k f)
1054 |   => DMap k f -> DMap k f -> Bool
1055 | isProperSubmapOf m1 m2
1056 |   = isProperSubmapOfBy (\k _ x0 x1 -> has' `Eq `f k (x0 == x1)) m1 m2
1057 | -}
1058 |
1059 | {--------------------------------------------------------------------
1060 |   Filter and partition
1061 | --------------------------------------------------------------------}
1062 | ||| *O(n)*. Filter all keys/values that satisfy the predicate.
1063 | export
1064 | filterWithKey : DOrd k => ({0 v : a} -> k v -> f v -> Bool) -> DMap k f -> DMap k f
1065 | filterWithKey p = go
1066 |   where
1067 |     go : DMap k f -> DMap k f
1068 |     go Tip = Tip
1069 |     go t@(Bin sz kx x l r)
1070 |       = let
1071 |           l' = go l
1072 |           r' = go r
1073 |         in if p kx x then if size l' == size l && size r' == size r
1074 |                           then Bin sz kx x l' r'
1075 |                           else combine kx x l' r'
1076 |                      else merge l' r'
1077 |
1078 | ||| *O(n)*. Partition the map according to a predicate. The first
1079 | ||| map contains all elements that satisfy the predicate, the second all
1080 | ||| elements that fail the predicate. See also 'split'.
1081 | export
1082 | partitionWithKey : (impl : DOrd k) => ({0 v : a} -> k v -> f v -> Bool) -> DMap k f -> (DMap k f, DMap k f)
1083 | partitionWithKey p0 m0 = go p0 m0
1084 |   where
1085 |     go : ({0 v : a} -> k v -> f v -> Bool) -> DMap k f -> (DMap k f, DMap k f)
1086 |     go _ Tip = (Tip, Tip)
1087 |     go p (Bin _ kx x l r) = let
1088 |         (l1, l2) = go p l
1089 |         (r1, r2) = go p r
1090 |       in if p kx x then (combine kx x l1 r1, merge l2 r2)
1091 |                    else (merge l1 r1, combine kx x l2 r2)
1092 |
1093 | ||| *O(n)*. Map keys/values and collect the 'Just' results.
1094 | mapMaybeWithKey : (impl : DOrd k) => ({0 v : a} -> k v -> f v -> Maybe (g v)) -> DMap k f -> DMap k g
1095 | mapMaybeWithKey func = go
1096 |   where
1097 |     go : DMap k f -> DMap k g
1098 |     go Tip = Tip
1099 |     go (Bin _ kx x l r) = case func kx x of
1100 |         Just y  => combine kx y (go l) (go r)
1101 |         Nothing => merge (go l) (go r)
1102 |
1103 | ||| *O(n)*. Map values and collect the 'Just' results.
1104 | export
1105 | mapMaybe : DOrd k => ({0 v : a} -> f v -> Maybe (g v)) -> DMap k f -> DMap k g
1106 | mapMaybe f = mapMaybeWithKey (const f)
1107 |
1108 | ||| *O(n)*. Map keys/values and separate the 'Left' and 'Right' results.
1109 | export
1110 | mapEitherWithKey : DOrd k =>
1111 |   ({0 v : a} -> k v -> f v -> Either (g v) (h v)) -> DMap k f -> (DMap k g, DMap k h)
1112 | mapEitherWithKey f0 = go f0
1113 |   where
1114 |     go : ({0 v : a} -> k v -> f v -> Either (g v) (h v))
1115 |       -> DMap k f
1116 |       -> (DMap k g, DMap k h)
1117 |     go _ Tip = (Tip, Tip)
1118 |     go f (Bin _ kx x l r) = let
1119 |         (l1, l2) = mapEitherWithKey f l
1120 |         (r1, r2) = mapEitherWithKey f r
1121 |       in case f kx x of
1122 |         Left y  => (combine kx y l1 r1, merge l2 r2)
1123 |         Right z => (merge l1 r1, combine kx z l2 r2)
1124 |
1125 | {--------------------------------------------------------------------
1126 |   Folds
1127 | --------------------------------------------------------------------}
1128 |
1129 | ||| *O(n)*. Post-order fold.  The function will be applied from the lowest
1130 | ||| value to the highest.
1131 | export
1132 | foldrWithKey : ({0 v : a} -> k v -> f v -> b -> b) -> b -> DMap k f -> b
1133 | foldrWithKey func = go
1134 |   where
1135 |     go : b -> DMap k f -> b
1136 |     go z Tip              = z
1137 |     go z (Bin _ kx x l r) = go (func kx x (go z r)) l
1138 |
1139 | ||| *O(n)*. Pre-order fold.  The function will be applied from the highest
1140 | ||| value to the lowest.
1141 | export
1142 | foldlWithKey : ({0 v : a} -> b -> k v -> f v -> b) -> b -> DMap k f -> b
1143 | foldlWithKey func = go
1144 |   where
1145 |     go : b -> DMap k f -> b
1146 |     go z Tip              = z
1147 |     go z (Bin _ kx x l r) = go (func (go z l) kx x) r
1148 |
1149 | export
1150 | implementation DFoldable (DMap k) where
1151 |   dfoldr f = foldrWithKey (\k => f)
1152 |
1153 | {--------------------------------------------------------------------
1154 |   Lists
1155 |   use [foldlStrict] to reduce demand on the control-stack
1156 | --------------------------------------------------------------------}
1157 |
1158 | ||| *O(n*log n)*. Build a map from a list of key/value pairs. See also 'fromAscList'.
1159 | ||| If the list contains more than one value for the same key, the last value
1160 | ||| for the key is retained.
1161 | export
1162 | fromList : DOrd k => List (DSum k f) -> DMap k f
1163 | fromList xs
1164 |   = foldl ins empty xs
1165 |   where
1166 |     ins : DMap k f -> DSum k f -> DMap k f
1167 |     ins t (k :=> x) = insert k x t
1168 |
1169 | ||| *O(n*log n)*. Build a map from a list of key/value pairs with a combining function. See also 'fromAscListWithKey'.
1170 | export
1171 | fromListWithKey : DOrd k => ({0 v : a} -> k v -> f v -> f v -> f v) -> List (DSum k f) -> DMap k f
1172 | fromListWithKey func xs
1173 |   = foldl (ins func) empty xs
1174 |   where
1175 |     ins : ({0 v : a} -> k v -> f v -> f v -> f v) -> DMap k f -> DSum k f -> DMap k f
1176 |     ins func t (k :=> x) = insertWithKey func k x t
1177 |
1178 | ||| *O(n)*. Convert to an ascending list.
1179 | export
1180 | toAscList : DMap k f -> List (DSum k f)
1181 | toAscList t = foldrWithKey (\k => \x => \xs => (k :=> x) :: xs) [] t
1182 |
1183 | ||| *O(n)*. Convert to a list of key/value pairs.
1184 | export
1185 | toList : DMap k f -> List (DSum k f)
1186 | toList t = toAscList t
1187 |
1188 | ||| *O(n)*. Convert to a descending list.
1189 | export
1190 | toDescList : DMap k f -> List (DSum k f)
1191 | toDescList t  = foldlWithKey (\xs => \k => \x => (k :=> x) :: xs) [] t
1192 |
1193 | {--------------------------------------------------------------------
1194 |   Building trees from ascending/descending lists can be done in linear time.
1195 |
1196 |   Note that if [xs] is ascending that:
1197 |     fromAscList xs       == fromList xs
1198 |     fromAscListWith f xs == fromListWith f xs
1199 | --------------------------------------------------------------------}
1200 |
1201 | ||| *O(n)*. Build a map from an ascending list of distinct elements in linear time.
1202 | ||| *The precondition is not checked.*
1203 | export
1204 | fromDistinctAscList : List (DSum k f) -> DMap k f
1205 | fromDistinctAscList xs = build const (cast $ length xs) xs
1206 |   where
1207 |     -- 1) use continutations so that we use heap space instead of stack space.
1208 |     -- 2) special case for n==5 to build bushier trees.
1209 |
1210 |     buildB : DMap k f -> k v -> f v -> (DMap k f -> a -> b) -> DMap k f -> a -> b
1211 |     buildB l k x c r zs = c (bin k x l r) zs
1212 |
1213 |     mutual
1214 |       build : (DMap k f -> List (DSum k f) -> b) -> Int -> List (DSum k f) -> b
1215 |       build c 0 xs' = c Tip xs'
1216 |       build c 5 xs' = case xs' of
1217 |         ((k1 :=> x1) :: (k2 :=> x2) :: (k3 :=> x3) :: (k4 :=> x4) :: (k5 :=> x5) :: xx)
1218 |           => c (bin k4 x4 (bin k2 x2 (singleton k1 x1) (singleton k3 x3)) (singleton k5 x5)) xx
1219 |         _ => error "fromDistinctAscList build"
1220 |       build c n xs' = build (buildR nr c) nl xs'
1221 |         where
1222 |           nl, nr : Int
1223 |           nl = n `div` 2
1224 |           nr = n - nl - 1
1225 |
1226 |       buildR : Int -> (DMap k f -> List (DSum k f) -> b) -> DMap k f -> List (DSum k f) -> b
1227 |       buildR n c l ((k :=> x) :: ys) = build (buildB l k x c) n ys
1228 |       buildR _ _ _ []                = error "fromDistinctAscList buildR []"
1229 |
1230 |
1231 |
1232 | ||| *O(n)*. Build a map from an ascending list in linear time with a
1233 | ||| combining function for equal keys.
1234 | ||| *The precondition (input list is ascending) is not checked.*
1235 | export
1236 | fromAscListWithKey : (impl : DEq k) => ({0 v : a} -> k v -> f v -> f v -> f v) -> List (DSum k f) -> DMap k f
1237 | fromAscListWithKey func xs = fromDistinctAscList (combineEq func xs)
1238 |   where
1239 |     combineEq' : ({0 v : a} -> k v -> f v -> f v -> f v) -> DSum k f -> List (DSum k f) -> List (DSum k f)
1240 |     combineEq' f z [] = [z]
1241 |     combineEq' f z@(kz :=> zz) (x@(kx :=> xx) :: xs') = case deq kx kz @{impl} of
1242 |       Just Refl   => let yy = func kx xx zz in combineEq' f (kx :=> yy) xs'
1243 |       Nothing     => z :: combineEq' func x xs'
1244 |
1245 |     -- [combineEq f xs] combines equal elements with function [f] in an ordered list [xs]
1246 |     combineEq : ({0 v : a} -> k v -> f v -> f v -> f v) -> List (DSum k f) -> List (DSum k f)
1247 |     combineEq _ xs' = case xs' of
1248 |       []        => []
1249 |       [x]       => [x]
1250 |       (x :: xx) => combineEq' func x xx
1251 |
1252 |
1253 | ||| *O(n)*. Build a map from an ascending list in linear time.
1254 | ||| *The precondition (input list is ascending) is not checked.*
1255 | export
1256 | fromAscList : DEq k => List (DSum k f) -> DMap k f
1257 | fromAscList xs = fromAscListWithKey (\_ => \x => \_ => x) xs
1258 |
1259 | {--------------------------------------------------------------------
1260 |   Eq converts the tree to a list. In a lazy setting, this
1261 |   actually seems one of the faster methods to compare two trees
1262 |   and it is certainly the simplest :-)
1263 | --------------------------------------------------------------------}
1264 | --implementation (GEq k, Has' Eq k f) => Eq (DMap k f) where
1265 | export
1266 | implementation DEq k => DEq f => Eq (DMap k f) where
1267 |   t1 == t2 = (size t1 == size t2) && (toAscList t1 == toAscList t2)
1268 |
1269 |
1270 | {--------------------------------------------------------------------
1271 |   List variations
1272 | --------------------------------------------------------------------}
1273 |
1274 | ||| *O(n)*. Return all key/value pairs in the map in ascending key order.
1275 | export
1276 | assocs : DMap k f -> List (DSum k f)
1277 | assocs m = toList m
1278 |
1279 | ||| *O(n)*. Return all keys of the map in ascending order.
1280 | |||
1281 | ||| ```
1282 | ||| keys (fromList [k1 :=> v1, k2 :=> v2]) == [k1, k2]
1283 | ||| keys empty == []
1284 | ||| ```
1285 | export
1286 | keys : DMap k f -> List (Some k)
1287 | keys m = [MkSome k | (k :=> _) <- assocs m]
1288 |
1289 | {--------------------------------------------------------------------
1290 |   Mapping
1291 | --------------------------------------------------------------------}
1292 |
1293 | ||| *O(n)*. Map a function over all values in the map.
1294 | export
1295 | map : ({0 v : a} -> f v -> g v) -> DMap k f -> DMap k g
1296 | map func = go
1297 |   where
1298 |     go : DMap k f -> DMap k g
1299 |     go Tip = Tip
1300 |     go (Bin sx kx x l r) = Bin sx kx (func x) (go l) (go r)
1301 |
1302 | export
1303 | implementation DFunctor (DMap k) where
1304 |   dmap = map
1305 |
1306 | ||| *O(n)*.
1307 | ||| `'ffor' == 'flip' 'map'` except we cannot actually use
1308 | ||| 'flip' because of the lack of impredicative types.
1309 | export
1310 | ffor : DMap k f -> ({0 v : a} -> f v -> g v) -> DMap k g
1311 | ffor m f = map f m
1312 |
1313 | ||| *O(n)*. Map a function over all values in the map.
1314 | export
1315 | mapWithKey : ({0 v : a} -> k v -> f v -> g v) -> DMap k f -> DMap k g
1316 | mapWithKey func = go
1317 |   where
1318 |     go : DMap k f -> DMap k g
1319 |     go Tip = Tip
1320 |     go (Bin sx kx x l r) = Bin sx kx (func kx x) (go l) (go r)
1321 |
1322 | ||| *O(n)*.
1323 | ||| `'fforWithKey' == 'flip' 'mapWithKey'` except we cannot actually use
1324 | ||| 'flip' because of the lack of impredicative types.
1325 | export
1326 | fforWithKey : DMap k f -> ({0 v : a} -> k v -> f v -> g v) -> DMap k g
1327 | fforWithKey m f = mapWithKey f m
1328 |
1329 | ||| *O(n)*.
1330 | ||| `'traverseWithKey' f m == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)`
1331 | ||| That is, behaves exactly like a regular 'traverse' except that the traversing
1332 | ||| function also has access to the key associated with a value.
1333 | export
1334 | traverseWithKey_ : Applicative t => ({0 v : a} -> k v -> f v -> t ()) -> DMap k f -> t ()
1335 | traverseWithKey_ func = go
1336 |   where
1337 |     go : DMap k f -> t ()
1338 |     go Tip = pure ()
1339 |     go (Bin 1 k v _ _) = func k v
1340 |     go (Bin s k v l r) = go l *> func k v *> go r
1341 |
1342 | ||| *O(n)*.
1343 | ||| `'forWithKey' == 'flip' 'traverseWithKey'` except we cannot actually use
1344 | ||| 'flip' because of the lack of impredicative types.
1345 | export
1346 | forWithKey_ : Applicative t => DMap k f -> ({0 v : a} -> k v -> f v -> t ()) -> t ()
1347 | forWithKey_ m f = traverseWithKey_ f m
1348 |
1349 | ||| *O(n)*.
1350 | ||| `'traverseWithKey' f m == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)`
1351 | ||| That is, behaves exactly like a regular 'traverse' except that the traversing
1352 | ||| function also has access to the key associated with a value.
1353 | export
1354 | traverseWithKey : Applicative t => ({0 v : a} -> k v -> f v -> t (g v)) -> DMap k f -> t (DMap k g)
1355 | traverseWithKey func = go
1356 |   where
1357 |     go : DMap k f -> t (DMap k g)
1358 |     go Tip = pure Tip
1359 |     go (Bin 1 k v _ _) = (\v' => Bin 1 k v' Tip Tip) <$> func k v
1360 |     go (Bin s k v l r) = flip (Bin s k) <$> go l <*> func k v <*> go r
1361 |
1362 | ||| *O(n)*.
1363 | ||| `'forWithKey' == 'flip' 'traverseWithKey'` except we cannot actually use
1364 | ||| 'flip' because of the lack of impredicative types.
1365 | export
1366 | forWithKey : Applicative t => DMap k f -> ({0 v : a} -> k v -> f v -> t (g v)) -> t (DMap k g)
1367 | forWithKey m f = traverseWithKey f m
1368 |
1369 | ||| *O(n)*. The function 'mapAccumLWithKey' threads an accumulating
1370 | ||| argument through the map in ascending order of keys.
1371 | export
1372 | mapAccumLWithKey : ({0 v : a'} -> a -> k v -> f v -> (a, g v)) -> a -> DMap k f -> (a, DMap k g)
1373 | mapAccumLWithKey func = go
1374 |   where
1375 |     go : a -> DMap k f -> (a, DMap k g)
1376 |     go a Tip               = (a,Tip)
1377 |     go a (Bin sx kx x l r) =
1378 |                  let (a1, l') = go a l
1379 |                      (a2, x') = func a1 kx x
1380 |                      (a3, r') = go a2 r
1381 |                  in (a3, Bin sx kx x' l' r')
1382 |
1383 | ||| *O(n)*. The function 'mapAccumRWithKey' threads an accumulating
1384 | ||| argument through the map in descending order of keys.
1385 | export
1386 | mapAccumRWithKey : ({0 v : a'} -> a -> k v -> f v -> (a, g v)) -> a -> DMap k f -> (a, DMap k g)
1387 | mapAccumRWithKey func = go
1388 |   where
1389 |     go : a -> DMap k f -> (a, DMap k g)
1390 |     go a Tip = (a,Tip)
1391 |     go a (Bin sx kx x l r) =
1392 |                  let (a1, r') = go a r
1393 |                      (a2, x') = func a1 kx x
1394 |                      (a3, l') = go a2 l
1395 |                  in (a3, Bin sx kx x' l' r')
1396 |
1397 | ||| *O(n*log n)*.
1398 | ||| `'mapKeysWith' c f s` is the map obtained by applying `f` to each key of `s`.
1399 | |||
1400 | ||| The size of the result may be smaller if `f` maps two or more distinct
1401 | ||| keys to the same new key.  In this case the associated values will be
1402 | ||| combined using `c`.
1403 | export
1404 | mapKeysWith : DOrd k2
1405 |            => ({0 v : a} -> k2 v -> f v -> f v -> f v)
1406 |            -> ({0 v : a} -> k1 v -> k2 v) -> DMap k1 f -> DMap k2 f
1407 | mapKeysWith c func = fromListWithKey c . Prelude.map fFirst . toList
1408 |   where
1409 |     fFirst : DSum k1 f -> DSum k2 f
1410 |     fFirst (x :=> y) = (func x :=> y)
1411 |
1412 | ||| *O(n)*.
1413 | ||| `'mapKeysMonotonic' f s == 'mapKeys' f s`, but works only when `f`
1414 | ||| is strictly monotonic.
1415 | ||| That is, for any values `x` and `y`, if `x` < `y` then `f x` < `f y`.
1416 | ||| *The precondition is not checked.*
1417 | ||| Semi-formally, we have:
1418 | |||
1419 | ||| ```
1420 | ||| and [x < y ==> f x < f y | x <- ls, y <- ls]
1421 | |||                     ==> mapKeysMonotonic f s == mapKeys f s
1422 | |||     where ls = keys s
1423 | ||| ```
1424 | |||
1425 | ||| This means that `f` maps distinct original keys to distinct resulting keys.
1426 | ||| This function has better performance than 'mapKeys'.
1427 | export
1428 | mapKeysMonotonic : ({0 v : a} -> k1 v -> k2 v) -> DMap k1 f -> DMap k2 f
1429 | mapKeysMonotonic _ Tip = Tip
1430 | mapKeysMonotonic f (Bin sz k x l r) =
1431 |     Bin sz (f k) x (mapKeysMonotonic f l) (mapKeysMonotonic f r)
1432 |
1433 | {--------------------------------------------------------------------
1434 |   Ord
1435 | --------------------------------------------------------------------}
1436 |
1437 | export
1438 | implementation DOrd k => DOrd f => Ord (DMap k f) where
1439 |   compare m1 m2 = compare (toAscList m1) (toAscList m2)
1440 |
1441 | {-
1442 | {--------------------------------------------------------------------
1443 |   Read
1444 | --------------------------------------------------------------------}
1445 |
1446 | instance (GCompare k, GRead k, Has' Read k f) => Read (DMap k f) where
1447 |   readPrec = parens $ prec 10 $ do
1448 |     Ident "fromList" <- lexP
1449 |     xs <- readPrec
1450 |     return (fromList xs)
1451 |
1452 |   readListPrec = readListPrecDefault
1453 | -}
1454 |
1455 | {--------------------------------------------------------------------
1456 |   Show
1457 | --------------------------------------------------------------------}
1458 | export
1459 | implementation DShow k => DShow f => Show (DMap k f) where
1460 |   show m = "fromList " ++ show (toList m)
1461 |
1462 | private
1463 | showWide : Bool -> List (String) -> String -> String
1464 | showWide wide bars
1465 |   = if wide then showString (concat (reverse bars)) . showString "|\n"
1466 |             else id
1467 |
1468 | private
1469 | node : String
1470 | node = "+--"
1471 |
1472 | private
1473 | showsBars : List (String) -> ShowS
1474 | showsBars bars
1475 |   = case bars of
1476 |       [] => id
1477 |       (bar :: bars)  => showString (concat (reverse bars)) . showString node
1478 |
1479 | private
1480 | withBar, withEmpty : List (String) -> List (String)
1481 | withBar bars   = "|  " :: bars
1482 | withEmpty bars = "   " :: bars
1483 |
1484 | private
1485 | showsTreeHang : ({0 v : a} -> k v -> f v -> String) -> Bool -> List (String) -> DMap k f -> ShowS
1486 | showsTreeHang showelem wide bars t
1487 |   = case t of
1488 |       Tip => showsBars bars . showString "|\n"
1489 |       Bin _ kx x Tip Tip
1490 |           => showsBars bars . showString (showelem kx x) . showString "\n"
1491 |       Bin _ kx x l r
1492 |           => showsBars bars . showString (showelem kx x) . showString "\n" .
1493 |              showWide wide bars .
1494 |              showsTreeHang showelem wide (withBar bars) l .
1495 |              showWide wide bars .
1496 |              showsTreeHang showelem wide (withEmpty bars) r
1497 |
1498 | private
1499 | showsTree : ({0 v : a} -> k v -> f v -> String) -> Bool -> List (String) -> List (String) -> DMap k f -> ShowS
1500 | showsTree showelem wide lbars rbars t
1501 |   = case t of
1502 |       Tip => showsBars lbars . showString "|\n"
1503 |       Bin _ kx x Tip Tip
1504 |           => showsBars lbars . showString (showelem kx x) . showString "\n"
1505 |       Bin _ kx x l r
1506 |           => showsTree showelem wide (withBar rbars) (withEmpty rbars) r .
1507 |              showWide wide rbars .
1508 |              showsBars lbars . showString (showelem kx x) . showString "\n" .
1509 |              showWide wide lbars .
1510 |              showsTree showelem wide (withEmpty lbars) (withBar lbars) l
1511 |
1512 | ||| *O(n)*. The expression (`'showTreeWith' showelem hang wide map`) shows
1513 | ||| the tree that implements the map. Elements are shown using the `showElem` function. If `hang` is
1514 | ||| 'True', a *hanging* tree is shown otherwise a rotated tree is shown. If
1515 | ||| `wide` is 'True', an extra wide version is shown.
1516 | export
1517 | showTreeWith : ({0 v : a} -> k v -> f v -> String) -> Bool -> Bool -> DMap k f -> String
1518 | showTreeWith showelem hang wide t
1519 |   = if hang then (showsTreeHang showelem wide [] t) ""
1520 |             else (showsTree showelem wide [] [] t) ""
1521 |
1522 | ||| *O(n)*. Show the tree that implements the map. The tree is shown
1523 | ||| in a compressed, hanging format. See 'showTreeWith'.
1524 | export
1525 | showTree : DShow k => DShow f => DMap k f -> String
1526 | showTree m
1527 |   = showTreeWith showElem True False m
1528 |   where
1529 |     showElem : k v -> f v -> String
1530 |     showElem kx fx = show (kx :=> fx) {ty = DSum k f}
1531 |
1532 | {--------------------------------------------------------------------
1533 |   Assertions
1534 | --------------------------------------------------------------------}
1535 |
1536 | private
1537 | ordered : DOrd k => DMap k f -> Bool
1538 | ordered t
1539 |   = bounded (const True) (const True) t
1540 |   where
1541 |     bounded : (Some k -> Bool) -> (Some k -> Bool) -> DMap k f -> Bool
1542 |     bounded lo hi t'
1543 |       = case t' of
1544 |           Tip             => True
1545 |           Bin _ kx _ l r  => lo (MkSome kx)
1546 |                           && hi (MkSome kx)
1547 |                           && bounded lo (\s => (<) s (MkSome kx)) l
1548 |                           && bounded (\s => (>) s (MkSome kx)) hi r
1549 |
1550 | ||| Exported only for "Debug.QuickCheck"
1551 | private
1552 | balanced : DMap k f -> Bool
1553 | balanced t
1554 |   = case t of
1555 |       Tip            => True
1556 |       Bin _ _ _ l r  => (size l + size r <= 1 || (size l <= delta*size r && size r <= delta*size l)) &&
1557 |                         balanced l && balanced r
1558 |
1559 | private
1560 | validsize : DMap k f -> Bool
1561 | validsize t
1562 |   = (realsize t == Just (size t))
1563 |   where
1564 |     realsize : DMap k f -> Maybe Int
1565 |     realsize t'
1566 |       = case t' of
1567 |           Tip            => Just 0
1568 |           Bin sz _ _ l r => case (realsize l,realsize r) of
1569 |                             (Just n, Just m) => if n + m + 1 == sz then Just sz
1570 |                                                                    else Nothing
1571 |                             _                => Nothing
1572 |
1573 | ||| *O(n)*. Test if the internal map structure is valid.
1574 | export
1575 | valid : DOrd k => DMap k f -> Bool
1576 | valid t = balanced t && ordered t && validsize t
1577 |
1578 | {--------------------------------------------------------------------
1579 |   Arbitrary maps
1580 | --------------------------------------------------------------------}
1581 |
1582 | ||| Generates a map using a 'Range' to determine the size.
1583 | export
1584 | genDMap : DOrd k => Hedgehog.Range Nat -> Gen (DSum k v) -> Gen (DMap k v)
1585 | genDMap range gen = fromList <$> list range gen
1586 |