2025-06-29 10:35:37 -07:00
module Lattice.Builder where
open import Lattice
open import Equivalence
open import Data.Maybe as Maybe using ( Maybe; just; nothing; _>>=_)
open import Data.Unit using ( ⊤ ; tt)
open import Data.List.NonEmpty using ( List⁺; tail; toList) renaming ( _∷_ to _∷⁺_)
open import Data.List using ( List; _∷_; [])
open import Data.Sum using ( _⊎_; inj₁; inj₂)
open import Data.Product using ( Σ)
open import Relation.Binary.PropositionalEquality as Eq using ( _≡_; refl; sym; trans; cong; subst)
open import Agda.Primitive using ( lsuc; Level) renaming ( _⊔_ to _⊔ℓ _)
data lift-≈ { a} { A : Set a} ( _≈_ : A → A → Set a) : Maybe A → Maybe A → Set a where
≈-just : ∀ { a₁ a₂ : A} → a₁ ≈ a₂ → lift-≈ _≈_ ( just a₁) ( just a₂)
≈-nothing : lift-≈ _≈_ nothing nothing
-- lift-≈-to-≈' : ∀ {a} {A : Set a} (_≈_ : A → A → Set a) (_≈'_ : A → A → Set a) →
-- (∀ x y → (x ≈ y) ≡ (x ≈' y)) →
-- ∀ m₁ m₂ → lift-≈ _≈_ m₁ m₂ → lift-≈ _≈'_ m₁ m₂
-- lift-≈-to-≈' _≈_ _≈'_ ≈≡≈' (just x₁) (just x₂) (≈-just x₁≈x₂)
-- rewrite ≈≡≈' x₁ x₂ = ≈-just x₁≈x₂
-- lift-≈-to-≈' _≈_ _≈'_ ≈≡≈' m₁ m₂ ≈-nothing = ≈-nothing
lift-≈-map : ∀ { a b} { A : Set a} { B : Set b} ( f : A → B)
( _≈ᵃ_ : A → A → Set a) ( _≈ᵇ_ : B → B → Set b) →
( ∀ a₁ a₂ → a₁ ≈ᵃ a₂ → f a₁ ≈ᵇ f a₂) →
∀ m₁ m₂ → lift-≈ _≈ᵃ_ m₁ m₂ → lift-≈ _≈ᵇ_ ( Maybe.map f m₁) ( Maybe.map f m₂)
lift-≈-map f _≈ᵃ_ _≈ᵇ_ ≈ᵃ→≈ᵇ ( just a₁) ( just a₂) ( ≈-just a₁≈a₂) = ≈-just ( ≈ᵃ→≈ᵇ a₁ a₂ a₁≈a₂)
lift-≈-map f _≈ᵃ_ _≈ᵇ_ ≈ᵃ→≈ᵇ nothing nothing ≈-nothing = ≈-nothing
2025-07-05 14:52:40 -07:00
instance
lift-≈-Equivalence : ∀ { a} { A : Set a} { _≈_ : A → A → Set a} { { isEquivalence : IsEquivalence A _≈_} } → IsEquivalence ( Maybe A) ( lift-≈ _≈_)
lift-≈-Equivalence { { isEquivalence} } = record
{ ≈-trans =
( λ { ( ≈-just a₁≈a₂) ( ≈-just a₂≈a₃) → ≈-just ( IsEquivalence.≈-trans isEquivalence a₁≈a₂ a₂≈a₃)
; ≈-nothing ≈-nothing → ≈-nothing
} )
; ≈-sym =
( λ { ( ≈-just a₁≈a₂) → ≈-just ( IsEquivalence.≈-sym isEquivalence a₁≈a₂)
; ≈-nothing → ≈-nothing
} )
; ≈-refl = λ { { just a} → ≈-just ( IsEquivalence.≈-refl isEquivalence)
; { nothing} → ≈-nothing
}
}
2025-07-02 13:11:12 -07:00
PartialAssoc : ∀ { a} { A : Set a} ( _≈_ : A → A → Set a) ( _⊗_ : A → A → Maybe A) → Set a
PartialAssoc { a} { A} _≈_ _⊗_ = ∀ ( x y z : A) → lift-≈ _≈_ ( ( x ⊗ y) >>= ( _⊗ z) ) ( ( y ⊗ z) >>= ( x ⊗_) )
PartialComm : ∀ { a} { A : Set a} ( _≈_ : A → A → Set a) ( _⊗_ : A → A → Maybe A) → Set a
PartialComm { a} { A} _≈_ _⊗_ = ∀ ( x y : A) → lift-≈ _≈_ ( x ⊗ y) ( y ⊗ x)
PartialIdemp : ∀ { a} { A : Set a} ( _≈_ : A → A → Set a) ( _⊗_ : A → A → Maybe A) → Set a
PartialIdemp { a} { A} _≈_ _⊗_ = ∀ ( x : A) → lift-≈ _≈_ ( x ⊗ x) ( just x)
2025-06-29 10:35:37 -07:00
record IsPartialSemilattice { a} { A : Set a}
( _≈_ : A → A → Set a)
( _⊔?_ : A → A → Maybe A) : Set a where
_≈?_ : Maybe A → Maybe A → Set a
_≈?_ = lift-≈ _≈_
field
≈-equiv : IsEquivalence A _≈_
≈-⊔-cong : ∀ { a₁ a₂ a₃ a₄} → a₁ ≈ a₂ → a₃ ≈ a₄ → ( a₁ ⊔? a₃) ≈? ( a₂ ⊔? a₄)
2025-07-02 13:11:12 -07:00
⊔-assoc : PartialAssoc _≈_ _⊔?_
⊔-comm : PartialComm _≈_ _⊔?_
⊔-idemp : PartialIdemp _≈_ _⊔?_
2025-06-29 10:35:37 -07:00
record HasIdentityElement : Set a where
field
x : A
not-partial : ∀ ( a₁ a₂ : A) → Σ A ( λ a₃ → ( a₁ ⊔? a₂) ≡ just a₃)
x-identity : ( a : A) → ( x ⊔? a) ≈? just a
data Trivial a : Set a where
instance
mkTrivial : Trivial a
data Empty a : Set a where
Maybe-≈ : ∀ { a} { A : Set a} → ( _≈_ : A → A → Set a) → Maybe A → A → Set a
Maybe-≈ _≈_ ( just a₁) a₂ = a₁ ≈ a₂
Maybe-≈ { a} _≈_ nothing a₂ = Trivial a
record IsPartialLattice { a} { A : Set a}
( _≈_ : A → A → Set a)
( _⊔?_ : A → A → Maybe A)
( _⊓?_ : A → A → Maybe A) : Set a where
field
{ { partialJoinSemilattice} } : IsPartialSemilattice _≈_ _⊔?_
{ { partialMeetSemilattice} } : IsPartialSemilattice _≈_ _⊓?_
absorb-⊔-⊓ : ( x y : A) → Maybe-≈ _≈_ ( ( x ⊓? y) >>= ( x ⊔?_) ) x
absorb-⊓-⊔ : ( x y : A) → Maybe-≈ _≈_ ( ( x ⊔? y) >>= ( x ⊓?_) ) x
open IsPartialSemilattice partialJoinSemilattice public
open IsPartialSemilattice partialMeetSemilattice using ( )
renaming
( ≈-⊔-cong to ≈-⊓-cong
; ⊔-assoc to ⊓-assoc
; ⊔-comm to ⊓-comm
; ⊔-idemp to ⊓-idemp
)
public
record PartialLattice { a} ( A : Set a) : Set ( lsuc a) where
field
_≈_ : A → A → Set a
_⊔?_ : A → A → Maybe A
_⊓?_ : A → A → Maybe A
{ { isPartialLattice} } : IsPartialLattice _≈_ _⊔?_ _⊓?_
open IsPartialLattice isPartialLattice public
HasLeastElement : Set a
HasLeastElement =
IsPartialSemilattice.HasIdentityElement
( IsPartialLattice.partialJoinSemilattice isPartialLattice)
HasGreatestElement : Set a
HasGreatestElement =
IsPartialSemilattice.HasIdentityElement
( IsPartialLattice.partialMeetSemilattice isPartialLattice)
record PartialLatticeType ( a : Level) : Set ( lsuc a) where
field
EltType : Set a
{ { partialLattice} } : PartialLattice EltType
open PartialLattice partialLattice public
Layer : ( a : Level) → Set ( lsuc a)
Layer a = List⁺ ( PartialLatticeType a)
data LayerLeast { a} : Layer a → Set ( lsuc a) where
instance
MkLayerLeast : { T : Set a}
{ { partialLattice : PartialLattice T } }
{ { hasLeast : PartialLattice.HasLeastElement partialLattice } } →
LayerLeast ( record { EltType = T; partialLattice = partialLattice } ∷⁺ [])
data LayerGreatest { a} : Layer a → Set ( lsuc a) where
instance
MkLayerGreatest : { T : Set a}
{ { partialLattice : PartialLattice T } }
{ { hasGreatest : PartialLattice.HasGreatestElement partialLattice } } →
LayerGreatest ( record { EltType = T; partialLattice = partialLattice } ∷⁺ [])
interleaved mutual
data Layers a : Set ( lsuc a)
head : ∀ { a} → Layers a → Layer a
data Layers where
single : Layer a → Layers a
add-via-least : ( l : Layer a) { { least : LayerLeast l } } ( ls : Layers a) → Layers a
add-via-greatest : ( l : Layer a) ( ls : Layers a) { { greatest : LayerGreatest ( head ls) } } → Layers a
head ( single l) = l
head ( add-via-greatest l _) = l
head ( add-via-least l _) = l
ListValue : ∀ { a} → List ( PartialLatticeType a) → Set a
ListValue [] = Empty _
ListValue ( plt ∷ plts) = PartialLatticeType.EltType plt ⊎ ListValue plts
-- Define LayerValue and Path' as functions to avoid increasing the universe level.
-- Path' in particular needs to be at the same level as the other lattices
-- in the builder to ensure composability.
LayerValue : ∀ { a} → Layer a → Set a
LayerValue l⁺ = ListValue ( toList l⁺)
Path' : ∀ { a} → Layers a → Set a
Path' ( single l) = LayerValue l
Path' ( add-via-least l ls) = LayerValue l ⊎ Path' ls
Path' ( add-via-greatest l ls) = LayerValue l ⊎ Path' ls
record Path { a} ( Ls : Layers a) : Set a where
constructor MkPath
field path : Path' Ls
valueAtHead : ∀ { a} ( ls : Layers a) ( lv : LayerValue ( head ls) ) → Path' ls
valueAtHead ( single _) lv = lv
valueAtHead ( add-via-least _ _) lv = inj₁ lv
valueAtHead ( add-via-greatest _ _) lv = inj₁ lv
CombineForPLT : ∀ a → Set ( lsuc a)
CombineForPLT a = ∀ ( plt : PartialLatticeType a) → PartialLatticeType.EltType plt → PartialLatticeType.EltType plt → Maybe ( PartialLatticeType.EltType plt)
lvCombine : ∀ { a} ( f : CombineForPLT a) ( l : List ( PartialLatticeType a) ) ( lv₁ lv₂ : ListValue l) → Maybe ( ListValue l)
lvCombine _ [] _ _ = nothing
lvCombine f ( plt ∷ plts) ( inj₁ v₁) ( inj₁ v₂)
with f plt v₁ v₂
... | just v = just ( inj₁ v)
... | nothing = nothing
lvCombine f ( _ ∷ plts) ( inj₂ lv₁) ( inj₂ lv₂) = Maybe.map inj₂ ( lvCombine f plts lv₁ lv₂)
lvCombine _ ( _ ∷ plts) ( inj₁ _) ( inj₂ _) = nothing
lvCombine _ ( _ ∷ plts) ( inj₂ _) ( inj₁ _) = nothing
lvJoin : ∀ { a} ( l : List ( PartialLatticeType a) ) ( lv₁ lv₂ : ListValue l) → Maybe ( ListValue l)
lvJoin = lvCombine PartialLatticeType._⊔?_
lvMeet : ∀ { a} ( l : List ( PartialLatticeType a) ) ( lv₁ lv₂ : ListValue l) → Maybe ( ListValue l)
lvMeet = lvCombine PartialLatticeType._⊓?_
pathJoin' : ∀ { a} ( Ls : Layers a) ( p₁ p₂ : Path' Ls) → Maybe ( Path' Ls)
pathJoin' ( single l) lv₁ lv₂ = lvJoin ( toList l) lv₁ lv₂
pathJoin' ( add-via-least l ls) ( inj₁ lv₁) ( inj₁ lv₂) = Maybe.map inj₁ ( lvJoin ( toList l) lv₁ lv₂)
pathJoin' ( add-via-least l ls) ( inj₁ lv₁) ( inj₂ p₂) = just ( inj₁ lv₁)
pathJoin' ( add-via-least l ls) ( inj₂ p₁) ( inj₁ lv₂) = just ( inj₁ lv₂)
pathJoin' ( add-via-least l@( plt ∷⁺ []) { { MkLayerLeast { { hasLeast = hasLeast} } } } ls) ( inj₂ p₁) ( inj₂ p₂)
with pathJoin' ls p₁ p₂
... | just p = just ( inj₂ p)
... | nothing = just ( inj₁ ( inj₁ ( IsPartialSemilattice.HasIdentityElement.x hasLeast) ) )
pathJoin' ( add-via-greatest l ls) ( inj₁ lv₁) ( inj₁ lv₂) = Maybe.map inj₁ ( lvJoin ( toList l) lv₁ lv₂)
pathJoin' ( add-via-greatest l ls) ( inj₁ lv₁) ( inj₂ p₂) = just ( inj₁ lv₁)
pathJoin' ( add-via-greatest l ls) ( inj₂ p₁) ( inj₁ lv₂) = just ( inj₁ lv₂)
pathJoin' ( add-via-greatest l ls { { greatest} } ) ( inj₂ p₁) ( inj₂ p₂) = Maybe.map inj₂ ( pathJoin' ls p₁ p₂) -- not our job to provide the least element here. If there was a "greatest" there, recursion would've found it (?)
pathMeet' : ∀ { a} ( Ls : Layers a) ( p₁ p₂ : Path' Ls) → Maybe ( Path' Ls)
pathMeet' ( single l) lv₁ lv₂ = lvMeet ( toList l) lv₁ lv₂
pathMeet' ( add-via-least l ls) ( inj₁ lv₁) ( inj₁ lv₂) = Maybe.map inj₁ ( lvMeet ( toList l) lv₁ lv₂)
pathMeet' ( add-via-least l ls) ( inj₁ lv₁) ( inj₂ p₂) = just ( inj₂ p₂)
pathMeet' ( add-via-least l ls) ( inj₂ p₁) ( inj₁ lv₂) = just ( inj₂ p₁)
pathMeet' ( add-via-least l ls) ( inj₂ p₁) ( inj₂ p₂) = Maybe.map inj₂ ( pathMeet' ls p₁ p₂)
pathMeet' ( add-via-greatest l ls { { greatest} } ) ( inj₁ lv₁) ( inj₁ lv₂)
with lvMeet ( toList l) lv₁ lv₂
... | just lv = just ( inj₁ lv)
... | nothing
with head ls | greatest | valueAtHead ls
... | _ | MkLayerGreatest { { hasGreatest = hasGreatest} } | vah
= just ( inj₂ ( vah ( inj₁ ( IsPartialSemilattice.HasIdentityElement.x hasGreatest) ) ) )
pathMeet' ( add-via-greatest l ls) ( inj₁ lv₁) ( inj₂ p₂) = just ( inj₂ p₂)
pathMeet' ( add-via-greatest l ls) ( inj₂ p₁) ( inj₁ lv₂) = just ( inj₂ p₁)
pathMeet' ( add-via-greatest l ls) ( inj₂ p₁) ( inj₂ p₂) = Maybe.map inj₂ ( pathMeet' ls p₁ p₂)
eqL : ∀ { a} ( L : List ( PartialLatticeType a) ) → ListValue L → ListValue L → Set a
eqL [] ( )
eqL ( plt ∷ plts) ( inj₁ v₁ ) ( inj₁ v₂) = PartialLattice._≈_ ( PartialLatticeType.partialLattice plt) v₁ v₂
eqL ( plt ∷ plts) ( inj₂ v₁ ) ( inj₂ v₂) = eqL plts v₁ v₂
eqL ( plt ∷ plts) ( inj₁ _) ( inj₂ _) = Empty _
eqL ( plt ∷ plts) ( inj₂ _) ( inj₁ _) = Empty _
eqL-refl : ∀ { a} ( L : List ( PartialLatticeType a) ) ( lv : ListValue L) → eqL L lv lv
eqL-refl [] ( )
eqL-refl ( plt ∷ plts) ( inj₁ v) = IsEquivalence.≈-refl ( PartialLatticeType.≈-equiv plt)
eqL-refl ( plt ∷ plts) ( inj₂ v) = eqL-refl plts v
eqLv : ∀ { a} ( L : Layer a) → LayerValue L → LayerValue L → Set a
eqLv L = eqL ( toList L)
eqLv-refl : ∀ { a} ( L : Layer a) → ( lv : LayerValue L) → eqLv L lv lv
eqLv-refl L = eqL-refl ( toList L)
eqPath' : ∀ { a} ( Ls : Layers a) → Path' Ls → Path' Ls → Set a
eqPath' ( single l) lv₁ lv₂ = eqLv l lv₁ lv₂
eqPath' ( add-via-least l ls) ( inj₁ lv₁) ( inj₁ lv₂) = eqLv l lv₁ lv₂
eqPath' ( add-via-least l ls) ( inj₂ p₁) ( inj₂ p₂) = eqPath' ls p₁ p₂
eqPath' ( add-via-least l ls) ( inj₁ lv₁) ( inj₂ p₂) = Empty _
eqPath' ( add-via-least l ls) ( inj₂ p₁) ( inj₁ lv₂) = Empty _
eqPath' ( add-via-greatest l ls) ( inj₁ lv₁) ( inj₁ lv₂) = eqLv l lv₁ lv₂
eqPath' ( add-via-greatest l ls) ( inj₂ p₁) ( inj₂ p₂) = eqPath' ls p₁ p₂
eqPath' ( add-via-greatest l ls) ( inj₁ lv₁) ( inj₂ p₂) = Empty _
eqPath' ( add-via-greatest l ls) ( inj₂ p₁) ( inj₁ lv₂) = Empty _
eqPath'-refl : ∀ { a} ( Ls : Layers a) → ( p : Path' Ls) → eqPath' Ls p p
eqPath'-refl ( single l) lv = eqLv-refl l lv
eqPath'-refl ( add-via-least l ls) ( inj₁ lv) = eqLv-refl l lv
eqPath'-refl ( add-via-least l ls) ( inj₂ p) = eqPath'-refl ls p
eqPath'-refl ( add-via-greatest l ls) ( inj₁ lv) = eqLv-refl l lv
eqPath'-refl ( add-via-greatest l ls) ( inj₂ p) = eqPath'-refl ls p
-- Now that we can compare paths for "equality", we can state and
-- prove theorems such as commutativity and idempotence.
lvCombine-comm : ∀ { a} ( f : CombineForPLT a) →
2025-07-02 13:11:12 -07:00
( ∀ plt → PartialComm ( PartialLatticeType._≈_ plt) ( f plt) ) →
∀ ( L : List ( PartialLatticeType a) ) →
PartialComm ( eqL L) ( lvCombine f L)
2025-06-29 10:35:37 -07:00
lvCombine-comm f f-comm L@( plt ∷ plts) lv₁@( inj₁ v₁) ( inj₁ v₂)
with f plt v₁ v₂
| f plt v₂ v₁
| f-comm plt v₁ v₂
... | _ | _ | ≈-just v₁v₂≈v₂v₁ = ≈-just v₁v₂≈v₂v₁
... | _ | _ | ≈-nothing = ≈-nothing
lvCombine-comm f f-comm ( plt ∷ plts) ( inj₂ lv₁) ( inj₂ lv₂)
with lvCombine f plts lv₁ lv₂ | lvCombine f plts lv₂ lv₁ | lvCombine-comm f f-comm plts lv₁ lv₂
... | _ | _ | ≈-just lv₁lv₂≈lv₂lv₁ = ≈-just lv₁lv₂≈lv₂lv₁
... | _ | _ | ≈-nothing = ≈-nothing
lvCombine-comm f f-comm ( plt ∷ plts) ( inj₁ v₁) ( inj₂ lv₂) = ≈-nothing
lvCombine-comm f f-comm ( plt ∷ plts) ( inj₂ lv₁) ( inj₁ v₂) = ≈-nothing
2025-07-02 13:11:12 -07:00
lvJoin-comm : ∀ { a} ( L : List ( PartialLatticeType a) ) → PartialComm ( eqL L) ( lvJoin L)
2025-06-29 10:35:37 -07:00
lvJoin-comm = lvCombine-comm PartialLatticeType._⊔?_ PartialLatticeType.⊔-comm
2025-07-02 13:11:12 -07:00
lvMeet-comm : ∀ { a} ( L : List ( PartialLatticeType a) ) → PartialComm ( eqL L) ( lvMeet L)
2025-06-29 10:35:37 -07:00
lvMeet-comm = lvCombine-comm PartialLatticeType._⊓?_ PartialLatticeType.⊓-comm
2025-07-02 13:11:12 -07:00
pathJoin'-comm : ∀ { a} { Ls : Layers a} → PartialComm ( eqPath' Ls) ( pathJoin' Ls)
2025-06-29 10:35:37 -07:00
pathJoin'-comm { Ls = single l} lv₁ lv₂ = lvJoin-comm ( toList l) lv₁ lv₂
pathJoin'-comm { Ls = add-via-least l ls} ( inj₁ lv₁) ( inj₁ lv₂) = lift-≈-map inj₁ _ _ ( λ _ _ x → x) _ _ ( lvJoin-comm ( toList l) lv₁ lv₂)
pathJoin'-comm { Ls = add-via-least l@( plt ∷⁺ []) { { MkLayerLeast { { hasLeast = hasLeast} } } } ls} ( inj₂ p₁) ( inj₂ p₂)
with pathJoin' ls p₁ p₂ | pathJoin' ls p₂ p₁ | pathJoin'-comm { Ls = ls} p₁ p₂
... | just p | just p' | ≈-just p≈p' = ≈-just p≈p'
... | nothing | nothing | ≈-nothing = ≈-just ( eqLv-refl l ( inj₁ ( IsPartialSemilattice.HasIdentityElement.x hasLeast) ) )
pathJoin'-comm { Ls = add-via-least l ls} ( inj₁ lv₁) ( inj₂ p₂) = ≈-just ( eqLv-refl l lv₁)
pathJoin'-comm { Ls = add-via-least l ls} ( inj₂ p₁) ( inj₁ lv₂) = ≈-just ( eqLv-refl l lv₂)
pathJoin'-comm { Ls = add-via-greatest l ls} ( inj₁ lv₁) ( inj₁ lv₂) = lift-≈-map inj₁ _ _ ( λ _ _ x → x) _ _ ( lvJoin-comm ( toList l) lv₁ lv₂)
pathJoin'-comm { Ls = add-via-greatest l ls} ( inj₂ p₁) ( inj₂ p₂) = lift-≈-map inj₂ _ _ ( λ _ _ x → x) _ _ ( pathJoin'-comm { Ls = ls} p₁ p₂)
pathJoin'-comm { Ls = add-via-greatest l ls} ( inj₁ lv₁) ( inj₂ p₂) = ≈-just ( eqLv-refl l lv₁)
pathJoin'-comm { Ls = add-via-greatest l ls} ( inj₂ p₁) ( inj₁ lv₂) = ≈-just ( eqLv-refl l lv₂)
2025-07-02 13:11:12 -07:00
pathMeet'-comm : ∀ { a} { Ls : Layers a} → PartialComm ( eqPath' Ls) ( pathMeet' Ls)
2025-06-29 10:35:37 -07:00
pathMeet'-comm { Ls = single l} lv₁ lv₂ = lvMeet-comm ( toList l) lv₁ lv₂
pathMeet'-comm { Ls = add-via-least l ls} ( inj₁ lv₁) ( inj₁ lv₂) = lift-≈-map inj₁ _ _ ( λ _ _ x → x) _ _ ( lvMeet-comm ( toList l) lv₁ lv₂)
pathMeet'-comm { Ls = add-via-least l ls} ( inj₂ p₁) ( inj₂ p₂) = lift-≈-map inj₂ _ _ ( λ _ _ x → x) _ _ ( pathMeet'-comm { Ls = ls} p₁ p₂)
pathMeet'-comm { Ls = add-via-least l ls} ( inj₁ lv₁) ( inj₂ p₂) = ≈-just ( eqPath'-refl ls p₂)
pathMeet'-comm { Ls = add-via-least l ls} ( inj₂ p₁) ( inj₁ lv₂) = ≈-just ( eqPath'-refl ls p₁)
pathMeet'-comm { Ls = add-via-greatest l ls { { greatest} } } ( inj₁ lv₁) ( inj₁ lv₂)
with lvMeet ( toList l) lv₁ lv₂ | lvMeet ( toList l) lv₂ lv₁ | lvMeet-comm ( toList l) lv₁ lv₂
... | just lv | just lv' | ≈-just lv≈lv' = ≈-just lv≈lv'
... | nothing | nothing | ≈-nothing
with ls | greatest | valueAtHead ls
-- begin dumb: don't know why, but abstracting on `head ls` leads to an ill-formed case
... | single l' | MkLayerGreatest { { hasGreatest = hasGreatest} } | vah
= ≈-just ( eqLv-refl l' ( vah ( inj₁ ( IsPartialSemilattice.HasIdentityElement.x hasGreatest) ) ) )
... | add-via-least l' { { least = least} } ls' | MkLayerGreatest { { hasGreatest = hasGreatest} } | vah
= ≈-just ( eqPath'-refl ( add-via-least l' { { least} } ls') ( vah ( inj₁ ( IsPartialSemilattice.HasIdentityElement.x hasGreatest) ) ) )
... | add-via-greatest l' ls' { { greatest = greatest'} } | MkLayerGreatest { { hasGreatest = hasGreatest} } | vah
= ≈-just ( eqPath'-refl ( add-via-greatest l' ls' { { greatest'} } ) ( vah ( inj₁ ( IsPartialSemilattice.HasIdentityElement.x hasGreatest) ) ) )
-- end dumb
pathMeet'-comm { Ls = add-via-greatest l ls { { greatest} } } ( inj₂ p₁) ( inj₂ p₂) = lift-≈-map inj₂ _ _ ( λ _ _ x → x) _ _ ( pathMeet'-comm { Ls = ls} p₁ p₂)
pathMeet'-comm { Ls = add-via-greatest l ls} ( inj₁ lv₁) ( inj₂ p₂) = ≈-just ( eqPath'-refl ls p₂)
pathMeet'-comm { Ls = add-via-greatest l ls} ( inj₂ p₁) ( inj₁ lv₂) = ≈-just ( eqPath'-refl ls p₁)
record _≈_ { a} { Ls : Layers a} ( p₁ p₂ : Path Ls) : Set a where
field pathEq : eqPath' Ls ( Path.path p₁) ( Path.path p₂)
_⊔̇_ : ∀ { a} { Ls : Layers a} ( p₁ p₂ : Path Ls) → Maybe ( Path Ls)
_⊔̇_ { a} { ls} p₁ p₂ = Maybe.map MkPath ( pathJoin' ls ( Path.path p₁) ( Path.path p₂) )
_⊓̇_ : ∀ { a} { Ls : Layers a} ( p₁ p₂ : Path Ls) → Maybe ( Path Ls)
_⊓̇_ { a} { ls} p₁ p₂ = Maybe.map MkPath ( pathMeet' ls ( Path.path p₁) ( Path.path p₂) )
-- data ListValue {a : Level} : List (PartialLatticeType a) → Set (lsuc a) where
-- here : ∀ {plt : PartialLatticeType a} {pltl : List (PartialLatticeType a)}
-- (v : PartialLatticeType.EltType plt) → ListValue (plt ∷ pltl)
-- there : ∀ {plt : PartialLatticeType a} {pltl : List (PartialLatticeType a)} →
-- ListValue pltl → ListValue (plt ∷ pltl)