This commit is contained in:
Michael Zhang 2024-06-05 15:26:46 -04:00
parent 2a2e7d279b
commit d2afe9399c

View file

@ -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
@ -373,3 +374,109 @@ $with { l : A_l}_(l in L)$
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 (<x>, <xs>) => 'cons(<f.force x>, <map f xs>)
```
$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$],
)