{-# OPTIONS --safe #-} module Interface.ComputationalRelation where open import Prelude open import Interface.STS public private variable a : Level C S Sig : Type Err Err₁ Err₂ : Type c : C s s' s'' : S sig : Sig data ComputationResult {a : Level} (Err : Type) (R : Type a) : Type a where success : R → ComputationResult Err R failure : Err → ComputationResult Err R isFailure : ∀ {A : Type a} → ComputationResult Err A → Type a isFailure x = ∃[ e ] x ≡ failure e module _ {a b} {E : Type} {A : Type a} {B : Type b} where caseCR_∣_∣_ : (ma : ComputationResult E A) → (∀ {a} → ma ≡ success a → B) → (isFailure ma → B) → B caseCR ma ∣ f ∣ g with ma ... | success _ = f refl ... | failure e = g (e , refl) caseCR-success : ∀ {a} {ma : ComputationResult E A} {f : ∀ {a} → ma ≡ success a → B} {g : isFailure ma → B} → (eq : ma ≡ success a) → caseCR ma ∣ f ∣ g ≡ f eq caseCR-success refl = refl caseCR-failure : {ma : ComputationResult E A} {f : ∀ {a} → ma ≡ success a → B} {g : isFailure ma → B} → (eq : isFailure ma) → caseCR ma ∣ f ∣ g ≡ g eq caseCR-failure (_ , refl) = refl instance Bifunctor-ComputationResult : ∀ {a : Level} → Bifunctor {_} {a} ComputationResult Bifunctor-ComputationResult .bimap _ f (success x) = success $ f x Bifunctor-ComputationResult .bimap f _ (failure x) = failure $ f x Functor-ComputationResult : ∀ {E : Type} → Functor (ComputationResult E) Functor-ComputationResult ._<$>_ f (success x) = success $ f x Functor-ComputationResult ._<$>_ _ (failure x) = failure x Applicative-ComputationResult : ∀ {E : Type} → Applicative (ComputationResult E) Applicative-ComputationResult .pure = success Applicative-ComputationResult ._<*>_ (success f) x = f <$> x Applicative-ComputationResult ._<*>_ (failure e) _ = failure e Monad-ComputationResult : ∀ {E : Type} → Monad (ComputationResult E) Monad-ComputationResult .return = success Monad-ComputationResult ._>>=_ (success a) m = m a Monad-ComputationResult ._>>=_ (failure e) _ = failure e map-failure : ∀ {A B C : Type} {f : A → B} {x : C} {ma} → ma ≡ failure x → map f ma ≡ failure x map-failure refl = refl success-maybe : ∀ {R : Type} → ComputationResult Err R → Maybe R success-maybe (success x) = just x success-maybe (failure _) = nothing failure-maybe : ∀ {R : Type} → ComputationResult Err R → Maybe Err failure-maybe (success _) = nothing failure-maybe (failure x) = just x _≈ᶜʳ_ : ∀ {A} → ComputationResult Err A → ComputationResult Err A → Type x ≈ᶜʳ y = success-maybe x ≡ success-maybe y module _ (STS : C → S → Sig → S → Type) where ExtendedRel : C → S → Sig → ComputationResult Err S → Type ExtendedRel c s sig (success s') = STS c s sig s' ExtendedRel c s sig (failure _ ) = ∀ s' → ¬ STS c s sig s' record Computational Err : Type₁ where constructor MkComputational field computeProof : (c : C) (s : S) (sig : Sig) → ComputationResult Err (∃[ s' ] STS c s sig s') compute : C → S → Sig → ComputationResult Err S compute c s sig = map proj₁ $ computeProof c s sig field completeness : (c : C) (s : S) (sig : Sig) (s' : S) → STS c s sig s' → compute c s sig ≡ success s' open ≡-Reasoning computeFail : C → S → Sig → Type computeFail c s sig = isFailure $ compute c s sig ≡-success⇔STS : compute c s sig ≡ success s' ⇔ STS c s sig s' ≡-success⇔STS {c} {s} {sig} {s'} with computeProof c s sig in eq ... | success (s'' , h) = mk⇔ (λ where refl → h) λ h' → begin success s'' ≡˘⟨ completeness _ _ _ _ h ⟩ compute c s sig ≡⟨ completeness _ _ _ _ h' ⟩ success s' ∎ ... | failure y = mk⇔ (λ ()) λ h → begin failure _ ≡˘⟨ map-failure eq ⟩ compute c s sig ≡⟨ completeness _ _ _ _ h ⟩ success s' ∎ failure⇒∀¬STS : computeFail c s sig → ∀ s' → ¬ STS c s sig s' failure⇒∀¬STS comp≡nothing s' h rewrite ≡-success⇔STS .Equivalence.from h = case comp≡nothing of λ () ∀¬STS⇒failure : (∀ s' → ¬ STS c s sig s') → computeFail c s sig ∀¬STS⇒failure {c = c} {s} {sig} ¬sts with computeProof c s sig ... | success (x , y) = ⊥-elim (¬sts x y) ... | failure y = (y , refl) failure⇔∀¬STS : computeFail c s sig ⇔ ∀ s' → ¬ STS c s sig s' failure⇔∀¬STS = mk⇔ failure⇒∀¬STS ∀¬STS⇒failure recomputeProof : ∀ {Γ s sig s'} → STS Γ s sig s' → ComputationResult Err (∃[ s'' ] STS Γ s sig s'') recomputeProof _ = computeProof _ _ _ module _ {STS : C → S → Sig → S → Type} (comp : Computational STS Err) where open Computational comp ExtendedRelSTS = ExtendedRel STS ExtendedRel-compute : ExtendedRelSTS c s sig (compute c s sig) ExtendedRel-compute {c} {s} {sig} with compute c s sig in eq ... | success s' = Equivalence.to ≡-success⇔STS eq ... | failure _ = λ s' h → case trans (sym $ Equivalence.from ≡-success⇔STS h) eq of λ () open ≡-Reasoning ExtendedRel-rightUnique : ExtendedRelSTS c s sig s' → ExtendedRelSTS c s sig s'' → _≈ᶜʳ_ {Err = Err} s' s'' ExtendedRel-rightUnique {s' = success x} {success x'} h h' with trans (sym $ Equivalence.from ≡-success⇔STS h) (Equivalence.from ≡-success⇔STS h') ... | refl = refl ExtendedRel-rightUnique {s' = success x} {failure _} h h' = ⊥-elim $ h' x h ExtendedRel-rightUnique {s' = failure _} {success x'} h h' = ⊥-elim $ h x' h' ExtendedRel-rightUnique {s' = failure a} {failure b} h h' = refl computational⇒rightUnique : STS c s sig s' → STS c s sig s'' → s' ≡ s'' computational⇒rightUnique h h' with ExtendedRel-rightUnique h h' ... | refl = refl Computational⇒Dec : ⦃ _ : DecEq S ⦄ → Dec (STS c s sig s') Computational⇒Dec {c} {s} {sig} {s'} with compute c s sig | ExtendedRel-compute {c} {s} {sig} ... | failure _ | ExSTS = no (ExSTS s') ... | success x | ExSTS with x ≟ s' ... | no ¬p = no λ h → ¬p $ sym $ computational⇒rightUnique h ExSTS ... | yes refl = yes ExSTS module _ {STS : C → S → Sig → S → Type} (comp comp' : Computational STS Err) where open Computational comp renaming (compute to compute₁) open Computational comp' renaming (compute to compute₂) compute-ext≡ : compute₁ c s sig ≈ᶜʳ compute₂ c s sig compute-ext≡ = ExtendedRel-rightUnique comp (ExtendedRel-compute comp) (ExtendedRel-compute comp') open Computational ⦃...⦄ Computational⇒Dec' : {STS : C → S → Sig → S → Type} ⦃ comp : Computational STS Err ⦄ → Dec (∃[ s' ] STS c s sig s') Computational⇒Dec' with computeProof _ _ _ in eq ... | success x = yes x ... | failure x = no λ (_ , h) → failure⇒∀¬STS (-, cong (map proj₁) eq) _ h record InjectError Err₁ Err₂ : Type where field injectError : Err₁ → Err₂ open InjectError instance InjectError-⊥ : InjectError ⊥ Err InjectError-⊥ = λ where .injectError () InjectError-Id : InjectError Err Err InjectError-Id = λ where .injectError → id Computational-Id : {C S : Type} → Computational (IdSTS {C} {S}) ⊥ Computational-Id .computeProof _ s _ = success (s , Id-nop) Computational-Id .completeness _ _ _ _ Id-nop = refl module _ {BSTS : C → S → ⊤ → S → Type} ⦃ _ : Computational BSTS Err₁ ⦄ where module _ {STS : C → S → Sig → S → Type} ⦃ _ : Computational STS Err₂ ⦄ ⦃ _ : InjectError Err₁ Err ⦄ ⦃ _ : InjectError Err₂ Err ⦄ where instance Computational-ReflexiveTransitiveClosureᵇ : Computational (ReflexiveTransitiveClosureᵇ {_⊢_⇀⟦_⟧ᵇ_ = BSTS}{STS}) (Err) Computational-ReflexiveTransitiveClosureᵇ .computeProof c s [] = bimap (injectError it) (map₂′ BS-base) (computeProof c s tt) Computational-ReflexiveTransitiveClosureᵇ .computeProof c s (sig ∷ sigs) with computeProof c s sig ... | success (s₁ , h) with computeProof c s₁ sigs ... | success (s₂ , hs) = success (s₂ , BS-ind h hs) ... | failure a = failure (injectError it a) Computational-ReflexiveTransitiveClosureᵇ .computeProof c s (sig ∷ sigs) | failure a = failure (injectError it a) Computational-ReflexiveTransitiveClosureᵇ .completeness c s [] s' (BS-base p) with computeProof {STS = BSTS} c s tt | completeness _ _ _ _ p ... | success x | refl = refl Computational-ReflexiveTransitiveClosureᵇ .completeness c s (sig ∷ sigs) s' (BS-ind h hs) with computeProof c s sig | completeness _ _ _ _ h ... | success (s₁ , _) | refl with computeProof ⦃ Computational-ReflexiveTransitiveClosureᵇ ⦄ c s₁ sigs | completeness _ _ _ _ hs ... | success (s₂ , _) | p = p module _ {STS : C × ℕ → S → Sig → S → Type} ⦃ Computational-STS : Computational STS Err₂ ⦄ ⦃ InjectError-Err₁ : InjectError Err₁ Err ⦄ ⦃ InjectError-Err₂ : InjectError Err₂ Err ⦄ where instance Computational-ReflexiveTransitiveClosureᵢᵇ' : Computational (_⊢_⇀⟦_⟧ᵢ*'_ {_⊢_⇀⟦_⟧ᵇ_ = BSTS}{STS}) Err Computational-ReflexiveTransitiveClosureᵢᵇ' .computeProof c s [] = bimap (injectError it) (map₂′ BS-base) (computeProof (proj₁ c) s tt) Computational-ReflexiveTransitiveClosureᵢᵇ' .computeProof c s (sig ∷ sigs) with computeProof c s sig ... | success (s₁ , h) with computeProof (proj₁ c , suc (proj₂ c)) s₁ sigs ... | success (s₂ , hs) = success (s₂ , BS-ind h hs) ... | failure a = failure a Computational-ReflexiveTransitiveClosureᵢᵇ' .computeProof c s (sig ∷ sigs) | failure a = failure (injectError it a) Computational-ReflexiveTransitiveClosureᵢᵇ' .completeness c s [] s' (BS-base p) with computeProof {STS = BSTS} (proj₁ c) s tt | completeness _ _ _ _ p ... | success x | refl = refl Computational-ReflexiveTransitiveClosureᵢᵇ' .completeness c s (sig ∷ sigs) s' (BS-ind h hs) with computeProof {STS = STS} c s sig | completeness _ _ _ _ h ... | success (s₁ , _) | refl with computeProof (proj₁ c , suc (proj₂ c)) s₁ sigs | completeness _ _ _ _ hs ... | success (s₂ , _) | p = p Computational-ReflexiveTransitiveClosureᵢᵇ : Computational (ReflexiveTransitiveClosureᵢᵇ {_⊢_⇀⟦_⟧ᵇ_ = BSTS}{STS}) Err Computational-ReflexiveTransitiveClosureᵢᵇ .computeProof c = Computational-ReflexiveTransitiveClosureᵢᵇ' .computeProof (c , 0) Computational-ReflexiveTransitiveClosureᵢᵇ .completeness c = Computational-ReflexiveTransitiveClosureᵢᵇ' .completeness (c , 0) module _ {BSTS : C → S → ⊤ → S → Type} ⦃ _ : Computational BSTS Err₁ ⦄ where module _ {STS : C → S → Sig → S → Type} ⦃ _ : Computational STS Err₂ ⦄ ⦃ _ : InjectError Err₁ Err ⦄ ⦃ _ : InjectError Err₂ Err ⦄ where instance Computational-ReflexiveTransitiveClosureᵇ' : Computational (ReflexiveTransitiveClosureᵇ' {_⊢_⇀⟦_⟧ᵇ_ = BSTS} {STS}) (Err) Computational-ReflexiveTransitiveClosureᵇ' .computeProof c s sigs with (computeProof{STS = BSTS} c s tt) ... | failure a = failure (injectError it a) ... | success (s' , h) with (computeProof{STS = ReflexiveTransitiveClosureᵇ {_⊢_⇀⟦_⟧ᵇ_ = IdSTS} {STS}} c s' sigs) ... | failure a = failure a ... | success (s' , hs) = success (s' , (RTC (h , hs))) Computational-ReflexiveTransitiveClosureᵇ' .completeness c s sigs s'' (RTC (bsts , sts)) with (computeProof {STS = BSTS} c s tt) | completeness _ _ _ _ bsts ... | success (s₁ , h) | refl with computeProof {STS = ReflexiveTransitiveClosureᵇ {_⊢_⇀⟦_⟧ᵇ_ = IdSTS} {STS}}{Err} c s₁ sigs | completeness {Err = Err} _ _ _ _ sts ... | success (s₂ , _) | p = p Computational-ReflexiveTransitiveClosure : {STS : C → S → Sig → S → Type} → ⦃ Computational STS Err ⦄ → Computational (ReflexiveTransitiveClosure {sts = STS}) Err Computational-ReflexiveTransitiveClosure = it Computational-ReflexiveTransitiveClosureᵢ : {STS : C × ℕ → S → Sig → S → Type} → ⦃ Computational STS Err ⦄ → Computational (ReflexiveTransitiveClosureᵢ {sts = STS}) Err Computational-ReflexiveTransitiveClosureᵢ = it