BRICS NBE 2004 A Functional Correspondence between Normalization - - PowerPoint PPT Presentation

brics
SMART_READER_LITE
LIVE PREVIEW

BRICS NBE 2004 A Functional Correspondence between Normalization - - PowerPoint PPT Presentation

BRICS NBE 2004 A Functional Correspondence between Normalization Functions and Abstract Machines Olivier Danvy (danvy@brics.dk) BRICS, University of Aarhus, Denmark 1 Plan The functional correspondence. The case of the untyped


slide-1
SLIDE 1

BRICS

NBE 2004 A Functional Correspondence between Normalization Functions and Abstract Machines Olivier Danvy (danvy@brics.dk) BRICS, University of Aarhus, Denmark

1

slide-2
SLIDE 2

Plan

  • The functional correspondence.
  • The case of the untyped lambda-calculus.
  • From one-step reduction to evaluation and

to normalization.

  • X by evaluation.
  • NBE for what else?

2

slide-3
SLIDE 3

The functional correspondence

evaluator closure conversion (to make it first order) CPS transformation (to make it sequential) defunctionalization (to make it first order)

  • abstract

machine

3

slide-4
SLIDE 4

Source terms (de Bruijn indices)

structure S = struct datatype term = VAR of int | LAM of term | APP of term * term end

4

slide-5
SLIDE 5

Target terms (de Bruijn levels)

structure T = struct datatype nf = LAM of nf | VAL of at and at = VAR of int | APP of at * nf end

5

slide-6
SLIDE 6

Example: λx.λk.k x

Source term:

S.LAM (S.LAM (S.APP (S.VAR 0, S.VAR 1)))

Target term:

T.LAM (T.LAM (T.VAL (T.APP (T.VAR 1, T.VAL (T.VAR 0)))))

6

slide-7
SLIDE 7

datatype expval = FUN of denval -> expval | RES of int -> T.at withtype denval = unit -> expval

7

slide-8
SLIDE 8

(* reify : expval -> int -> T.nf *) fun reify (RES r) = (fn n => T.VAL (r n)) | reify (FUN f) = (fn n => let fun d () = RES (fn n’ => T.VAR n) in T.LAM (reify (f d) (n+1)) end)

8

slide-9
SLIDE 9

(* eval : S.term * denval Env.env -> expval *) fun eval (S.VAR i, e) = List.nth (e, i) () | eval (S.LAM t, e) = FUN (fn a => eval (t, a :: e))

9

slide-10
SLIDE 10

| eval (S.APP (t0, t1), e) = (case eval (t0, e)

  • f (FUN f)

=> f (fn () => eval (t1, e)) | (RES r) => RES (fn n => T.APP (r n, reify (eval (t1, e)) n)))

10

slide-11
SLIDE 11

(* main : S.term -> T.nf *) fun main t = reify (eval (t, nil)) 0

11

slide-12
SLIDE 12

The derivation

  • uncurry
  • closure convert expressible values
  • defunctionalize residual abstract syntax
  • CPS transform
  • defunctionalize

12

slide-13
SLIDE 13

datatype expval = CLO of S.term * expval list | RES of target and target = VAR of int | APP of target * expval

13

slide-14
SLIDE 14

datatype econt = ECONT0 | ECONT1 of target * econt | ECONT2 of S.term * expval list * econt | ECONT3 of int * rcont and rcont = RCONT0 | RCONT1 of T.at * tcont | RCONT2 of rcont and tcont = TCONT0 of rcont | TCONT1 of expval * int * tcont

14

slide-15
SLIDE 15

(* reify : expval * int * rcont -> T.nf *) fun reify (RES r, n, k) = apply_target (r, n, TCONT0 k) | reify (CLO (t, e), n, k) = eval (t, (RES (VAR n)) :: e, ECONT3 (n+1, k))

15

slide-16
SLIDE 16

(* eval : S.term * denval Env.env * econt

  • > T.nf

*) and eval (S.VAR i, e, k) = (case List.nth (e, i)

  • f (RES r)

=> apply_econt (k, RES r) | (CLO (t’, e’)) => eval (t’, e’, k)) | eval (S.LAM t, e, k) = apply_econt (k, CLO (t, e)) | eval (S.APP (t0, t1), e, k) = eval (t0, e, ECONT2 (t1, e, k))

16

slide-17
SLIDE 17

(* apply_target : target * int * tcont

  • > T.nf

*) and apply_target (VAR n, n’, k) = apply_tcont (k, T.VAR n) | apply_target (APP (r0, v1), n, k) = apply_target (r0, n, TCONT1 (v1, n, k))

17

slide-18
SLIDE 18

(* apply_tcont : T.at -> T.nf *) and apply_tcont (TCONT0 k, at) = apply_rcont (k, T.VAL at) | apply_tcont (TCONT1 (v1, n, k), at0) = reify (v1, n, RCONT1 (at0, k))

18

slide-19
SLIDE 19

(* apply_econt : econt * expval -> T.nf *) and apply_econt (ECONT0, v) = reify (v, 0, RCONT0) | apply_econt (ECONT1 (r0, k), v1) = apply_econt (k, RES (APP (r0, v1))) | apply_econt (ECONT2 (t1, e, k), CLO (t’, e’)) = eval (t’, (CLO (t1, e)) :: e’, k) | apply_econt (ECONT2 (t1, e, k), RES r0) = eval (t1, e, ECONT1 (r0, k)) | apply_econt (ECONT3 (n, k), v) = reify (v, n, RCONT2 k)

