------------------------------------------------------------------------
-- 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