{-# OPTIONS --universe-polymorphism #-}
open import Data.Fin
open import Function
open import Data.Nat
open import Data.Vec as Vec
open import Level
open import Relation.Binary
module Relation.Binary.Reflection
{e a s}
{Expr : ℕ → Set e} {A : Set a}
(Sem : Setoid a s)
(var : ∀ {n} → Fin n → Expr n)
(⟦_⟧ ⟦_⇓⟧ : ∀ {n} → Expr n → Vec A n → Setoid.Carrier Sem)
(correct : ∀ {n} (e : Expr n) ρ →
⟦ e ⇓⟧ ρ ⟨ Setoid._≈_ Sem ⟩ ⟦ e ⟧ ρ)
where
open import Data.Vec.N-ary
open import Data.Product
import Relation.Binary.EqReasoning as Eq
open Setoid Sem
open Eq Sem
prove : ∀ {n} (ρ : Vec A n) e₁ e₂ →
⟦ e₁ ⇓⟧ ρ ≈ ⟦ e₂ ⇓⟧ ρ →
⟦ e₁ ⟧ ρ ≈ ⟦ e₂ ⟧ ρ
prove ρ e₁ e₂ hyp = begin
⟦ e₁ ⟧ ρ ≈⟨ sym (correct e₁ ρ) ⟩
⟦ e₁ ⇓⟧ ρ ≈⟨ hyp ⟩
⟦ e₂ ⇓⟧ ρ ≈⟨ correct e₂ ρ ⟩
⟦ e₂ ⟧ ρ ∎
close : ∀ {A} n → N-ary n (Expr n) A → A
close n f = f $ⁿ Vec.map var (allFin n)
solve : ∀ n (f : N-ary n (Expr n) (Expr n × Expr n)) →
Eqʰ n _≈_ (curryⁿ ⟦ proj₁ (close n f) ⇓⟧) (curryⁿ ⟦ proj₂ (close n f) ⇓⟧) →
Eq n _≈_ (curryⁿ ⟦ proj₁ (close n f) ⟧) (curryⁿ ⟦ proj₂ (close n f) ⟧)
solve n f hyp =
curryⁿ-cong ⟦ proj₁ (close n f) ⟧ ⟦ proj₂ (close n f) ⟧
(λ ρ → prove ρ (proj₁ (close n f)) (proj₂ (close n f))
(curryⁿ-cong⁻¹ ⟦ proj₁ (close n f) ⇓⟧ ⟦ proj₂ (close n f) ⇓⟧
(Eqʰ-to-Eq n hyp) ρ))
infix 4 _⊜_
_⊜_ : ∀ {n} → Expr n → Expr n → Expr n × Expr n
_⊜_ = _,_