19

slide-20
SLIDE 20

(* apply_rcont : rcont * T.nf -> T.nf *) and apply_rcont (RCONT0, r) = r | apply_rcont (RCONT1 (at0, k), r1) = apply_tcont (k, T.APP (at0, r1)) | apply_rcont (RCONT2 k, r) = apply_rcont (k, T.LAM r)

20

slide-21
SLIDE 21

(* main : S.term * (T.nf -> T.nf) -> T.nf *) fun main t = eval (t, nil, ECONT0)

21

slide-22
SLIDE 22

X by evaluation

Key idea: Reuse the evaluation mechanism

  • f the implementation language.

22

slide-23
SLIDE 23

NBE for what else?

M = E, ⋆, ε E =

set of elements

⋆ : M × M → M m ∈ M e ∈ E m ::= ε | m1 ⋆ m2 | e

23

slide-24
SLIDE 24

Conversion rules

m1 ⋆ (m2 ⋆ m3) ↔ (m1 ⋆ m2) ⋆ m3 m ⋆ ε ↔ m ε ⋆ m ↔ m

24

slide-25
SLIDE 25

Notion of normal form

m ∈ Mnf e ∈ E m ::= εnf | e ⋆nf m

25

slide-26
SLIDE 26

Reduction-based normalization

  • 1. We orient the conversion rules

into reduction rules:

m1 ⋆ (m2 ⋆ m3) ← (m1 ⋆ m2) ⋆ m3 ε ⋆ m → m

  • 2. We apply the reduction rules

until a normal form is obtained.

26

slide-27
SLIDE 27

Incidentally

“Reduction rules” is a wonderful title.

27

slide-28
SLIDE 28

Reduction-free normalization (1/2)

Notion of evaluation:

eval : M → (Mnf → Mnf) eval(ε) = λm.m eval(m1 ⋆ m2) = (eval(m1)) ◦ (eval(m2)) eval(e) = λm.e ⋆nf m

28

slide-29
SLIDE 29

Reduction-free normalization (2/2)

Notion of reification:

reify : (Mnf → Mnf) → Mnf reify(f) = f(εnf)

29

slide-30
SLIDE 30

Reduction-free normalization (2/2)

Notion of reification:

reify : (Mnf → Mnf) → Mnf reify(f) = f(εnf)

Normalization:

normalize : M → Mnf normalize(m) = reify(eval(m))

30

slide-31
SLIDE 31

Pragmatic look

From a programming standpoint:

  • Reduction-based: iterative flattening

by reordering.

  • Reduction-free: flatten function

with an accumulator.

31

slide-32
SLIDE 32

Pragmatic look

From a programming standpoint:

  • Reduction-based: iterative flattening

by reordering.

  • Reduction-free: flatten function

with an accumulator. Also: Correctness issues.

32

slide-33
SLIDE 33

Cool thing: NBE scales

  • The λ-calculus.
  • The computational λ-calculus.
  • Other algebraic structures.

33

slide-34
SLIDE 34

In short

NBE uses the expressive power

  • f functional programming.

34

slide-35
SLIDE 35

In particular

For the λ-calculus and the computational

λ-calculus, i.e., for proof theorists and

functional programmers:

  • Normalization steps involve substitutions

(due to parameter passing).

  • Why not reuse 30 years of compiler

expertise to carry out these substitutions?

35

slide-36
SLIDE 36

Joint work with Vincent Balat (GPCE’03)

  • Setting: The typed λ-calculus.
  • Issue: Type isomorphisms.
  • Application: Data conversion, library search,

language interoperability.

36

slide-37
SLIDE 37

In particular

The type-theoretical counterpart of Tarski’s high school algebra problem (1950): Can one prove all arithmetic propositions using the equations taught in high school?

37

slide-38
SLIDE 38

In particular

The type-theoretical counterpart of Tarski’s high school algebra problem (1950): Can one prove all arithmetic propositions using the equations taught in high school? (Or did they not teach you the secret ones?)

38

slide-39
SLIDE 39

In particular

The type-theoretical counterpart of Tarski’s high school algebra problem (1950): Can one prove all arithmetic propositions using the equations taught in high school? (Or did they not teach you the secret ones?)

  • cf. Balat, Di Cosmo, Fiore, LICS’02, POPL

’04.

39

slide-40
SLIDE 40

The problem

  • Verify that two families of functions are

inverses of each other, pointwise.

  • NBE approach: Write them in ML, compose

them, normalize them, and verify textual identity.

  • The problem: Huge normalization time,

gigantic normal forms.

40

slide-41
SLIDE 41

The root of the problem

Duplication of work across conditional expressions due to use of continuations. Our (pragmatic) solution: Dynamic memoization of intermediate results.

41

slide-42
SLIDE 42

Results: Size of normalized programs

4750 18984 49290 101716 182310 494 1312 2570 4268 6406 8984 12002 3 5 7 9 11 13 15 n size 300000 200000 100000 297120

42

slide-43
SLIDE 43

Results: Normalization time

4000 3000 2000 1000 22 2 96 6 358 13 1137 22 2340 34 4036 47 70 3 5 7 9 11 13 15 normalization time (ms) n

43

slide-44
SLIDE 44

Mission accomplished

NBE is now usable for more and bigger examples

  • f type isomorphisms.

44

slide-45
SLIDE 45

And furthermore

Using set/cupto instead of shift/reset, Balat met Filinski’s challenge of identifying

  • nce and thrice (POPL

’04).

45