module BSTskel where {--- Example of Dependently-typed program verfication. Inspired by Bove & Dyber, Dependent Types at Work. ---} open import Data.Nat open import Data.Bool hiding (_≟_) open import Data.Unit hiding (_≤_;_≤?_;_≟_;total) open import Data.Product open import Data.Empty open import Data.Sum open import Relation.Nullary open import Relation.Binary -- Some Properties of ≤ for natural numbers trans : Transitive _≤_ trans z≤n _ = z≤n trans (s≤s m≤n) (s≤s n≤o) = s≤s (trans m≤n n≤o) ≤-refl : forall {n} -> n ≤ n ≤-refl {zero} = z≤n ≤-refl {suc m} = s≤s (≤-refl {m}) total : ∀ ( m n : ℕ) -> m ≤ n ⊎ n ≤ m total zero _ = inj₁ z≤n total _ zero = inj₂ z≤n total (suc m) (suc n) with total m n ... | inj₁ m≤n = inj₁ (s≤s m≤n) ... | inj₂ n≤m = inj₂ (s≤s n≤m) -- A binary search tree that enforces the BST invariant---all vals -- on the left subtree are greater-eq than the current val, which -- is greater-eq than all vals on the right. mutual data BSTree : Set where leaf : BSTree node : (a : ℕ) -> (l : BSTree) -> ( r : BSTree) -> l >=T a -> r <=T a -> BSTree -- all elts in tree >= a (actually just looking at right spine (min)) _>=T_ : BSTree -> ℕ -> Set leaf >=T a = ⊤ (node x l r _ _) >=T a = (a ≤ x) × (r >=T a) -- all elts in tree <= a (actually just looking at left spine (max)) _<=T_ : BSTree -> ℕ -> Set leaf <=T a = ⊤ (node x l r _ _) <=T a = (x ≤ a) × (l <=T a) -- Our two relations are transitive trans-<=T : forall {m n} -> (r : BSTree) -> r <=T m -> m ≤ n -> r <=T n trans-<=T leaf tt q = tt trans-<=T (node n' l r p1 p2) (q11 , q12) q2 = trans q11 q2 , trans-<=T l q12 q2 trans->=T : forall {m n} -> (r : BSTree) -> r >=T m -> n ≤ m -> r >=T n trans->=T = {!!} -- determine whether an element is in the tree lookup : BSTree -> ℕ -> Bool lookup leaf n = false lookup (node m l r p1 p2) n with m ≟ n ... | yes _ = true ... | no _ with total m n ... | inj₁ _ = lookup r n ... | inj₂ _ = lookup l n -- insert a new value in the tree mutual insert : BSTree -> ℕ -> BSTree insert leaf n = node n leaf leaf tt tt insert (node m l r p1 p2) n with total m n ... | inj₁ q = node m (insert l n) r (ins-geqT l p1 q) p2 ... | inj₂ q = node m l (insert r n) p1 {!!} ins-geqT : { n x : ℕ } -> (t : BSTree) -> t >=T x -> x ≤ n -> insert t n >=T x ins-geqT leaf q1 q2 = q2 , _ ins-geqT {n} (node m l r p1 p2) q1 q2 with total m n ... | inj₁ q = q1 ... | inj₂ q = proj₁ q1 , ins-geqT r (proj₂ q1) q2 -- predicate on whether a tree is a node or leaf isNode : BSTree -> Set isNode (node _ _ _ _ _) = ⊤ isNode leaf = ⊥ -- find the minimum element of (non-empty) trees min : (n : BSTree) -> isNode n -> ℕ min = {!!} -- Given a tree that is not a leaf, delete its minimum -- element and return the new tree delete-min : (n : BSTree) -> isNode n -> BSTree delete-min = {!!} -- HINT: Important lemma(s) for BST deletion -- deleting the minimum from a tree produces a tree where every node -- is greater-eq than that minimum min-l : forall {n l r p1 p2} -> delete-min (node n l r p1 p2) tt >=T min (node n l r p1 p2) tt min-l = {!!} -- If a tree is geq m, then m is less than the minimum of the tree min-geq : (t : BSTree) -> (p : isNode t) -> (m : ℕ) -> t >=T m -> m ≤ min t p min-geq = {!!} -- BST deletion delete : BSTree -> ℕ -> BSTree delete = {!!}