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 = {!!}