Correct-by-construction programming in Agda

Lecture 2: indexed datatypes and dependent pattern matching

Jesper Cockx

1 September 2019

Recap: correct-by-construction programming

Indices capture invariants

The indices of a datatype capture important invariants of our programs:

  • The length of a list
  • The lower and upper bounds of a search tree
  • The type of a syntax tree (!)

Extrinsic vs intrinsic verification

Two styles of verification:

  • Extrinsic: write a program and then prove its properties
  • Intrinsic: define properties at the type-level and write programs that satisfy them by construction

Intrinsic verification is a good fit for complex programs with simple invariants

For small programs and/or complex invariants, extrinsic verification may work better

Let the types guide you

By encoding invariants in the types, they can guide the construction of our programs:

  • Rule out impossible cases (absurd patterns ())
  • Automatic case splitting (C-c C-c)
  • Program inference (C-c C-a)

Prototype indexed datatype: length-indexed vectors

What are vectors?

If n : ℕ, then Vec A n consists of vectors of As of length n:
data Vec (A : Set) :   Set where
  []  : Vec A 0
  _∷_ :  {n}  A  Vec A n  Vec A (suc n)
Compare to lists:
data List (A : Set) : Set where
  []  : List A
  _∷_ : A  List A  List A

Functions on vectors

Question: what should be the type of head and tail functions on Vec?

How about _++_ (append) and map?

Indexing into vectors

An index into a vector of length n is a number between 0 and n-1:
data Fin :   Set where
  zero :  {n}  Fin (suc n)
  suc  :  {n}  Fin n  Fin (suc n)

lookup :  {A} {n}  Vec A n  Fin n  A
lookup xs i = 

lookup is a total function!

Intrinsically well-typed syntax

Well-typed syntax representation

Our correct-by-construction typechecker produces intrinsically well-typed syntax:

  data Type : Set where
    int bool : Type

  data Exp : Type  Set
    -- ...

A term e : Exp Γ t is a well-typed WHILE expression in context Γ.

Well-typed syntax

  data Op : (dom codom : Type)  Set where
    plus  : Op int  int
    gt    : Op int  bool
    and   : Op bool bool

  data Exp where
    eInt  : (i : )             Exp int
    eBool : (b : Bool)          Exp bool
    eOp   : ∀{t t'} (op : Op t t')
           (e e' : Exp t)      Exp t'

See WellTypedSyntax.agda.

Evaluating well-typed syntax

We can interpret C types as Agda types:
  Val : Type  Set
  Val int  = 
  Val bool = Bool

We can now define eval for well-typed expressions:

  eval :  {t}  Exp t  Val t
  eval = 

that always returns a value (bye bye Maybe!)

See definition of eval in Interpreter.agda.

Dealing with variables

Extending well-typed syntax with variables

A context is a list containing the types of variables in scope
data Type : Set where int bool : Type

Cxt = List Type
A variable is an index into the context
data Var : (Γ : Cxt) (t : Type)  Set where
  here  :  {Γ t}     Var (t  Γ) t
  there :  {Γ t t'}  Var Γ t  Var (t'  Γ) t

(compare this to the definition of Fin)

Well-typed syntax with variables

The type Exp is now parametrized by a context Γ:

data Exp (Γ : Cxt) : Type  Set where
  -- ...
  eVar  : ∀{t} (x : Var Γ t)  Exp Γ t

See WellTypedSyntax.agda.

The All type

All P xs contains an element of P x for each x in the list xs:

data All {A : Set} (P : A  Set) : List A  Set where
  []  : All P []
  _∷_ :  {x xs}  P x  All P xs  All P (x  xs)

Evaluation environments

During evaluation we need a value for All variables
Val : Type  Set
Val int  = 
Val bool = Bool

Env : Cxt  Set
Env Γ = All Val Γ

We can now extend eval to expressions with variables:

eval :  {Γ} {t}  Env Γ  Exp Γ t  Val t
eval = 

See definition of eval in Interpreter.agda.

Exercises

Extend the well-typed syntax and interpreter with the syntactic constructions you added before.