60
An Algebraic Approach to Typechecking and Elaboration Robert Atkey [email protected] Wednesday 18th February 2015

An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

AnAlgebraic Approach

toTypechecking and Elaboration

Robert [email protected]

Wednesday 18th February 2015

Page 2: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s write a typechecker

Page 3: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s write a typechecker

Page 4: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s write a typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

Page 5: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s write a typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

Page 6: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s write a typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

typecheck :: Term→ [Type]→ Maybe Type

Page 7: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s write a typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

typecheck :: Term→ [Type]→ Maybe Typetypecheck (Var i) ctxt = Just (ctxt !! i)

Page 8: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s write a typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

typecheck :: Term→ [Type]→ Maybe Typetypecheck (Var i) ctxt = Just (ctxt !! i)typecheck (Lam ty tm) ctxt = case typecheck tm (ty:ctxt) of

Just ty′ → Just (ty⇒ ty′)Nothing→ Nothing

Page 9: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s write a typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

typecheck :: Term→ [Type]→ Maybe Typetypecheck (Var i) ctxt = Just (ctxt !! i)typecheck (Lam ty tm) ctxt = case typecheck tm (ty:ctxt) of

Just ty′ → Just (ty⇒ ty′)Nothing→ Nothing

typecheck (App tm1 tm2) ctxt = case typecheck tm1 ctxt ofJust (ty1 ⇒ ty2)→

case typecheck tm2 ctxt ofJust ty′1 | ty1 ≡ ty′1 → Just ty2_→ Nothing

_→ Nothing

Page 10: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s take a typechecker to bits

Page 11: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s take a Typechecker to bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

Page 12: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s take a Typechecker to bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

type TypeChecker = [Type]→ Maybe Type

Page 13: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s take a Typechecker to bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

type TypeChecker = [Type]→ Maybe Type

typecheck :: Term→ TypeChecker

Page 14: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s take a Typechecker to bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

type TypeChecker = [Type]→ Maybe Type

typecheck :: Term→ TypeCheckertypecheck (Var i) = var i

Page 15: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s take a Typechecker to bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

type TypeChecker = [Type]→ Maybe Type

typecheck :: Term→ TypeCheckertypecheck (Var i) = var itypecheck (Lam ty tm) = lam ty (typecheck tm)

Page 16: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Let’s take a Typechecker to bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

data Term = Var Int | Lam Type Term | App Term Term

type TypeChecker = [Type]→ Maybe Type

typecheck :: Term→ TypeCheckertypecheck (Var i) = var itypecheck (Lam ty tm) = lam ty (typecheck tm)typecheck (App tm1 tm2) = app (typecheck tm1) (typecheck tm2)

Page 17: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bits of a Typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

type TypeChecker = [Type]→ Maybe Type

Page 18: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bits of a Typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

type TypeChecker = [Type]→ Maybe Type

var :: Int→ TypeCheckervar i = λctxt→ Just (ctxt !! i)

Page 19: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bits of a Typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

type TypeChecker = [Type]→ Maybe Type

var :: Int→ TypeCheckervar i = λctxt→ Just (ctxt !! i)

lam :: Type→ TypeChecker→ TypeCheckerlam ty tc = case typecheck tm (ty:ctxt) of

Just ty′ → Just (ty⇒ ty′); Nothing→ Nothing

Page 20: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bits of a Typecheckerdata Type = A | B | C | Type⇒ Type deriving (Eq)

type TypeChecker = [Type]→ Maybe Type

var :: Int→ TypeCheckervar i = λctxt→ Just (ctxt !! i)

lam :: Type→ TypeChecker→ TypeCheckerlam ty tc = case typecheck tm (ty:ctxt) of

Just ty′ → Just (ty⇒ ty′); Nothing→ Nothing

app :: TypeChecker→ TypeChecker→ TypeCheckerapp tc1 tc2 = λctxt→ case tc1 ctxt of

Just (ty1 ⇒ ty2)→case tc2 ctxt of

Just ty′1 | ty1 ≡ ty′1 → Just ty2_→ Nothing

_→ Nothing

Page 21: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Typechecker Scripts

With these bits, we can write typechecker scripts.

A term: “λf :A⇒ B. λa:A. f a”& its typechecker: lam (A⇒ B) (lam A (app (var 1) (var 0)))

