module Data.AVLTree
import Builtin
import Algebra.Relation.Equivalence
import Algebra.Relation.Preorder
import Algebra.Relation.Order
import Data.Either
import Data.Natural
import Data.Optional
import Data.PrimInteger
%default total
public export
data AVLTree : (o : Order t) => (t : Type) -> (height : Natural) -> (bounds : Optional (t, t)) -> Type where
Empty : AVLTree t Zero Nothing {o}
Node : AVLTree t leftHeight leftBounds {o}
-> (pivot : t)
-> AVLTree t rigthHeight rightBounds {o}
-> {auto heightCheck : diff leftHeight rightHeight `LTE` 1}
-- TODO: Figure out how to make Idris2 happy about this signature
-- -> {auto leftBoundOk : (optional leftBounds ((`LT` pivot) . Builtin.snd) Unit)}
-- -> {auto rightBoundOk : (optional rightBounds ((`GT` pivot) . Builtin.fst) Unit)}
-> AVLTree t
(Succesor $ max leftHeight rightHeight)
(Some (optional leftBounds (Builtin.fst) pivot, optional rightBounds (Builtin.snd) pivot))
{o}
public export
data NonEmpty : AVLTree t h b {o} -> Type where
IsNode : NonEmpty (Node _ _ _ @{o})
partial
insert : Order t => AVLTree t h b {o} -> (x : t)
-> Either
(AVLTree t h (Some (optional b (min x . Builtin.fst) x, optional b (max x . Builtin.snd) x)) {o})
(AVLTree t (Succesor h) (Some (optional b (min x . Builtin.fst) x, optional b (max x . Builtin.snd) x)) {o})
insert Empty x = Right $ Node Empty x Empty
insert (Node leftTree pivot rightTree {leftHeight} {rightHeight}) x =
case compare x pivot of
(Left equiv) => Left $ ?hole1
(Right (Left lt)) => ?hole2
(Right (Right gt)) => ?hole3