{-# OPTIONS --without-K #-}
open import Relation.Unary
open import Core.Functor
open import Core.Functor.NaturalTransformation
open import Core.Functor.Monad
open import Core.Ternary
open import Core.Container
open import Core.Signature
open import Core.Extensionality
open import Core.Logic
open import Effect.Syntax.Free
open import Effect.Syntax.Hefty
open import Effect.Base
open import Data.Empty
open import Data.Product
open import Data.Sum
open import Effect.Relation.Ternary.FirstOrderSeparation
open import Effect.Relation.Binary.FirstOrderInclusion
open import Effect.Relation.Ternary.HigherOrderSeparation
open import Effect.Relation.Binary.HigherOrderInclusion
open import Effect.Theory.FirstOrder
open import Function hiding (_⇔_)
open import Relation.Binary using (Preorder)
open import Relation.Binary.PropositionalEquality
open import Effect.Handle
module Effect.Elaborate where
open import Core.MonotonePredicate Effect _≲_
S : ∀ {a b c} {A : Set a} {B : Set b} {C : Set c} → (A → B → C) → (A → B) → A → C
S = λ x y z → x z (y z)
record Elaboration (η : Effectᴴ) (ε : Effect) : Set₁ where
field
elab : □ (S (Algebra ∘ η) Free) ε
elaborate : ∀[ Hefty (η ε) ⇒ Free ε ]
elaborate = fold-hefty pure (□⟨ elab ⟩ ≲-refl)
elaborate′ : ⦃ ε ≲ ε′ ⦄ → ∀[ Hefty (η ε′) ⇒ Free ε′ ]
elaborate′ ⦃ i ⦄ = fold-hefty pure (□⟨ elab ⟩ i)
ℰ⟦_⟧ = elaborate′
ℰ⟪_⟫ : ⦃ ε ≲ ε′ ⦄ → (A → Hefty (η ε′) B) → (A → Free ε′ B)
ℰ⟪ f ⟫ = λ x → ℰ⟦ f x ⟧
field
commutes :
∀ {A B : Set} {f : A → B}
→ (x : ⟦ η ε′ ⟧ (Free ε′) A)
→ ⦃ i : ε ≲ ε′ ⦄ → (□⟨ elab ⟩ i) .α (fmap f x) ≡ fmap f ((□⟨ elab ⟩ i) .α x)
coherent :
∀ {A B ε′ c s} → ⦃ i : ε ≲ ε′ ⦄
→ (k₁ : response (η _) c → Free ε′ A)
→ (k₂ : A → Free ε′ B)
→ (□⟨ elab ⟩ i) .α ⟪ c , k₁ >=> k₂ , s ⟫ ≡ (□⟨ elab ⟩ i) .α ⟪ c , k₁ , s ⟫ >>= k₂
elab-natural : ∀ {ε′} → ⦃ _ : ε ≲ ε′ ⦄ → Natural ℰ⟦_⟧
elab-natural ⦃ i ⦄ .commute = commute-elab
where
open ≡-Reasoning
commute-elab : ∀ {X Y} {f : X → Y} → (x : Hefty (η _) X) → ℰ⟦ (fmap f x) ⟧ ≡ fmap f ℰ⟦ x ⟧
commute-elab (pure x) = refl
commute-elab {f = f} (impure ⟪ c , k , s ⟫) =
begin
ℰ⟦ fmap f (impure ⟪ c , k , s ⟫) ⟧
≡⟨⟩
ℰ⟦ impure ⟪ c , fmap f ∘ k , s ⟫ ⟧
≡⟨⟩
(□⟨ elab ⟩ i) .α ⟪ c , ℰ⟪ fmap f ∘ k ⟫ , ℰ⟦_⟧ ∘ s ⟫
≡⟨ cong (λ ○ → (□⟨ elab ⟩ i) .α ⟪ c , ○ , ℰ⟦_⟧ ∘ s ⟫) (extensionality λ x → commute-elab (k x)) ⟩
(□⟨ elab ⟩ i) .α ⟪ c , fmap f ∘ ℰ⟪ k ⟫ , ℰ⟦_⟧ ∘ s ⟫
≡⟨⟩
(□⟨ elab ⟩ i) .α (fmap f ⟪ c , ℰ⟪ k ⟫ , ℰ⟦_⟧ ∘ s ⟫)
≡⟨ commutes ⟪ c , ℰ⟪ k ⟫ , ℰ⟦_⟧ ∘ s ⟫ ⟩
fmap f ((□⟨ elab ⟩ i) .α ⟪ c , ℰ⟪ k ⟫ , ℰ⟦_⟧ ∘ s ⟫)
≡⟨⟩
fmap f ℰ⟦ impure ⟪ c , k , s ⟫ ⟧
∎
elab-id : ⦃ _ : ε ≲ ε′ ⦄ → ℰ⟪ return {A = A} ⟫ ≡ return {F = Free ε′}
elab-id = refl
mutual
elab-∘′ : ∀ {B C : Set}
→ ⦃ _ : ε ≲ ε′ ⦄
→ (m : Hefty (η ε′) B)
→ (k : B → Hefty (η ε′) C)
→ ℰ⟦ m >>= k ⟧ ≡ ℰ⟦ m ⟧ >>= ℰ⟪ k ⟫
elab-∘′ (pure x) k = refl
elab-∘′ ⦃ i ⦄ (impure ⟪ c , k′ , s ⟫) k =
begin
ℰ⟦ impure ⟪ c , k′ , s ⟫ >>= k ⟧
≡⟨⟩
ℰ⟦ impure ⟪ c , (k′ >=> k) , (_>>= pure) ∘ s ⟫ ⟧
≡⟨ cong (λ ○ → ℰ⟦ impure ⟪ c , (k′ >=> k) , ○ ⟫ ⟧) (extensionality $ λ ψ → >>=-idʳ (s ψ)) ⟩
ℰ⟦ impure ⟪ c , (k′ >=> k) , s ⟫ ⟧
≡⟨⟩
fold-hefty pure (□⟨ elab ⟩ i) (impure ⟪ c , (k′ >=> k) , s ⟫)
≡⟨⟩
(□⟨ elab ⟩ i) .α ⟪ c , ℰ⟪ k′ >=> k ⟫ , ℰ⟦_⟧ ∘ s ⟫
≡⟨ cong (λ ○ → (□⟨ elab ⟩ i) .α ⟪ c , ○ , ℰ⟦_⟧ ∘ s ⟫) (elab-∘ k′ k) ⟩
(□⟨ elab ⟩ i) .α ⟪ c , (ℰ⟪ k′ ⟫ >=> ℰ⟪ k ⟫) , ℰ⟦_⟧ ∘ s ⟫
≡⟨ coherent ℰ⟪ k′ ⟫ ℰ⟪ k ⟫ ⟩
(□⟨ elab ⟩ i) .α ⟪ c , ℰ⟪ k′ ⟫ , ℰ⟦_⟧ ∘ s ⟫ >>= ℰ⟪ k ⟫
≡⟨⟩
fold-hefty pure (□⟨ elab ⟩ i) (impure ⟪ c , k′ , s ⟫) >>= ℰ⟪ k ⟫
≡⟨⟩
ℰ⟦ impure ⟪ c , k′ , s ⟫ ⟧ >>= ℰ⟪ k ⟫
∎
where
open ≡-Reasoning
elab-∘ : ∀ {A B C : Set}
→ ⦃ _ : ε ≲ ε′ ⦄
→ (k₁ : A → Hefty (η ε′) B)
→ (k₂ : B → Hefty (η ε′) C)
→ ℰ⟪ k₁ >=> k₂ ⟫ ≡ ℰ⟪ k₁ ⟫ >=> ℰ⟪ k₂ ⟫
elab-∘ ⦃ i ⦄ k₁ k₂ = extensionality λ x → elab-∘′ (k₁ x) k₂
elab-mm : ∀ {ε′} → ⦃ _ : ε ≲ ε′ ⦄ → MonadMorphism (Hefty (η ε′)) (Free ε′)
elab-mm = record
{ Ψ = elaborate′
; Ψ-natural = elab-natural
; resp-unit = elab-id
; resp-join = elab-∘
}
open Elaboration
record _⊑_ (e₁ : Elaboration η₁ ε₁) (e₂ : Elaboration η₂ ε₂) : Set₁ where
field
⦃ ≲-eff ⦄ : ε₁ ≲ ε₂
⦃ ≲-effᴴ ⦄ : η₁ ≲ η₂
preserves-cases :
∀ {M}
→ (m : ⟦ η₁ ε₂ ⟧ M A)
→ (e′ : ∀[ M ⇒ Free ε₂ ])
→ (□⟨ e₁ .elab ⟩ ≲-eff ) .α (sig-hmap e′ m)
≡ (□⟨ e₂ .elab ⟩ ≲-refl) .α (sig-hmap e′ (injᴴ m))
open _⊑_ public
⊑-refl : {e : Elaboration η ε} → e ⊑ e
≲-eff ⊑-refl = ≲-refl
≲-effᴴ ⊑-refl = ≲ᴴ-refl
preserves-cases ⊑-refl m e′ = refl
module _ {e₁ : Elaboration η₁ ε₁} {e₂ : Elaboration η₂ ε₂} where
use-elab-def :
∀ ⦃ ζ : e₁ ⊑ e₂ ⦄
→ (m : ⟦ η₁ ε₂ ⟧ (Hefty (η₂ ε₂)) A)
→ elaborate e₂ (impure (injᴴ m))
≡ (□⟨ e₁ .elab ⟩ ζ .≲-eff) .α (sig-hmap (elaborate e₂) m)
use-elab-def ⦃ ζ ⦄ m =
begin
elaborate e₂ (impure (injᴴ m))
≡⟨ (sym $ ζ .preserves-cases m (elaborate e₂)) ⟩
(□⟨ e₁ .elab ⟩ ζ .≲-eff) .α (sig-hmap (elaborate e₂) m)
∎
where
open ≡-Reasoning
open □
open _✴_
instance elab-monotone : Monotone (Elaboration η)
elab-monotone .weaken i e .elab = necessary (λ i′ → □⟨ e .elab ⟩ ≲-trans i i′)
elab-monotone .weaken i e .commutes x ⦃ i′ ⦄ = e .commutes x ⦃ ≲-trans i i′ ⦄
elab-monotone .weaken i e .coherent ⦃ i′ ⦄ = λ k₁ k₂ → e .coherent ⦃ ≲-trans i i′ ⦄ k₁ k₂
_⟪⊕⟫_ : ∀[ Elaboration η₁ ⇒ Elaboration η₂ ⇒ Elaboration (η₁ ·⊕ η₂) ]
(e₁ ⟪⊕⟫ e₂) .elab = necessary λ i → (□⟨ e₁ .elab ⟩ i) ⟨⊕⟩ (□⟨ e₂ .elab ⟩ i)
(e₁ ⟪⊕⟫ e₂) .commutes ⟪ inj₁ c , k , s ⟫ = e₁ .commutes ⟪ c , k , s ⟫
(e₁ ⟪⊕⟫ e₂) .commutes ⟪ inj₂ c , k , s ⟫ = e₂ .commutes ⟪ c , k , s ⟫
(e₁ ⟪⊕⟫ e₂) .coherent {c = inj₁ x} = e₁ .coherent
(e₁ ⟪⊕⟫ e₂) .coherent {c = inj₂ y} = e₂ .coherent
⊑-⟪⊕⟫-left : ∀ {e₁ : Elaboration η₁ ε} → {e₂ : Elaboration η₂ ε} → e₁ ⊑ (e₁ ⟪⊕⟫ e₂)
≲-eff ⊑-⟪⊕⟫-left = ≲-refl
≲-effᴴ ⊑-⟪⊕⟫-left = ·⊑-⊕-left
preserves-cases ⊑-⟪⊕⟫-left _ _ = refl
⊑-⟪⊕⟫-right : ∀ {e₁ : Elaboration η₁ ε} → {e₂ : Elaboration η₂ ε} → e₂ ⊑ (e₁ ⟪⊕⟫ e₂)
≲-eff ⊑-⟪⊕⟫-right = ≲-refl
≲-effᴴ ⊑-⟪⊕⟫-right = ·⊑-⊕-right
preserves-cases ⊑-⟪⊕⟫-right _ _ = refl
compose-elab : ∀[ (Elaboration η₁ ✴ Elaboration η₂) ⇒ Elaboration (η₁ ·⊕ η₂) ]
compose-elab (e₁ ✴⟨ σ ⟩ e₂) = weaken (≲-∙-left σ) e₁ ⟪⊕⟫ weaken (≲-∙-right σ) e₂