#import "prooftree.typ": * #import "@preview/showybox:2.0.1": showybox #set page(width: 5.6in, height: 9in, margin: 0.4in) = Type theory crash course == MLTT + Sets Important features in MLTT: #let Nat = $sans("Nat")$ #let Vect = $sans("Vect")$ - Dependent types and functions. e.g $ "concatenate": Pi_(m,n:"Nat") Vect(m) -> Vect(n) -> Vect(m+n) $ - Function arrows always associate to the right. - All functions are total. Goal: to write well-typed programs. (implementing an algorithm and proving a mathematical statement are the same) === Judgements $ "context" tack.r "conclusion" $ #let defeq = $equiv$ #table( columns: 2, stroke: gray, $Gamma$, [sequence of variable declarations (contexts are always well-formed)], $Gamma tack.r A$, [$A$ is well-formed *type* in context $Gamma$], $Gamma tack.r a : A$, [*term* $a$ is well-formed and of type $A$], $Gamma tack.r A defeq B$, [types $A$ and $B$ are *convertible*], $Gamma tack.r a defeq b : A$, [$a$ is convertible to $b$ in type $A$], ) Example: $ "isZero?"& : Nat -> "Bool" \ "isZero?"& (n) :defeq "??" $ At this point, looking for $(n: Nat) tack.r "isZero?"(n) : "Bool"$. === Inference rules #prooftree( axiom($J_1$), axiom($J_2$), axiom($J_3$), rule(n: 3, $J$), ) For example: #prooftree( axiom($Gamma tack.r a defeq b : A$), rule($Gamma tack.r b defeq a : A$), ) #let subst(name, replacement, expr) = $#expr [ #replacement \/ #name ]$ === Interpreting types as sets You can interpret types as sets, where $a : A$ is interpreted as $floor(a) : floor(A)$. - Univalent mathematics can _not_ be interpreted as sets. There are extra axioms that breaks the interpretation. - The judgement $a : A$ cannot be proved or disproved. - For ex. 2 of natural numbers and 2 of integers can be converted but are inherently different values. === Convertibility If $x : A$ and $A defeq B$, then $x : B$. We are thinking of these types as literally the same. If $a defeq a'$ then $f @ a defeq f @ a'$. === Declaring types and terms 4 types of rules: #let typeIntroTable(formation, introduction, elimination, computation) = table( columns: 2, stroke: 0in, [#text(fill: blue, [Formation])], [#formation], [#text(fill: blue, [Introduction])], [#introduction], [#text(fill: blue, [Elimination])], [#elimination], [#text(fill: blue, [Computation])], [#computation], ) #typeIntroTable( [a way to construct a new type], [way to construct *canonical terms* of the type], [how to use a term of the new type to construct terms of other types], [what happens when one does Introduction followed by Elimination], ) Example (context $Gamma$ are elided): #typeIntroTable( [If $A$ and $B$ are types, then $A -> B$ is a type #prooftree(axiom($Gamma tack.r A$), axiom($Gamma tack.r B$), rule(n: 2, $Gamma tack.r A -> B$))], [If $(x : A) tack.r b : B$, then $tack.r lambda (x : A) . b(x) : A -> B$ - $b$ is an expression that might involve $x$], [If we have a function $f : A -> B$, and $a : A$, then $f @ a : B$ (or $f(a) : B$)], [What is the result of the application? $(lambda(x : A) . b(x)) @ a defeq subst(a, x, b)$ - Substitution $subst(a, x, b)$ is built-in], ) Questions: - *What does the lambda symbol mean?* Lambda is just notation. It could also be written $tack.r "lambda"((x:A), b(x)) : A -> B$. Another example: the singleton type #let unit = $bb(1)$ #let tt = $t t$ #let rec = $sans("rec")$ #typeIntroTable( [$unit$ is a type], [$tt : unit$], [If $x : unit$ and $C$ is a type and $c : C$, then $rec_unit (C, c, x) : C$], [$rec_unit (C, c, t) defeq c$ - Interpretation in sets: a one-element set], ) - Question: *How to construct this using lambda abstraction?* - (Structural rule: having $tack.r c : C$ means $x : unit tack.r c : C$, which by the lambda introduction rule gives us $lambda x.c : unit -> C$) Booleans #let Bool = $sans("Bool")$ #let tru = $sans("true")$ #let fls = $sans("false")$ #typeIntroTable( [$Bool$ is a type], [$tru : Bool$ and $fls : Bool$], [If $x : Bool$ and $C$ is a type and $c, c' : C$, then $rec_Bool (C, c, c', x) : C$], [$rec_Bool (C, c, c', tru) defeq c$ and $rec_Bool (C, c, c', fls) defeq c'$], ) Empty type #let empty = $bb(0)$ #typeIntroTable( [$empty$ is a type], [_(no introduction rule)_], [If $x : empty$ and $C$ is a type, then $rec_empty (C, x) : C$], [_(no computation rule)_], ) Natural numbers #let zero = $sans("zero")$ #let suc = $sans("suc")$ #typeIntroTable( [$Nat$ is a type], [- $zero : Nat$ - If $n : Nat$, then $suc(n) : Nat$], [If $C$ is a type and $c_0:C$ and $c_s:C->C$ and $x: Nat$, then $rec_Nat (C,c_0,c_s,x) : C$], [- $rec_Nat (C, c_0, c_s, zero) defeq c_0$ - $rec_Nat (C, c_0, c_s, suc(n)) defeq c_s @ (rec_Nat (C, c_0, c_s, n))$ We can define computation rule on naturals using a universal property], )