added test cases

This commit is contained in:
wadler 2018-05-18 12:43:53 -03:00
parent dce878d6e8
commit 67d27d0843

View file

@ -62,238 +62,228 @@ Id : Set
Id = String
\end{code}
### Lists of identifiers
## Syntax
\begin{code}
open Collections (Id) (_≟_)
infix 4 _∋_`:_
infix 4 _⊢_↑_
infix 4 _⊢_↓_
infixl 5 _,_`:_
infix 5 _`:_
infixr 6 _`→_
infix 6 `λ_`→_
infix 6 `μ_`→_
infixl 9 _·_
data Type : Set where
` : Type
_`→_ : Type → Type → Type
data Ctx : Set where
ε : Ctx
_,_`:_ : Ctx → Id → Type → Ctx
data Term : Set where
⌊_⌋ : Id → Term
`λ_`→_ : Id → Term → Term
_·_ : Term → Term → Term
`zero : Term
`suc : Term → Term
`case_[`zero`→_|`suc_`→_] : Term → Term → Id → Term → Term
`μ_`→_ : Id → Term → Term
_`:_ : Term → Type → Term
\end{code}
## First development: Raw
## Example terms
\begin{code}
module Raw where
\end{code}
two : Term
two = `suc (`suc `zero) `: `
### Syntax
plus : Term
plus = (`μ "p" `→ `λ "m" `→ `λ "n" `→
`case ⌊ "m" ⌋ [`zero`→ ⌊ "n" ⌋
|`suc "m" `→ `suc (⌊ "p" ⌋ · ⌊ "m" ⌋) · ⌊ "n" ⌋ ])
`: ` `→ `
\begin{code}
infix 4 _∋_`:_
infix 4 _⊢_↑_
infix 4 _⊢_↓_
infixl 5 _,_`:_
infix 5 _`:_
infixr 6 _`→_
infix 6 `λ_`→_
infix 6 `μ_`→_
infixl 9 _·_
four : Term
four = plus · two · two
data Type : Set where
` : Type
_`→_ : Type → Type → Type
Ch : Type
Ch = (` `→ `) `→ ` `→ `
data Ctx : Set where
ε : Ctx
_,_`:_ : Ctx → Id → Type → Ctx
twoCh : Term
twoCh = (`λ "s" `→ `λ "z" `→ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) `: Ch
data Term : Set where
⌊_⌋ : Id → Term
`λ_`→_ : Id → Term → Term
_·_ : Term → Term → Term
`zero : Term
`suc : Term → Term
`case_[`zero`→_|`suc_`→_] : Term → Term → Id → Term → Term
`μ_`→_ : Id → Term → Term
_`:_ : Term → Type → Term
\end{code}
### Example terms
\begin{code}
Ch : Type
Ch = (` `→ `) `→ ` `→ `
two : Term
two = (`λ "s" `→ `λ "z" `→ ⌊ "s" ⌋ · (⌊ "s" ⌋ · ⌊ "z" ⌋)) `: Ch
plus : Term
plus = (`λ "m" `→ `λ "n" `→ `λ "s" `→ `λ "z" `→
plusCh : Term
plusCh = (`λ "m" `→ `λ "n" `→ `λ "s" `→ `λ "z" `→
⌊ "m" ⌋ · ⌊ "s" ⌋ · (⌊ "n" ⌋ · ⌊ "s" ⌋ · ⌊ "z" ⌋))
`: Ch `→ Ch `→ Ch
`: Ch `→ Ch `→ Ch
norm : Term
norm = (`λ "m" `→ ⌊ "m" ⌋ · (`λ "x" `→ `suc ⌊ "x" ⌋) · `zero)
`: Ch `→ `
fromCh : Term
fromCh = (`λ "m" `→ ⌊ "m" ⌋ · (`λ "x" `→ `suc ⌊ "x" ⌋) · `zero)
`: Ch `→ `
four : Term
four = norm · (plus · two · two)
fourCh : Term
fourCh = fromCh · (plusCh · twoCh · twoCh)
\end{code}
### Bidirectional type checking
## Bidirectional type checking
\begin{code}
data _∋_`:_ : Ctx → Id → Type → Set where
data _∋_`:_ : Ctx → Id → Type → Set where
Z : ∀ {Γ x A}
--------------------
→ Γ , x `: A ∋ x `: A
Z : ∀ {Γ x A}
--------------------
→ Γ , x `: A ∋ x `: A
S : ∀ {Γ w x A B}
→ w ≢ x
→ Γ ∋ w `: B
--------------------
→ Γ , x `: A ∋ w `: B
S : ∀ {Γ w x A B}
→ w ≢ x
→ Γ ∋ w `: B
--------------------
→ Γ , x `: A ∋ w `: B
data _⊢_↑_ : Ctx → Term → Type → Set
data _⊢_↓_ : Ctx → Term → Type → Set
data _⊢_↑_ : Ctx → Term → Type → Set
data _⊢_↓_ : Ctx → Term → Type → Set
data _⊢_↑_ where
data _⊢_↑_ where
Ax : ∀ {Γ A x}
→ Γ ∋ x `: A
--------------
→ Γ ⊢ ⌊ x ⌋ ↑ A
Ax : ∀ {Γ A x}
→ Γ ∋ x `: A
--------------
→ Γ ⊢ ⌊ x ⌋ ↑ A
_·_ : ∀ {Γ L M A B}
→ Γ ⊢ L ↑ A `→ B
→ Γ ⊢ M ↑ A
---------------
→ Γ ⊢ L · M ↑ B
_·_ : ∀ {Γ L M A B}
→ Γ ⊢ L ↑ A `→ B
→ Γ ⊢ M ↑ A
---------------
→ Γ ⊢ L · M ↑ B
↑↓ : ∀ {Γ M A}
→ Γ ⊢ M ↓ A
----------------
→ Γ ⊢ M `: A ↑ A
↑↓ : ∀ {Γ M A}
→ Γ ⊢ M ↓ A
----------------
→ Γ ⊢ M `: A ↑ A
data _⊢_↓_ where
data _⊢_↓_ where
⊢λ : ∀ {Γ x N A B}
→ Γ , x `: A ⊢ N ↓ B
-----------------------
→ Γ ⊢ `λ x `→ N ↓ A `→ B
⊢λ : ∀ {Γ x N A B}
→ Γ , x `: A ⊢ N ↓ B
-----------------------
→ Γ ⊢ `λ x `→ N ↓ A `→ B
⊢zero : ∀ {Γ}
---------------
→ Γ ⊢ `zero ↓ `
⊢zero : ∀ {Γ}
---------------
→ Γ ⊢ `zero ↓ `
⊢suc : ∀ {Γ M}
→ Γ ⊢ M ↓ `
----------------
→ Γ ⊢ `suc M ↓ `
⊢suc : ∀ {Γ M}
→ Γ ⊢ M ↓ `
----------------
→ Γ ⊢ `suc M ↓ `
⊢case : ∀ {Γ L M x N A}
→ Γ ⊢ L ↑ `
→ Γ ⊢ M ↓ A
→ Γ , x `: ` ⊢ N ↓ A
------------------------------------------
→ Γ ⊢ `case L [`zero`→ M |`suc x `→ N ] ↓ A
⊢case : ∀ {Γ L M x N A}
→ Γ ⊢ L ↑ `
→ Γ ⊢ M ↓ A
→ Γ , x `: ` ⊢ N ↓ A
------------------------------------------
→ Γ ⊢ `case L [`zero`→ M |`suc x `→ N ] ↓ A
⊢μ : ∀ {Γ x N A}
→ Γ , x `: A ⊢ N ↓ A
-----------------------
→ Γ ⊢ `μ x `→ N ↓ A
⊢μ : ∀ {Γ x N A}
→ Γ , x `: A ⊢ N ↓ A
-----------------------
→ Γ ⊢ `μ x `→ N ↓ A
↓↑ : ∀ {Γ M A}
→ Γ ⊢ M ↑ A
----------
→ Γ ⊢ M ↓ A
↓↑ : ∀ {Γ M A}
→ Γ ⊢ M ↑ A
----------
→ Γ ⊢ M ↓ A
\end{code}
## Type checking monad
\begin{code}
Msg : Set
Msg = String
Msg : Set
Msg = String
data Error : Set where
err : Msg → Term → List Type → Error
data TC (A : Set) : Set where
error : Msg → Term → List Type → TC A
return : A → TC A
TC : Set → Set
TC A = Error ⊎ A
error : ∀ {A : Set} → Msg → Term → List Type → TC A
error msg M As = inj₁ (err msg M As)
return : ∀ {A : Set} → A → TC A
return = inj₂
_>>=_ : ∀ {A B : Set} → TC A → (A → TC B) → TC B
inj₁ e >>= k = inj₁ e
inj₂ x >>= k = k x
_>>=_ : ∀ {A B : Set} → TC A → (A → TC B) → TC B
error msg M As >>= k = error msg M As
return v >>= k = k v
\end{code}
## Type inferencer
\begin{code}
_≟Tp_ : (A B : Type) → Dec (A ≡ B)
A ≟Tp B = {!!}
_≟Tp_ : (A B : Type) → Dec (A ≡ B)
A ≟Tp B = {!!}
data Lookup (Γ : Ctx) (x : Id) : Set where
ok : ∀ (A : Type) → (Γ ∋ x `: A) → Lookup Γ x
data Lookup (Γ : Ctx) (x : Id) : Set where
ok : ∀ (A : Type) → (Γ ∋ x `: A) → Lookup Γ x
lookup : ∀ (Γ : Ctx) (x : Id) → TC (Lookup Γ x)
lookup ε x =
error "variable not bound" ⌊ x ⌋ []
lookup (Γ , x `: A) w with w ≟ x
... | yes refl =
return (ok A Z)
... | no w≢ =
do ok A ⊢x ← lookup Γ w
return (ok A (S w≢ ⊢x))
lookup : ∀ (Γ : Ctx) (x : Id) → TC (Lookup Γ x)
lookup ε x =
error "variable not bound" ⌊ x ⌋ []
lookup (Γ , x `: A) w with w ≟ x
... | yes refl =
return (ok A Z)
... | no w≢ =
do ok A ⊢x ← lookup Γ w
return (ok A (S w≢ ⊢x))
data Synth (Γ : Ctx) (M : Term) : Set where
ok : ∀ (A : Type) → (Γ ⊢ M ↑ A) → Synth Γ M
synth : ∀ (Γ : Ctx) (M : Term) → TC (Synth Γ M)
inher : ∀ (Γ : Ctx) (M : Term) (A : Type) → TC (Γ ⊢ M ↓ A)
data Synthesize (Γ : Ctx) (M : Term) : Set where
ok : ∀ (A : Type) → (Γ ⊢ M ↑ A) → Synthesize Γ M
synth Γ ⌊ x ⌋ =
do ok A ⊢x ← lookup Γ x
return (ok A (Ax ⊢x))
synth Γ (L · M) =
do ok (A₀ `→ B) ⊢L ← synth Γ L
where ok ` _ → error "must apply function" (L · M) []
ok A₁ ⊢M ← synth Γ M
yes refl ← return (A₀ ≟Tp A₁)
where no _ → error "types differ in application" (L · M) [ A₀ , A₁ ]
return (ok B (⊢L · ⊢M))
synth Γ (M `: A) =
do ⊢M ← inher Γ M A
return (ok A (↑↓ ⊢M))
{-# CATCHALL #-}
synth Γ M =
error "untypable term" M []
synthesize : ∀ (Γ : Ctx) (M : Term) → TC (Synthesize Γ M)
inherit : ∀ (Γ : Ctx) (M : Term) (A : Type) → TC (Γ ⊢ M ↓ A)
inher Γ (`λ x `→ N) (A `→ B) =
do ⊢N ← inher (Γ , x `: A) N B
return (⊢λ ⊢N)
inher Γ (`λ x `→ N) ` =
error "lambda cannot be natural" (`λ x `→ N) []
inher Γ `zero ` =
return ⊢zero
inher Γ `zero (A `→ B) =
error "zero cannot be function" `zero [ A `→ B ]
inher Γ (`suc M) ` =
do ⊢M ← inher Γ M `
return (⊢suc ⊢M)
inher Γ (`suc M) (A `→ B) =
error "suc cannot be function" (`suc M) [ A `→ B ]
inher Γ `case L [`zero`→ M |`suc x `→ N ] A =
do ok ` ⊢L ← synth Γ L
where ok (A `→ B) _ → error "cannot case on function"
(`case L [`zero`→ M |`suc x `→ N ])
[ A `→ B ]
⊢M ← inher Γ M A
⊢N ← inher (Γ , x `: `) N A
return (⊢case ⊢L ⊢M ⊢N)
inher Γ (`μ x `→ M) A =
do ⊢M ← inher (Γ , x `: A) M A
return (⊢μ ⊢M)
{-# CATCHALL #-}
inher Γ M A₀ =
do ok A₁ ⊢M ← synth Γ M
yes refl ← return (A₀ ≟Tp A₁)
where no _ → error "inheritance and synthesis conflict" M [ A₀ , A₁ ]
return (↓↑ ⊢M)
synthesize Γ ⌊ x ⌋ =
do ok A ⊢x ← lookup Γ x
return (ok A (Ax ⊢x))
synthesize Γ (L · M) =
do ok (A₀ `→ B) ⊢L ← synthesize Γ L
where ok ` _ → error "must apply function" (L · M) []
ok A₁ ⊢M ← synthesize Γ M
yes refl ← return (A₀ ≟Tp A₁)
where no _ → error "types differ in application" (L · M) [ A₀ , A₁ ]
return (ok B (⊢L · ⊢M))
synthesize Γ (M `: A) =
do ⊢M ← inherit Γ M A
return (ok A (↑↓ ⊢M))
{-# CATCHALL #-}
synthesize Γ M =
error "cannot synthesize type for term" M []
inherit Γ (`λ x `→ N) (A `→ B) =
do ⊢N ← inherit (Γ , x `: A) N B
return (⊢λ ⊢N)
inherit Γ (`λ x `→ N) ` =
error "lambda cannot be natural" (`λ x `→ N) []
inherit Γ `zero ` =
return ⊢zero
inherit Γ `zero (A `→ B) =
error "zero cannot be function" `zero [ A `→ B ]
inherit Γ (`suc M) ` =
do ⊢M ← inherit Γ M `
return (⊢suc ⊢M)
inherit Γ (`suc M) (A `→ B) =
error "suc cannot be function" (`suc M) [ A `→ B ]
inherit Γ `case L [`zero`→ M |`suc x `→ N ] A =
do ok ` ⊢L ← synthesize Γ L
where ok (A `→ B) _ → error "cannot case on function"
(`case L [`zero`→ M |`suc x `→ N ])
[ A `→ B ]
⊢M ← inherit Γ M A
⊢N ← inherit (Γ , x `: `) N A
return (⊢case ⊢L ⊢M ⊢N)
inherit Γ (`μ x `→ M) A =
do ⊢M ← inherit (Γ , x `: A) M A
return (⊢μ ⊢M)
{-# CATCHALL #-}
inherit Γ M A₀ =
do ok A₁ ⊢M ← synthesize Γ M
yes refl ← return (A₀ ≟Tp A₁)
where no _ → error "inheritance and synthesis conflict" M [ A₀ , A₁ ]
return (↓↑ ⊢M)
\end{code}