A term family: “λf :A⇒ B. λa:A. [−]”& its typechecker: λx. lam (A⇒ B) (lam A x)

Page 22: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

More Typechecker Bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

type TypeChecker = [Type]→ Maybe Type

Page 23: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

More Typechecker Bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

type TypeChecker = [Type]→ Maybe Type

failure :: TypeCheckerfailure = λctxt→ Nothing

Page 24: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

More Typechecker Bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

type TypeChecker = [Type]→ Maybe Type

failure :: TypeCheckerfailure = λctxt→ Nothing

have :: Int→ Type→ TypeChecker→ TypeCheckerhave i ty tc = λctxt→ if ctxt !! i ≡ ty then tc ctxt else Nothing

Page 25: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

More Typechecker Bitsdata Type = A | B | C | Type⇒ Type deriving (Eq)

type TypeChecker = [Type]→ Maybe Type

failure :: TypeCheckerfailure = λctxt→ Nothing

have :: Int→ Type→ TypeChecker→ TypeCheckerhave i ty tc = λctxt→ if ctxt !! i ≡ ty then tc ctxt else Nothing

hasType :: Type→ TypeChecker→ TypeCheckerhasType ty tc = λctxt→ case tc ctxt of

Just ty′ | ty ≡ ty′ → Just ty_→ Nothing

Page 26: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Typechecker ScriptsA term, with an assertionhasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A (app (var 1) (var 0))))

A term with a hole, with an assertionλx. hasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A x))

A term with a hole, with two assertionsλx. hasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A (have 1 (A⇒ B) x))

Page 27: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Typechecker ScriptsA term, with an assertionhasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A (app (var 1) (var 0))))

A term with a hole, with an assertionλx. hasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A x))

A term with a hole, with two assertionsλx. hasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A (have 1 (A⇒ B) x))

Page 28: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Typechecker ScriptsA term, with an assertionhasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A (app (var 1) (var 0))))

A term with a hole, with an assertionλx. hasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A x))

A term with a hole, with two assertionsλx. hasType ((A⇒ B)⇒ A⇒ B)

