{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

-- |
-- Module      : Data.Tree.AVL.Extern.Delete
-- Description : Deletion algorithm over ITree trees
-- Copyright   : (c) Nicolás Rodríguez, 2021
-- License     : GPL-3
-- Maintainer  : Nicolás Rodríguez
-- Stability   : experimental
-- Portability : POSIX
--
-- Implementation of the deletion algorithm over ITree trees for
-- externalist AVL trees.
module Data.Tree.AVL.Extern.Delete
  ( MaxKeyDeletable (MaxKeyDelete, maxKeyDelete),
    Deletable (Delete, delete),
    Deletable' (Delete'),
  )
where

import Data.Proxy (Proxy (Proxy))
import Data.Tree.AVL.Extern.Balance (Balanceable (Balance, balance))
import Data.Tree.BST.Extern.Delete (Maxable (MaxKey, MaxValue, maxValue))
import Data.Tree.ITree
  ( ITree (EmptyITree, ForkITree),
    Tree (EmptyTree, ForkTree),
  )
import Data.Tree.Node (Node, mkNode)
import GHC.TypeNats (CmpNat, Nat)
import Prelude (Ordering (EQ, GT, LT), Show, ($))

-- | This type class provides the functionality to delete the node with maximum key value
-- in a tree @t@ without checking any structural invariant (key ordering or height balance).
-- The deletion is defined at the value level and the type level, and is performed
-- as if the tree is an `Data.Tree.AVL.Extern.Constructors.AVL`; the verification of the @AVL@ restrictions is performed after the deletion.
class MaxKeyDeletable (t :: Tree) where
  type MaxKeyDelete (t :: Tree) :: Tree
  maxKeyDelete ::
    (t ~ 'ForkTree l (Node n a1) r) =>
    ITree t ->
    ITree (MaxKeyDelete t)

instance MaxKeyDeletable 'EmptyTree where
  type MaxKeyDelete 'EmptyTree = 'EmptyTree
  maxKeyDelete :: forall (l :: Tree) (n :: Nat) a1 (r :: Tree).
('EmptyTree ~ 'ForkTree l (Node n a1) r) =>
ITree 'EmptyTree -> ITree (MaxKeyDelete 'EmptyTree)
maxKeyDelete ITree 'EmptyTree
_ = ITree 'EmptyTree
ITree (MaxKeyDelete 'EmptyTree)
EmptyITree

instance MaxKeyDeletable ('ForkTree l (Node n a1) 'EmptyTree) where
  type MaxKeyDelete ('ForkTree l (Node n a1) 'EmptyTree) = l
  maxKeyDelete :: forall (l :: Tree) (n :: Nat) a1 (r :: Tree).
('ForkTree l (Node n a1) 'EmptyTree ~ 'ForkTree l (Node n a1) r) =>
ITree ('ForkTree l (Node n a1) 'EmptyTree)
-> ITree (MaxKeyDelete ('ForkTree l (Node n a1) 'EmptyTree))
maxKeyDelete (ForkITree ITree l
l Node n a
_ ITree r
_) = ITree l
ITree (MaxKeyDelete ('ForkTree l (Node n a1) 'EmptyTree))
l

instance
  ( r ~ 'ForkTree rl (Node rn ra) rr,
    MaxKeyDeletable r,
    Balanceable ('ForkTree l (Node n a1) (MaxKeyDelete r))
  ) =>
  MaxKeyDeletable ('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr))
  where
  type
    MaxKeyDelete ('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr)) =
      Balance ('ForkTree l (Node n a1) (MaxKeyDelete ('ForkTree rl (Node rn ra) rr)))
  maxKeyDelete :: forall (l :: Tree) (n :: Nat) a1 (r :: Tree).
('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr)
 ~ 'ForkTree l (Node n a1) r) =>
ITree ('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr))
-> ITree
     (MaxKeyDelete
        ('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr)))
maxKeyDelete (ForkITree ITree l
l Node n a
node ITree r
r) =
    ITree
  ('ForkTree
     l (Node n a) (MaxKeyDelete ('ForkTree rl (Node rn ra) rr)))
-> ITree
     (Balance
        ('ForkTree
           l (Node n a) (MaxKeyDelete ('ForkTree rl (Node rn ra) rr))))
forall (t :: Tree). Balanceable t => ITree t -> ITree (Balance t)
balance (ITree
   ('ForkTree
      l (Node n a) (MaxKeyDelete ('ForkTree rl (Node rn ra) rr)))
 -> ITree
      (Balance
         ('ForkTree
            l (Node n a) (MaxKeyDelete ('ForkTree rl (Node rn ra) rr)))))
-> ITree
     ('ForkTree
        l (Node n a) (MaxKeyDelete ('ForkTree rl (Node rn ra) rr)))
-> ITree
     (Balance
        ('ForkTree
           l (Node n a) (MaxKeyDelete ('ForkTree rl (Node rn ra) rr))))
forall a b. (a -> b) -> a -> b
$ ITree l
-> Node n a
-> ITree (MaxKeyDelete ('ForkTree rl (Node rn ra) rr))
-> ITree
     ('ForkTree
        l (Node n a) (MaxKeyDelete ('ForkTree rl (Node rn ra) rr)))
forall a (l :: Tree) (n :: Nat) (r :: Tree).
Show a =>
ITree l -> Node n a -> ITree r -> ITree ('ForkTree l (Node n a) r)
ForkITree ITree l
l Node n a
node (ITree r -> ITree (MaxKeyDelete r)
forall (t :: Tree) (l :: Tree) (n :: Nat) a1 (r :: Tree).
(MaxKeyDeletable t, t ~ 'ForkTree l (Node n a1) r) =>
ITree t -> ITree (MaxKeyDelete t)
maxKeyDelete ITree r
r)

-- | This type class provides the functionality to delete the node with key @x@
-- in a tree @t@ without checking any structural invariant (key ordering or height balance).
-- The deletion is defined at the value level and the type level, and is performed
-- as if the tree is a `Data.Tree.AVL.Extern.Constructors.AVL`; the verification of the @AVL@ restrictions is performed after the deletion.
class Deletable (x :: Nat) (t :: Tree) where
  type Delete (x :: Nat) (t :: Tree) :: Tree

  -- | Delete the node with the given key.
  -- If the key is not in the tree, return the same tree.
  delete :: Proxy x -> ITree t -> ITree (Delete x t)

instance Deletable x 'EmptyTree where
  type Delete x 'EmptyTree = 'EmptyTree
  delete :: Proxy x -> ITree 'EmptyTree -> ITree (Delete x 'EmptyTree)
delete Proxy x
_ ITree 'EmptyTree
_ = ITree 'EmptyTree
ITree (Delete x 'EmptyTree)
EmptyITree

instance
  ( o ~ CmpNat x n,
    Deletable' x ('ForkTree l (Node n a1) r) o
  ) =>
  Deletable x ('ForkTree l (Node n a1) r)
  where
  type Delete x ('ForkTree l (Node n a1) r) = Delete' x ('ForkTree l (Node n a1) r) (CmpNat x n)
  delete :: Proxy x
-> ITree ('ForkTree l (Node n a1) r)
-> ITree (Delete x ('ForkTree l (Node n a1) r))
delete Proxy x
px ITree ('ForkTree l (Node n a1) r)
t = Proxy x
-> ITree ('ForkTree l (Node n a1) r)
-> Proxy o
-> ITree (Delete' x ('ForkTree l (Node n a1) r) o)
forall (x :: Nat) (t :: Tree) (o :: Ordering).
Deletable' x t o =>
Proxy x -> ITree t -> Proxy o -> ITree (Delete' x t o)
delete' Proxy x
px ITree ('ForkTree l (Node n a1) r)
t (Proxy o
forall {k} (t :: k). Proxy t
Proxy :: Proxy o)

-- | This type class provides the functionality to delete a node with key @x@
-- in a non empty tree @t@ without checking any structural invariant (key ordering or height balance).
-- It's only used by the 'Deletable' type class and it has one extra parameter @o@,
-- which is the type level comparison of @x@ with the key value of the root node.
-- The @o@ parameter guides the deletion.
class Deletable' (x :: Nat) (t :: Tree) (o :: Ordering) where
  type Delete' (x :: Nat) (t :: Tree) (o :: Ordering) :: Tree
  delete' :: Proxy x -> ITree t -> Proxy o -> ITree (Delete' x t o)

instance Deletable' x ('ForkTree 'EmptyTree (Node n a1) 'EmptyTree) 'EQ where
  type Delete' x ('ForkTree 'EmptyTree (Node n a1) 'EmptyTree) 'EQ = 'EmptyTree
  delete' :: Proxy x
-> ITree ('ForkTree 'EmptyTree (Node n a1) 'EmptyTree)
-> Proxy 'EQ
-> ITree
     (Delete' x ('ForkTree 'EmptyTree (Node n a1) 'EmptyTree) 'EQ)
delete' Proxy x
_ ITree ('ForkTree 'EmptyTree (Node n a1) 'EmptyTree)
_ Proxy 'EQ
_ = ITree 'EmptyTree
ITree (Delete' x ('ForkTree 'EmptyTree (Node n a1) 'EmptyTree) 'EQ)
EmptyITree

instance Deletable' x ('ForkTree 'EmptyTree (Node n a1) ('ForkTree rl (Node rn ra) rr)) 'EQ where
  type Delete' x ('ForkTree 'EmptyTree (Node n a1) ('ForkTree rl (Node rn ra) rr)) 'EQ = 'ForkTree rl (Node rn ra) rr
  delete' :: Proxy x
-> ITree
     ('ForkTree 'EmptyTree (Node n a1) ('ForkTree rl (Node rn ra) rr))
-> Proxy 'EQ
-> ITree
     (Delete'
        x
        ('ForkTree 'EmptyTree (Node n a1) ('ForkTree rl (Node rn ra) rr))
        'EQ)
delete' Proxy x
_ (ForkITree ITree l
_ Node n a
_ ITree r
r) Proxy 'EQ
_ = ITree r
ITree
  (Delete'
     x
     ('ForkTree 'EmptyTree (Node n a1) ('ForkTree rl (Node rn ra) rr))
     'EQ)
r

instance Deletable' x ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) 'EmptyTree) 'EQ where
  type Delete' x ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) 'EmptyTree) 'EQ = 'ForkTree ll (Node ln la) lr
  delete' :: Proxy x
-> ITree
     ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) 'EmptyTree)
-> Proxy 'EQ
-> ITree
     (Delete'
        x
        ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) 'EmptyTree)
        'EQ)
delete' Proxy x
_ (ForkITree ITree l
l Node n a
_ ITree r
_) Proxy 'EQ
_ = ITree l
ITree
  (Delete'
     x
     ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) 'EmptyTree)
     'EQ)
l

instance
  ( l ~ 'ForkTree ll (Node ln la) lr,
    r ~ 'ForkTree rl (Node rn ra) rr,
    Show (MaxValue l),
    MaxKeyDeletable l,
    Maxable l,
    Balanceable ('ForkTree (MaxKeyDelete l) (Node (MaxKey l) (MaxValue l)) r)
  ) =>
  Deletable' x ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) ('ForkTree rl (Node rn ra) rr)) 'EQ
  where
  type
    Delete' x ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) ('ForkTree rl (Node rn ra) rr)) 'EQ =
      Balance ('ForkTree (MaxKeyDelete ('ForkTree ll (Node ln la) lr)) (Node (MaxKey ('ForkTree ll (Node ln la) lr)) (MaxValue ('ForkTree ll (Node ln la) lr))) ('ForkTree rl (Node rn ra) rr))
  delete' :: Proxy x
-> ITree
     ('ForkTree
        ('ForkTree ll (Node ln la) lr)
        (Node n a1)
        ('ForkTree rl (Node rn ra) rr))
-> Proxy 'EQ
-> ITree
     (Delete'
        x
        ('ForkTree
           ('ForkTree ll (Node ln la) lr)
           (Node n a1)
           ('ForkTree rl (Node rn ra) rr))
        'EQ)
delete' Proxy x
_ (ForkITree ITree l
l Node n a
_ ITree r
r) Proxy 'EQ
_ =
    ITree
  ('ForkTree
     (MaxKeyDelete ('ForkTree ll (Node ln la) lr))
     (Node
        (MaxKey ('ForkTree ll (Node ln la) lr))
        (MaxValue ('ForkTree ll (Node ln la) lr)))
     r)
-> ITree
     (Balance
        ('ForkTree
           (MaxKeyDelete ('ForkTree ll (Node ln la) lr))
           (Node
              (MaxKey ('ForkTree ll (Node ln la) lr))
              (MaxValue ('ForkTree ll (Node ln la) lr)))
           r))
forall (t :: Tree). Balanceable t => ITree t -> ITree (Balance t)
balance (ITree
   ('ForkTree
      (MaxKeyDelete ('ForkTree ll (Node ln la) lr))
      (Node
         (MaxKey ('ForkTree ll (Node ln la) lr))
         (MaxValue ('ForkTree ll (Node ln la) lr)))
      r)
 -> ITree
      (Balance
         ('ForkTree
            (MaxKeyDelete ('ForkTree ll (Node ln la) lr))
            (Node
               (MaxKey ('ForkTree ll (Node ln la) lr))
               (MaxValue ('ForkTree ll (Node ln la) lr)))
            r)))
-> ITree
     ('ForkTree
        (MaxKeyDelete ('ForkTree ll (Node ln la) lr))
        (Node
           (MaxKey ('ForkTree ll (Node ln la) lr))
           (MaxValue ('ForkTree ll (Node ln la) lr)))
        r)
-> ITree
     (Balance
        ('ForkTree
           (MaxKeyDelete ('ForkTree ll (Node ln la) lr))
           (Node
              (MaxKey ('ForkTree ll (Node ln la) lr))
              (MaxValue ('ForkTree ll (Node ln la) lr)))
           r))
forall a b. (a -> b) -> a -> b
$ ITree (MaxKeyDelete ('ForkTree ll (Node ln la) lr))
-> Node
     (MaxKey ('ForkTree ll (Node ln la) lr))
     (MaxValue ('ForkTree ll (Node ln la) lr))
-> ITree r
-> ITree
     ('ForkTree
        (MaxKeyDelete ('ForkTree ll (Node ln la) lr))
        (Node
           (MaxKey ('ForkTree ll (Node ln la) lr))
           (MaxValue ('ForkTree ll (Node ln la) lr)))
        r)
forall a (l :: Tree) (n :: Nat) (r :: Tree).
Show a =>
ITree l -> Node n a -> ITree r -> ITree ('ForkTree l (Node n a) r)
ForkITree (ITree l -> ITree (MaxKeyDelete l)
forall (t :: Tree) (l :: Tree) (n :: Nat) a1 (r :: Tree).
(MaxKeyDeletable t, t ~ 'ForkTree l (Node n a1) r) =>
ITree t -> ITree (MaxKeyDelete t)
maxKeyDelete ITree l
l) Node
  (MaxKey ('ForkTree ll (Node ln la) lr))
  (MaxValue ('ForkTree ll (Node ln la) lr))
node ITree r
r
    where
      node :: Node
  (MaxKey ('ForkTree ll (Node ln la) lr))
  (MaxValue ('ForkTree ll (Node ln la) lr))
node = Proxy (MaxKey ('ForkTree ll (Node ln la) lr))
-> MaxValue ('ForkTree ll (Node ln la) lr)
-> Node
     (MaxKey ('ForkTree ll (Node ln la) lr))
     (MaxValue ('ForkTree ll (Node ln la) lr))
forall (k :: Nat) a. Proxy k -> a -> Node k a
mkNode (Proxy (MaxKey l)
forall {k} (t :: k). Proxy t
Proxy :: Proxy (MaxKey l)) (ITree l -> MaxValue l
forall (t :: Tree) (l :: Tree) (n :: Nat) a1 (r :: Tree).
(Maxable t, t ~ 'ForkTree l (Node n a1) r) =>
ITree t -> MaxValue t
maxValue ITree l
l)

instance Deletable' x ('ForkTree 'EmptyTree (Node n a1) r) 'LT where
  type Delete' x ('ForkTree 'EmptyTree (Node n a1) r) 'LT = 'ForkTree 'EmptyTree (Node n a1) r
  delete' :: Proxy x
-> ITree ('ForkTree 'EmptyTree (Node n a1) r)
-> Proxy 'LT
-> ITree (Delete' x ('ForkTree 'EmptyTree (Node n a1) r) 'LT)
delete' Proxy x
_ ITree ('ForkTree 'EmptyTree (Node n a1) r)
t Proxy 'LT
_ = ITree ('ForkTree 'EmptyTree (Node n a1) r)
ITree (Delete' x ('ForkTree 'EmptyTree (Node n a1) r) 'LT)
t

instance
  ( l ~ 'ForkTree ll (Node ln la) lr,
    o ~ CmpNat x ln,
    Deletable' x l o,
    Balanceable ('ForkTree (Delete' x l (CmpNat x ln)) (Node n a1) r)
  ) =>
  Deletable' x ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) r) 'LT
  where
  type
    Delete' x ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) r) 'LT =
      Balance ('ForkTree (Delete' x ('ForkTree ll (Node ln la) lr) (CmpNat x ln)) (Node n a1) r)
  delete' :: Proxy x
-> ITree ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) r)
-> Proxy 'LT
-> ITree
     (Delete'
        x ('ForkTree ('ForkTree ll (Node ln la) lr) (Node n a1) r) 'LT)
delete' Proxy x
px (ForkITree ITree l
l Node n a
node ITree r
r) Proxy 'LT
_ = ITree
  ('ForkTree
     (Delete' x ('ForkTree ll (Node ln la) lr) o) (Node n a) r)
-> ITree
     (Balance
        ('ForkTree
           (Delete' x ('ForkTree ll (Node ln la) lr) o) (Node n a) r))
forall (t :: Tree). Balanceable t => ITree t -> ITree (Balance t)
balance (ITree
   ('ForkTree
      (Delete' x ('ForkTree ll (Node ln la) lr) o) (Node n a) r)
 -> ITree
      (Balance
         ('ForkTree
            (Delete' x ('ForkTree ll (Node ln la) lr) o) (Node n a) r)))
-> ITree
     ('ForkTree
        (Delete' x ('ForkTree ll (Node ln la) lr) o) (Node n a) r)
-> ITree
     (Balance
        ('ForkTree
           (Delete' x ('ForkTree ll (Node ln la) lr) o) (Node n a) r))
forall a b. (a -> b) -> a -> b
$ ITree (Delete' x ('ForkTree ll (Node ln la) lr) o)
-> Node n a
-> ITree r
-> ITree
     ('ForkTree
        (Delete' x ('ForkTree ll (Node ln la) lr) o) (Node n a) r)
forall a (l :: Tree) (n :: Nat) (r :: Tree).
Show a =>
ITree l -> Node n a -> ITree r -> ITree ('ForkTree l (Node n a) r)
ForkITree (Proxy x -> ITree l -> Proxy o -> ITree (Delete' x l o)
forall (x :: Nat) (t :: Tree) (o :: Ordering).
Deletable' x t o =>
Proxy x -> ITree t -> Proxy o -> ITree (Delete' x t o)
delete' Proxy x
px ITree l
l (Proxy o
forall {k} (t :: k). Proxy t
Proxy :: Proxy o)) Node n a
node ITree r
r

instance Deletable' x ('ForkTree l (Node n a1) 'EmptyTree) 'GT where
  type Delete' x ('ForkTree l (Node n a1) 'EmptyTree) 'GT = ('ForkTree l (Node n a1) 'EmptyTree)
  delete' :: Proxy x
-> ITree ('ForkTree l (Node n a1) 'EmptyTree)
-> Proxy 'GT
-> ITree (Delete' x ('ForkTree l (Node n a1) 'EmptyTree) 'GT)
delete' Proxy x
_ ITree ('ForkTree l (Node n a1) 'EmptyTree)
t Proxy 'GT
_ = ITree ('ForkTree l (Node n a1) 'EmptyTree)
ITree (Delete' x ('ForkTree l (Node n a1) 'EmptyTree) 'GT)
t

instance
  ( o ~ CmpNat x rn,
    r ~ 'ForkTree rl (Node rn ra) rr,
    Deletable' x r o,
    Balanceable ('ForkTree l (Node n a1) (Delete' x r o))
  ) =>
  Deletable' x ('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr)) 'GT
  where
  type
    Delete' x ('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr)) 'GT =
      Balance ('ForkTree l (Node n a1) (Delete' x ('ForkTree rl (Node rn ra) rr) (CmpNat x rn)))
  delete' :: Proxy x
-> ITree ('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr))
-> Proxy 'GT
-> ITree
     (Delete'
        x ('ForkTree l (Node n a1) ('ForkTree rl (Node rn ra) rr)) 'GT)
delete' Proxy x
px (ForkITree ITree l
l Node n a
node ITree r
r) Proxy 'GT
_ = ITree
  ('ForkTree
     l (Node n a) (Delete' x ('ForkTree rl (Node rn ra) rr) o))
-> ITree
     (Balance
        ('ForkTree
           l (Node n a) (Delete' x ('ForkTree rl (Node rn ra) rr) o)))
forall (t :: Tree). Balanceable t => ITree t -> ITree (Balance t)
balance (ITree
   ('ForkTree
      l (Node n a) (Delete' x ('ForkTree rl (Node rn ra) rr) o))
 -> ITree
      (Balance
         ('ForkTree
            l (Node n a) (Delete' x ('ForkTree rl (Node rn ra) rr) o))))
-> ITree
     ('ForkTree
        l (Node n a) (Delete' x ('ForkTree rl (Node rn ra) rr) o))
-> ITree
     (Balance
        ('ForkTree
           l (Node n a) (Delete' x ('ForkTree rl (Node rn ra) rr) o)))
forall a b. (a -> b) -> a -> b
$ ITree l
-> Node n a
-> ITree (Delete' x ('ForkTree rl (Node rn ra) rr) o)
-> ITree
     ('ForkTree
        l (Node n a) (Delete' x ('ForkTree rl (Node rn ra) rr) o))
forall a (l :: Tree) (n :: Nat) (r :: Tree).
Show a =>
ITree l -> Node n a -> ITree r -> ITree ('ForkTree l (Node n a) r)
ForkITree ITree l
l Node n a
node (Proxy x -> ITree r -> Proxy o -> ITree (Delete' x r o)
forall (x :: Nat) (t :: Tree) (o :: Ordering).
Deletable' x t o =>
Proxy x -> ITree t -> Proxy o -> ITree (Delete' x t o)
delete' Proxy x
px ITree r
r (Proxy o
forall {k} (t :: k). Proxy t
Proxy :: Proxy o))