{-# OPTIONS --sized-types #-}

module A201607.WIP2.BasicICML.Sketch where

open import A201607.BasicICML.Syntax.DyadicGentzen public


-- Let us assume some types X and Y, and a function foo from X to Y.
postulate
  X : Ty
  Y : Ty
  foo : ∀ {Γ Δ} → Γ ⁏ Δ ⊢ X ▻ Y

-- We can construct a term of type Y under the assumption that we have a term of type X.
-- In other words, we can construct a term with a free variable, or an open term.
a1 : ∀ {Γ Δ} → Γ , X ⁏ Δ ⊢ Y
a1 = app foo v₀

-- We can also construct a term of type Y under the assumption that we have a quoted term of type X.
-- In other words, we can construct a term with a free metavariable.
a2 : ∀ {Γ Δ} → Γ ⁏ Δ , [ ∅ ] X ⊢ Y
a2 = app foo (mv₀ ∙)

-- We can quote terms with free variables, because we track free variables in the type.
b1 : ∀ {Γ Δ} → Γ ⁏ Δ ⊢ [ ∅ , X ] Y
b1 = box (app foo v₀)

-- We can also quote terms with free metavariables, as long as we can supply these metavariables.
b2 : ∀ {Γ Δ} → Γ ⁏ Δ , [ ∅ ] X ⊢ [ ∅ ] Y
b2 = box (app foo (mv₀ ∙))


-- Now, let us assume a value of type X.
postulate
  bar : ∀ {Γ Δ} → Γ ⁏ Δ ⊢ X

-- To construct a term of type Y, we can apply foo directly.
c1 : ∀ {Γ Δ} → Γ ⁏ Δ ⊢ Y
c1 = app foo bar

-- We can also close the open term and apply the result.
c2 : ∀ {Γ Δ} → Γ ⁏ Δ ⊢ Y
c2 = app (lam a1) bar

-- We can also bind a metavariable to our value of type X.
-- This could be a way to implement let-bindings.
-- Note that the
c3 : ∀ {Γ Δ} → Γ ⁏ Δ ⊢ Y
c3 = unbox {Ψ = ∅} (box bar) (app foo (mv₀ ∙))

-- We can simply quote a closed term.
d1 : ∀ {Γ Δ} → Γ ⁏ Δ ⊢ [ ∅ ] Y
d1 = box (app foo bar)

d2 : ∀ {Γ Δ} → Γ ⁏ Δ ⊢ [ ∅ ] Y
d2 = unbox {Ψ = ∅} (box bar) (box (app foo (mv₀ ∙)))