feat(library/init/lean): add SMap for implementing Environment
This commit is contained in:
parent
8c68251b72
commit
9e246b365e
2 changed files with 75 additions and 0 deletions
59
library/init/lean/smap.lean
Normal file
59
library/init/lean/smap.lean
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/-
|
||||
Copyright (c) 2019 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import init.data.hashmap init.data.rbmap
|
||||
universes u v w w'
|
||||
|
||||
namespace Lean
|
||||
|
||||
/- Staged map for implementing the Environment. The idea is to store
|
||||
imported entries into a hashtable and local entries into a red-black tree.
|
||||
|
||||
Hypotheses:
|
||||
- The number of entries (i.e., declarations) coming from imported files is much bigger than
|
||||
the number of entries in the current file.
|
||||
- HashMap is faster than RBMap.
|
||||
- When we are reading imported files, we have exclusive access to the map, and efficient
|
||||
destructive updates are performed.
|
||||
|
||||
Remarks:
|
||||
- We never remove declarations from the Environment. In principle, we could support
|
||||
deletion by using `(RBMap α (Option β) lt)` where the value `none` would indicate
|
||||
that an entry was "removed" from the hashtable.
|
||||
- We do not need additional bookkeeping for extracting the local entries.
|
||||
-/
|
||||
structure SMap (α : Type u) (β : Type v) (lt : α → α → Bool) [HasBeq α] [Hashable α] :=
|
||||
(stage₁ : Bool := true)
|
||||
(map₁ : HashMap α β := {})
|
||||
(map₂ : RBMap α β lt := {})
|
||||
|
||||
namespace SMap
|
||||
variables {α : Type u} {β : Type v} {lt : α → α → Bool} [HasBeq α] [Hashable α]
|
||||
|
||||
def empty : SMap α β lt := {}
|
||||
instance : HasEmptyc (SMap α β lt) := ⟨SMap.empty⟩
|
||||
|
||||
@[specialize] def insert : SMap α β lt → α → β → SMap α β lt
|
||||
| ⟨true, m₁, m₂⟩ k v := ⟨true, m₁.insert k v, m₂⟩
|
||||
| ⟨false, m₁, m₂⟩ k v := ⟨false, m₁, m₂.insert k v⟩
|
||||
|
||||
@[specialize] def find : SMap α β lt → α → Option β
|
||||
| ⟨true, m₁, _⟩ k := m₁.find k
|
||||
| ⟨false, m₁, m₂⟩ k := (m₂.find k).orelse (m₁.find k)
|
||||
|
||||
@[specialize] def contains : SMap α β lt → α → Bool
|
||||
| ⟨true, m₁, _⟩ k := m₁.contains k
|
||||
| ⟨false, m₁, m₂⟩ k := m₂.contains k || m₁.contains k
|
||||
|
||||
/- Move from stage 1 into stage 2. -/
|
||||
def switch (m : SMap α β lt) : SMap α β lt :=
|
||||
{ stage₁ := false, .. m }
|
||||
|
||||
@[inline] def foldStage2 {σ : Type w} (f : σ → α → β → σ) (s : σ) (m : SMap α β lt) : σ :=
|
||||
m.map₂.fold f s
|
||||
|
||||
end SMap
|
||||
end Lean
|
||||
16
tests/playground/smap.lean
Normal file
16
tests/playground/smap.lean
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import init.lean.smap
|
||||
|
||||
abbrev Map : Type := Lean.SMap Nat Bool (λ a b, a < b)
|
||||
|
||||
def test1 (n₁ n₂ : Nat) : IO Unit :=
|
||||
let m : Map := {} in
|
||||
let m := n₁.for (λ i (m : Map), m.insert i (i % 2 == 0)) m in
|
||||
let m := m.switch in
|
||||
let m := n₂.for (λ i (m : Map), m.insert (i+n₁) (i % 3 == 0)) m in
|
||||
do
|
||||
n₁.mfor $ λ i, IO.println (i, (m.find i)),
|
||||
n₂.mfor $ λ i, IO.println (i+n₁, (m.find (i+n₁))),
|
||||
IO.println (m.foldStage2 (λ kvs k v, (k, v)::kvs) [])
|
||||
|
||||
def main (xs : List String) : IO Unit :=
|
||||
test1 xs.head.toNat xs.tail.head.toNat
|
||||
Loading…
Add table
Reference in a new issue