open import Relation.Binary
open import Prelude

module Data.Heap {ℓ₁} {Key : Type ℓ₁} {ℓ₂ ℓ₃} (ord : TotalOrder Key ℓ₂ ℓ₃) where

open import Data.List
open import Data.Maybe

open import Relation.Binary.Construct.LowerBound ord

open TotalOrder ord using (_≤|≥_)
open TotalOrder lb-ord hiding (_≤|≥_)

private
  variable
    u v : Level
    U : Key  Type u
    V : Key  Type v

record Heap⁺ {v} (lb : ⌊∙⌋) (V : Key  Type v) : Type (v ℓ⊔ ℓ₁ ℓ⊔ ℓ₃) where
  inductive; pattern; constructor node
  field
    key : Key
    val : V key
    bnd : lb   key 
    rst : List (Heap⁺  key  V)
open Heap⁺ public

private variable lb : ⌊∙⌋

_∪_ : Heap⁺ lb V  Heap⁺ lb V  Heap⁺ lb V
node      node     with  ≤|≥ 
... | inl x≤y = node    (node   x≤y   )
... | inr y≤x = node    (node   y≤x   )

merge⁺ : Heap⁺ lb V  List (Heap⁺ lb V)  Heap⁺ lb V
merge⁺ x [] = x
merge⁺ x₁ (x₂  []) = x₁  x₂
merge⁺ x₁ (x₂  x₃  xs) = (x₁  x₂)  merge⁺ x₃ xs

merge : List (Heap⁺ lb V)  Maybe (Heap⁺ lb V)
merge [] = nothing
merge (x  xs) = just (merge⁺ x xs)

popMin⁺ : Heap⁺ lb V   k × V k × (lb   k ) × Maybe (Heap⁺  k  V)
popMin⁺ (node k v b r) = k , v , b , merge r