forked from leanprover/lean4
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPrefixTree.lean
110 lines (88 loc) · 3.72 KB
/
PrefixTree.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/-
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
import Lean.Data.RBMap
namespace Lean
/- Similar to trie, but for arbitrary keys -/
inductive PrefixTreeNode (α : Type u) (β : Type v) where
| Node : Option β → RBNode α (fun _ => PrefixTreeNode α β) → PrefixTreeNode α β
instance : Inhabited (PrefixTreeNode α β) where
default := PrefixTreeNode.Node none RBNode.leaf
namespace PrefixTreeNode
def empty : PrefixTreeNode α β :=
PrefixTreeNode.Node none RBNode.leaf
@[specialize]
partial def insert (t : PrefixTreeNode α β) (cmp : α → α → Ordering) (k : List α) (val : β) : PrefixTreeNode α β :=
let rec insertEmpty (k : List α) : PrefixTreeNode α β :=
match k with
| [] => PrefixTreeNode.Node (some val) RBNode.leaf
| k :: ks =>
let t := insertEmpty ks
PrefixTreeNode.Node none (RBNode.singleton k t)
let rec loop
| PrefixTreeNode.Node _ m, [] =>
PrefixTreeNode.Node (some val) m -- overrides old value
| PrefixTreeNode.Node v m, k :: ks =>
let t := match RBNode.find cmp m k with
| none => insertEmpty ks
| some t => loop t ks
PrefixTreeNode.Node v (RBNode.insert cmp m k t)
loop t k
@[specialize]
partial def find? (t : PrefixTreeNode α β) (cmp : α → α → Ordering) (k : List α) : Option β :=
let rec loop
| PrefixTreeNode.Node val _, [] => val
| PrefixTreeNode.Node _ m, k :: ks =>
match RBNode.find cmp m k with
| none => none
| some t => loop t ks
loop t k
@[specialize]
partial def foldMatchingM [Monad m] (t : PrefixTreeNode α β) (cmp : α → α → Ordering) (k : List α) (init : σ) (f : β → σ → m σ) : m σ :=
let rec fold : PrefixTreeNode α β → σ → m σ
| PrefixTreeNode.Node b? n, d => do
let d ← match b? with
| none => pure d
| some b => f b d
n.foldM (init := d) fun d _ t => fold t d
let rec find : List α → PrefixTreeNode α β → σ → m σ
| [], t, d => fold t d
| k::ks, PrefixTreeNode.Node _ m, d =>
match RBNode.find cmp m k with
| none => pure init
| some t => find ks t d
find k t init
inductive WellFormed (cmp : α → α → Ordering) : PrefixTreeNode α β → Prop where
| emptyWff : WellFormed cmp empty
| insertWff : WellFormed cmp t → WellFormed cmp (insert t cmp k val)
end PrefixTreeNode
def PrefixTree (α : Type u) (β : Type v) (cmp : α → α → Ordering) : Type (max u v) :=
{ t : PrefixTreeNode α β // t.WellFormed cmp }
open PrefixTreeNode
def PrefixTree.empty : PrefixTree α β p :=
⟨PrefixTreeNode.empty, WellFormed.emptyWff⟩
instance : Inhabited (PrefixTree α β p) where
default := PrefixTree.empty
instance : EmptyCollection (PrefixTree α β p) where
emptyCollection := PrefixTree.empty
@[inline]
def PrefixTree.insert (t : PrefixTree α β p) (k : List α) (v : β) : PrefixTree α β p :=
⟨t.val.insert p k v, WellFormed.insertWff t.property⟩
@[inline]
def PrefixTree.find? (t : PrefixTree α β p) (k : List α) : Option β :=
t.val.find? p k
@[inline]
def PrefixTree.foldMatchingM [Monad m] (t : PrefixTree α β p) (k : List α) (init : σ) (f : β → σ → m σ) : m σ :=
t.val.foldMatchingM p k init f
@[inline]
def PrefixTree.foldM [Monad m] (t : PrefixTree α β p) (init : σ) (f : β → σ → m σ) : m σ :=
t.foldMatchingM [] init f
@[inline]
def PrefixTree.forMatchingM [Monad m] (t : PrefixTree α β p) (k : List α) (f : β → m Unit) : m Unit :=
t.val.foldMatchingM p k () (fun b _ => f b)
@[inline]
def PrefixTree.forM [Monad m] (t : PrefixTree α β p) (f : β → m Unit) : m Unit :=
t.forMatchingM [] f
end Lean