section ‹Tries via Functions› theory Trie_Fun imports Set_Specs begin text ‹A trie where each node maps a key to sub-tries via a function. Nice abstract model. Not efficient because of the function space.› datatype 'a trie = Nd bool "'a ⇒ 'a trie option" fun isin :: "'a trie ⇒ 'a list ⇒ bool" where "isin (Nd b m) [] = b" | "isin (Nd b m) (k # xs) = (case m k of None ⇒ False | Some t ⇒ isin t xs)" fun insert :: "('a::linorder) list ⇒ 'a trie ⇒ 'a trie" where "insert [] (Nd b m) = Nd True m" | "insert (x#xs) (Nd b m) = Nd b (m(x := Some(insert xs (case m x of None ⇒ Nd False (λ_. None) | Some t ⇒ t))))" fun delete :: "('a::linorder) list ⇒ 'a trie ⇒ 'a trie" where "delete [] (Nd b m) = Nd False m" | "delete (x#xs) (Nd b m) = Nd b (case m x of None ⇒ m | Some t ⇒ m(x := Some(delete xs t)))" text ‹The actual definition of ‹set› is a bit cryptic but canonical, to enable primrec to prove termination:› primrec set :: "'a trie ⇒ 'a list set" where "set (Nd b m) = (if b then {[]} else {}) ∪ (⋃a. case (map_option set o m) a of None ⇒ {} | Some t ⇒ (#) a ` t)" text ‹This is the more human-readable version:› lemma set_Nd: "set (Nd b m) = (if b then {[]} else {}) ∪ (⋃a. case m a of None ⇒ {} | Some t ⇒ (#) a ` set t)" by (auto simp: split: option.splits) lemma isin_set: "isin t xs = (xs ∈ set t)" apply(induction t xs rule: isin.induct) apply (auto split: option.split) done lemma set_insert: "set (insert xs t) = set t ∪ {xs}" proof(induction xs t rule: insert.induct) case 1 thus ?case by simp next case 2 thus ?case apply(simp) apply(subst set_eq_iff) apply(auto split!: if_splits option.splits) apply fastforce by (metis imageI option.sel) qed lemma set_delete: "set (delete xs t) = set t - {xs}" proof(induction xs t rule: delete.induct) case 1 thus ?case by (force split: option.splits) next case 2 thus ?case apply (auto simp add: image_iff split!: if_splits option.splits) apply blast apply (metis insertE insertI2 insert_Diff_single option.inject) apply blast by (metis insertE insertI2 insert_Diff_single option.inject) qed interpretation S: Set where empty = "Nd False (λ_. None)" and isin = isin and insert = insert and delete = delete and set = set and invar = "λ_. True" proof (standard, goal_cases) case 1 show ?case by (simp) next case 2 thus ?case by(simp add: isin_set) next case 3 thus ?case by(simp add: set_insert) next case 4 thus ?case by(simp add: set_delete) qed (rule TrueI)+ end