------------------------------------------------------------------------
-- The Agda standard library
--
-- Some examples showing how the AVL tree module can be used
------------------------------------------------------------------------
{-# OPTIONS --cubical-compatible --safe #-}
module README.Data.Tree.AVL where
------------------------------------------------------------------------
-- Setup
-- AVL trees are defined in Data.Tree.AVL.
import Data.Tree.AVL
-- This module is parametrised by keys, which have to form a (strict)
-- total order, and values, which are indexed by keys. Let us use
-- natural numbers as keys and vectors of strings as values.
open import Data.Nat.Properties using (<-strictTotalOrder)
open import Data.Product.Base as Product using (_,_; _,′_)
open import Data.String.Base using (String)
open import Data.Vec.Base using (Vec; _∷_; [])
open import Relation.Binary.PropositionalEquality
open Data.Tree.AVL <-strictTotalOrder renaming (Tree to Tree′)
Tree = Tree′ (MkValue (Vec String) (subst (Vec String)))
-- The first argument to `MkValue` should be a function from a key
-- (a `ℕ` in this case) to a value type (a `String` vector type).
-- Since `(Vec String)` is missing `Vec`'s second parameter, a `ℕ`,
-- it's equivalent to `λ n → Vec String n`.
-- The second argument to `MkValue` is a function that can accept
-- a proof that two keys are equal, and then substitute a unique key
-- for an equivalent key that is passed in.  Applying `subst` to the
-- key-to-value-type function passed as `MkValue`'s first argument is
-- a normal way to create such a function.
-- Note that there is no need to define the type of keys separately:
-- passing a key-to-value-type function to `MkValue` and providing
-- the result of `MkValue` to `Data.Tree.AVL.Tree` is enough.
------------------------------------------------------------------------
-- Construction of trees
-- Some values.
v₁  = "cepa" ∷ []
v₁′ = "depa" ∷ []
v₂  = "apa" ∷ "bepa" ∷ []
-- Empty and singleton trees.
t₀ : Tree
t₀ = empty
t₁ : Tree
t₁ = singleton 2 v₂
-- Insertion of a key-value pair into a tree.
t₂ = insert 1 v₁ t₁
-- If you insert a key-value pair and the key already exists in the
-- tree, then the old value is thrown away.
t₂′ = insert 1 v₁′ t₂
-- Deletion of the mapping for a certain key.
t₃ = delete 2 t₂
-- Conversion of a list of key-value mappings to a tree.
open import Data.List.Base using (_∷_; [])
t₄ : Tree
t₄ = fromList ((2 , v₂) ∷ (1 , v₁) ∷ [])
------------------------------------------------------------------------
-- Queries
-- Let us formulate queries as unit tests.
open import Relation.Binary.PropositionalEquality using (_≡_; refl)
-- Searching for a key.
open import Data.Bool.Base using (true; false)
open import Data.Maybe.Base as Maybe using (just; nothing)
q₀ : lookup t₂ 2 ≡ just v₂
q₀ = refl
q₁ : lookup t₃ 2 ≡ nothing
q₁ = refl
q₂ : (3 ∈? t₂) ≡ false
q₂ = refl
q₃ : (1 ∈? t₄) ≡ true
q₃ = refl
-- Turning a tree into a sorted list of key-value pairs.
q₄ : toList t₁ ≡ (2 , v₂) ∷ []
q₄ = refl
q₅ : toList t₂ ≡ (1 , v₁) ∷ (2 , v₂) ∷ []
q₅ = refl
q₅′ : toList t₂′ ≡ (1 , v₁′) ∷ (2 , v₂) ∷ []
q₅′ = refl
------------------------------------------------------------------------
-- Views
-- Partitioning a tree into the smallest element plus the rest, or the
-- largest element plus the rest.
open import Function.Base using (id)
v₆ : headTail t₀ ≡ nothing
v₆ = refl
v₇ : Maybe.map (Product.map₂ toList) (headTail t₂) ≡
     just ((1 , v₁) , ((2 , v₂) ∷ []))
v₇ = refl
v₈ : initLast t₀ ≡ nothing
v₈ = refl
v₉ : Maybe.map (Product.map₁ toList) (initLast t₄) ≡
     just (((1 , v₁) ∷ []) ,′ (2 , v₂))
v₉ = refl
------------------------------------------------------------------------
-- Further reading
-- Variations of the AVL tree module are available:
-- • Finite maps in which types of values don't depend on keys.
import Data.Tree.AVL.Map
-- • Finite maps with indexed keys and values.
import Data.Tree.AVL.IndexedMap
-- • Finite sets.
import Data.Tree.AVL.Sets