diff --git a/pfenning/notes.typ b/pfenning/notes.typ index 8c00986..df14f84 100644 --- a/pfenning/notes.typ +++ b/pfenning/notes.typ @@ -1,3 +1,4 @@ +#import "@preview/fletcher:0.4.5" as fletcher: diagram, node, edge #import "../common.typ": * #import "@preview/prooftrees:0.1.0": * #import "@preview/algo:0.3.3": algo, i, d, comment, code @@ -372,4 +373,110 @@ $with { l : A_l}_(l in L)$ #tree( axi[$Gamma tack.r e : with { l : A_l}_(l in L) (forall l in L)$], uni[$Gamma tack.r e.k : A_k (k in L)$] +) + +#pagebreak() + +=== Lecture 3 + +- negation +- Mixing linear & non-linear programs +- Mode checking & inference + +#diagram(( + node((0, -0.8), "Unrestricted"), + edge("-|>"), + node((0.8, 0), "Strict (at least once)"), + node((-0.8, 0), "Affine (at most once)"), + edge("-|>"), + node((0, 0.8), "Linear"), + edge((0, -0.8), (-0.8, 0), "-|>"), + edge((0.8, 0), (0, 0.8), "-|>"), +)) + +Cannot write map: + +``` +fail decl map (f : nat -> nat) (xs : list) : list +defn map f xs = match xs with + | 'nil () => 'nil () + | 'cons (x, xs) => 'cons (f x, map f xs) +``` + +This is because $f$ isn't used in the first line but used twice in the second line. + +We could write some iterator: + +``` +type iterator = &{'next : nat -> nat * iterator, 'done : 1} + +decl iterate (iter : iterator) (xs : list) : list +defn iterate iter xs = match xs with + | 'nil () => (match iter.'done with | () => 'nil ()) + | 'cons (x, xs) => (match iter.'next x with | (y, iter) => 'cons ('succ y, iterate iter xs)) +``` + +This is a linear implementation of a function that adds 1 to everything in the list. + +=== Modes + +Take the entire language and parameterize by modes: + +$A, B_m ::= 1_m &| A_m times B_m | +{l : A^l_m}_(l in L) | arrow.b^k_m A_k (k >= m) \ +&| A_m arrow B_m | \&{l:A^l_m}_(l in L) | arrow.t^i_m A_i (i <= m) +$ + +These are implemented in the code: + +``` +type nat[k] = +{'zero : 1, 'succ : nat[k]} +``` + +Modes need to be _guarded_. For example: + +``` +type nat[k] = +{'zero : 1, 'succ : down[k] nat[k]} + +type list[m k] = +{ + 'nil : 1, + 'cons : down[k] nat[k] * down[m] list[m k], +} +``` + +The `m` is used because it comes first. + +$ (!A_L)_L eq.delta arrow.b^U_L arrow.t^U_L A_L$ + +needs a partial ordering on U and L. Need to copy when it's in the U and then move it back into the L when you're done. + +``` +decl map (f : [mf] up[k] (nat[k] -> nat[k])) (xs : list[m k]) : list[r k] +defn map f xs = match xs with + | 'nil () => 'nil () + | 'cons (, ) => 'cons(, ) +``` + +$Gamma$ can be multi-modal. This is how top-level declarations can be re-used. + +https://www.cs.cmu.edu/~fp/papers/tocl07.pdf + +Need to enforce independence, that $Gamma tack.r e : A_m$ means $Gamma >= m$ + +Pointer: + +#let wrap(e) = $angle.l #e angle.r $ + +#tree( + axi[$Gamma >= k$], + axi[$Gamma tack.r e : A_k$], + bin[$Gamma tack.r wrap(e) : arrow.b^k_m A_k$] +) + +*NOTE:* The bottom would not be valid if $Gamma cancel(>=) k$ + +#tree( + axi[$Delta >= m >= r$], + axi[$Delta tack.r e : arrow.b^k_m A_k$], + axi[$Gamma , x : A_k tack.r e' : C_r$], + nary(3)[$Delta Gamma tack.r "match" e with wrap(x) => e' : C_r$], ) \ No newline at end of file