(lam (A⇒ B) (lam A (have 1 (A⇒ B) x))

Page 29: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Algebraic Theory of Typechecking

Page 30: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

The Algebraic Theory of Typecheckingdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker α wherevar :: Int→ α;lam :: Type→ α→ α;app :: α→ α→ α;

have :: Int→ Type→ α→ αhasType :: Type→ α→ αfailure :: α

Page 31: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

The Algebraic Theory of Typecheckingdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker α wherevar :: Int→ α;lam :: Type→ α→ α;app :: α→ α→ α;

have :: Int→ Type→ α→ αhasType :: Type→ α→ αfailure :: α

Equations 1: Failure is contagious

failure = lam A failure= app failure x= app x failure= have i A failure= hasType A failure

Page 32: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

The Algebraic Theory of Typecheckingdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker α wherevar :: Int→ α;lam :: Type→ α→ α;app :: α→ α→ α;

have :: Int→ Type→ α→ αhasType :: Type→ α→ αfailure :: α

Equations 2: To have and to have not

lam A x = lam A (have 0 A x)have n A (lam B x) = lam B (have (n+ 1) A x)have n A (app x y) = app (have n A x) (have n A y)have n A (var n) = hasType A (var n)

have n A (have n A x) = have n A xhave n A (have n B x) = failure (A ̸= B)have n A (have n′ B x) = have n′ B (have n A x) (n ̸= n′)

Page 33: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

The Algebraic Theory of Typecheckingdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker α wherevar :: Int→ α;lam :: Type→ α→ α;app :: α→ α→ α;

have :: Int→ Type→ α→ αhasType :: Type→ α→ αfailure :: α

Equations 3: I can hasType

lam A (hasType B x) = hasType (A⇒ B) (lam A x)app (hasType (A⇒ B) x)

(hasType A y)= hasType B (app (hasType (A⇒ B) x) y)

app (hasType A x) y = failure (A ̸= − ⇒ −)app (hasType (A⇒ B) x)

(hasType C y)= failure (A ̸= C)

hasType A (hasType A x) = hasType A xhasType A (hasType B x) = failure (A ̸= B)

Page 34: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Equations vs. Actual Typing

For any term t, let TtU be the translation into the Typecheckertheory using var, lam, and app.

Theorem

⊢ t : A

if and only ifhasType A TtU ̸= failure

(in the Typechecker theory)

Page 35: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Have an Algebraic Theory? Think “Monad!”data TCTerm α = Return α

| Var Int| Lam Type (TCTerm α)| App (TCTerm α) (TCTerm α)| Have Int Type (TCTerm α)| HasType Type (TCTerm α)| Failure

(>>=) :: TCTerm α→ (α→ TCTerm β)→ TCTerm βReturn a >>= f = f aVar i >>= f = Var iLam ty t >>= f = Lam ty (t >>= f)App t1 t2 >>= f = App (t1 >>= f) (t2 >>= f)Have i ty t >>= f = Have i ty (t >>= f)HasType ty t >>= f = HasType ty (t >>= f)Failure >>= f = Failure

Page 36: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Typechecker ScriptsFor, any α, TCTerm α is a free Typechecker algebra

(rules shall be imposed later)

Some algebraic operations, and generic effects:var i = Var i have n A = Have n A (Return ())lam A = Lam A (Return ()) goalIs A = HasType A (Return ())app x y = App x y failure = Failure

A typechecker script, monadic style:do goalIs ((A⇒ B)⇒ A⇒ B)

lam (A⇒ B)lam Ahave 1 (A⇒ B)have 0 AgoalIs Bapp (var 1) (var 0)

Page 37: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Sorting out Scoping, Method A: de Bruijndata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker (α :: Nat→ ∗) wherevar :: Fin n→ α n;lam :: Type→ α (Suc n)→ α n;app :: α n→ α n→ α n;

have :: Fin n→ Type→ α n→ α nhasType :: Type→ α n→ α nfailure :: α n

(Abstract Syntax and Variable Binding, Fiore, Plotkin, Turi, LICS 1999)

So α n is a typechecker in a context with n free variables

Same equations...

Page 38: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Sorting out Scoping, Method B: HOASdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker ν α wherevar :: ν → α;lam :: Type→ (ν → α)→ α;app :: α→ α→ α;

have :: ν → Type→ α→ αhasType :: Type→ α→ αfailure :: α

The abstract type ν represents variables.

Using a lam gets us a new variable.

Typecheckers with no free variables are represented by the type:

∀ν α. TypeChecker ν α⇒ α

(Equivalent to previous (Syntax for free..., Atkey, TLCA 2009))

Equations???

Page 39: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Have an Algebraic Theory? Think “Monad!”data TCTerm ν α = Return α

| Var ν| Lam Type (ν → TCTerm ν α)| App (TCTerm ν α) (TCTerm ν α)| Have ν Type (TCTerm ν α)| HasType Type (TCTerm ν α)| Failure

(>>=) :: TCTerm ν α→ (α→ TCTerm ν β)→ TCTerm ν βReturn a >>= f = f aVar v >>= f = Var vLam ty t >>= f = Lam ty (λv. t v >>= f)App t1 t2 >>= f = App (t1 >>= f) (t2 >>= f)Have v ty t >>= f = Have v ty (t >>= f)HasType ty t >>= f = HasType ty (t >>= f)Failure >>= f = Failure

Page 40: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

HOAS Typechecker ScriptsSome algebraic operations, and generic effects:

var v = Var vlam A = Lam A (λv. Return v)app x y = App x yhave v A = Have v A (Return ())goalIs A = HasType A (Return ())failure = Failure

A typechecker script, HOAS monadic style:do goalIs ((A⇒ B)⇒ A⇒ B)

v1 ← lam (A⇒ B)v2 ← lam Ahave v1 (A⇒ B)have v2 AgoalIs Bapp (var v1) (var v2)

Page 41: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

HOAS Typechecker ScriptsSome algebraic operations, and generic effects:

var v = Var vintroduce A = Lam A (λv. Return v)app x y = App x yhave v A = Have v A (Return ())goalIs A = HasType A (Return ())failure = Failure

A typechecker script, HOAS monadic style:do goalIs ((A⇒ B)⇒ A⇒ B)

v1 ← introduce (A⇒ B)v2 ← introduce Ahave v1 (A⇒ B)have v2 AgoalIs Bapp (var v1) (var v2)

Page 42: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

HOAS Typechecker ScriptsSome algebraic operations, and generic effects:

assumption v = Var vintroduce A = Lam A (λv. Return v)app x y = App x yhave v A = Have v A (Return ())goalIs A = HasType A (Return ())failure = Failure

A typechecker script, HOAS monadic style:do goalIs ((A⇒ B)⇒ A⇒ B)

v1 ← introduce (A⇒ B)v2 ← introduce Ahave v1 (A⇒ B)have v2 AgoalIs Bapp (assumption v1) (assumption v2)

Page 43: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Evaluating Typechecker Scriptseval :: TypeChecker α⇒ TCTerm 0→ αeval (Return ())eval (Var i) = var ieval (Lam A t) = lam A (eval t)eval (App t1 t2) = app (eval t1) (eval t2)eval (Have i A t) = have i A (eval t)eval (HasType A t) = hasType A (eval t)eval Failure = failure

Type checking:instance TypeChecker ([Type]→ Maybe Type) where...

Elaboration:instance TypeChecker

((Γ :: [Type])→ Maybe ((A :: Type)× Tm Γ A) where...

Page 44: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Evaluating Typechecker Scriptseval :: TypeChecker α⇒ TCTerm 0→ αeval (Return ())eval (Var i) = var ieval (Lam A t) = lam A (eval t)eval (App t1 t2) = app (eval t1) (eval t2)eval (Have i A t) = have i A (eval t)eval (HasType A t) = hasType A (eval t)eval Failure = failure

Type checking:instance TypeChecker ([Type]→ Maybe Type) where...

Elaboration:instance TypeChecker

((Γ :: [Type])→ Maybe ((A :: Type)× Tm Γ A) where...

Page 45: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Evaluating Typechecker Scriptseval :: TypeChecker α⇒ TCTerm 0→ αeval (Return ())eval (Var i) = var ieval (Lam A t) = lam A (eval t)eval (App t1 t2) = app (eval t1) (eval t2)eval (Have i A t) = have i A (eval t)eval (HasType A t) = hasType A (eval t)eval Failure = failure

Type checking:instance TypeChecker ([Type]→ Maybe Type) where...

Elaboration:instance TypeChecker

((Γ :: [Type])→ Maybe ((A :: Type)× Tm Γ A) where...

Page 46: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Two Useful Variations

Page 47: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bidirectional Checking and Synthesisdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker ν (α :: {CHK,SYN} → ∗) wherevar :: ν → α SYNlam :: (ν → α CHK)→ α CHKapp :: α SYN→ α CHK→ α SYN

Page 48: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bidirectional Checking and Synthesisdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker ν (α :: {CHK,SYN} → ∗) wherevar :: ν → α SYNlam :: (ν → α CHK)→ α CHKapp :: α SYN→ α CHK→ α SYN

switch :: α SYN→ α CHKascribe :: Type→ α CHK→ α SYN

Page 49: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bidirectional Checking and Synthesisdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker ν (α :: {CHK,SYN} → ∗) wherevar :: ν → α SYNlam :: (ν → α CHK)→ α CHKapp :: α SYN→ α CHK→ α SYN

switch :: α SYN→ α CHKascribe :: Type→ α CHK→ α SYN

have :: ν → (Type→ α δ)→ α δgoalIs :: (Type→ α CHK)→ α CHKfailure :: α δ

Page 50: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bidirectional Checking and Synthesisdata Type = A | B | C | Type⇒ Type deriving (Eq)

class TypeChecker ν (α :: {CHK,SYN} → ∗) wherevar :: ν → α SYNlam :: (ν → α CHK)→ α CHKapp :: α SYN→ α CHK→ α SYN

switch :: α SYN→ α CHKascribe :: Type→ α CHK→ α SYN

have :: ν → (Type→ α δ)→ α δgoalIs :: (Type→ α CHK)→ α CHKfailure :: α δ

instance TypeChecker(CHK 7→ [Type]→ Type→ Bool;SYN 7→ [Type]→ Maybe Type)

where...

Page 51: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bidirectional Typechecker ScriptsTerms that are “active” in their environment:

do v1 ← introducev2 ← introducety← goalcase ty of

A→ someAConstantB→ someBConstant_→ assumption v1

Application: Polymorphic Constants (elaboration from source):elaborate (PolyConstant str) =

do ty← goalcase ty of

A→ interpretAsAConstant strB→ interpretAsBConstant str_→ failure

(Safely Composable Type-Specific Languages, Omar et al., ECOOP 2014)

Page 52: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Bidirectional Typechecker ScriptsTerms that are “active” in their environment:

do v1 ← introducev2 ← introducety← goalcase ty of

A→ someAConstantB→ someBConstant_→ assumption v1

Application: Polymorphic Constants (elaboration from source):elaborate (PolyConstant str) =

do ty← goalcase ty of

A→ interpretAsAConstant strB→ interpretAsBConstant str_→ failure

(Safely Composable Type-Specific Languages, Omar et al., ECOOP 2014)

Page 53: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Type Inference (in Prolog)(An Algebraic Presentation of Predicate Logic, Staton, FoSSaCS 2013)

data Type µ = A | B | C | Type µ⇒ Type µ | MV µ deriving (Eq)

class TypeChecker ν µ α wherevar :: ν → αlam :: (ν → α)→ αapp :: α→ α→ α

Page 54: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Type Inference (in Prolog)(An Algebraic Presentation of Predicate Logic, Staton, FoSSaCS 2013)

data Type µ = A | B | C | Type µ⇒ Type µ | MV µ deriving (Eq)

class TypeChecker ν µ α wherevar :: ν → αlam :: (ν → α)→ αapp :: α→ α→ αnewMVar :: (µ→ α)→ αunify :: Type µ→ Type µ→ α→ α

Page 55: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Type Inference (in Prolog)(An Algebraic Presentation of Predicate Logic, Staton, FoSSaCS 2013)

data Type µ = A | B | C | Type µ⇒ Type µ | MV µ deriving (Eq)

class TypeChecker ν µ α wherevar :: ν → αlam :: (ν → α)→ αapp :: α→ α→ αnewMVar :: (µ→ α)→ αunify :: Type µ→ Type µ→ α→ αhave :: ([(ν, Type µ)]→ α)→ αgoalIs :: (Type µ→ α)→ α

Page 56: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Type Inference (in Prolog)(An Algebraic Presentation of Predicate Logic, Staton, FoSSaCS 2013)

data Type µ = A | B | C | Type µ⇒ Type µ | MV µ deriving (Eq)

class TypeChecker ν µ α wherevar :: ν → αlam :: (ν → α)→ αapp :: α→ α→ αnewMVar :: (µ→ α)→ αunify :: Type µ→ Type µ→ α→ αhave :: ([(ν, Type µ)]→ α)→ αgoalIs :: (Type µ→ α)→ αfailure :: αchoice :: α→ α→ α

Page 57: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Type Inference (in Prolog)(An Algebraic Presentation of Predicate Logic, Staton, FoSSaCS 2013)

data Type µ = A | B | C | Type µ⇒ Type µ | MV µ deriving (Eq)

class TypeChecker ν µ α wherevar :: ν → αlam :: (ν → α)→ αapp :: α→ α→ αnewMVar :: (µ→ α)→ αunify :: Type µ→ Type µ→ α→ αhave :: ([(ν, Type µ)]→ α)→ αgoalIs :: (Type µ→ α)→ αfailure :: αchoice :: α→ α→ α

instance TypeChecker (Int→ Int)MV(MetaContext→ [Type MV]→ Type MV→ Bool) where...

Page 58: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Typechecker Scripts with Unification

A “by assumption” tactic for programming:byAssumption =

do g← goalctxt← getContextlet search [] = failure

search ((v, ty):ctxt = choice (do unify ty g; return v)(search ctxt)

v← search ctxtvar v

Page 59: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Summary, and Some Questions

Page 60: An AlgebraicApproach to TypecheckingandElaboration · Let’swriteatypechecker dataType = A jB jC jType)Type deriving(Eq) dataTerm = Var Int jLam Type Term jApp Term Term typecheck::

Summary:1. Treat the bits of a typechecker as operations2. Typechecker scripts3. Elaboration implementation yields well-typed terms4. Separation of core typechecking from elaboration5. Monadic typechecker terms allow for “active terms”

Questions:▶ Does this work for more complex type systems?▶ What are the right operations and equations, in general?▶ What are the free algebras?▶ Is this a sensible way to implement a typed language?▶ What is relationship to tactic scripts? HiProofs? Isar mode?▶ Does this subsume (hygenic) macros?