How to be a Productive Programmer by putting things ofg until - - PowerPoint PPT Presentation

how to be a productive programmer
SMART_READER_LITE
LIVE PREVIEW

How to be a Productive Programmer by putting things ofg until - - PowerPoint PPT Presentation

How to be a Productive Programmer by putting things ofg until tomorrow Robert Atkey University of Strathclyde, Glasgow, UK 11th November 2011 Playing in Streams co data Stream = StreamCons Integer Stream ones :: Stream ones = StreamCons 1 ones


slide-1
SLIDE 1

How to be a Productive Programmer

by putting things ofg until tomorrow Robert Atkey University of Strathclyde, Glasgow, UK 11th November 2011

slide-2
SLIDE 2

Playing in Streams

co data Stream = StreamCons Integer Stream

  • nes :: Stream
  • nes = StreamCons 1 ones

map :: (Integer → Integer) → Stream → Stream map f (StreamCons x xs) = StreamCons (f x) (map f xs) merge :: Stream → Stream → Stream merge (StreamCons x xs) (StreamCons y ys) = StreamCons x (StreamCons y (merge xs ys))

slide-3
SLIDE 3

Playing in Streams

co data Stream = StreamCons Integer Stream

  • nes :: Stream
  • nes = StreamCons 1 ones

map :: (Integer → Integer) → Stream → Stream map f (StreamCons x xs) = StreamCons (f x) (map f xs) merge :: Stream → Stream → Stream merge (StreamCons x xs) (StreamCons y ys) = StreamCons x (StreamCons y (merge xs ys))

slide-4
SLIDE 4

Higher-order Functions on Streams

mergef :: (Integer → Integer → Stream → Stream) → Stream → Stream → Stream mergef f (StreamCons x xs) (StreamCons y ys) = f x y (mergef f xs ys)

slide-5
SLIDE 5

Higher-order Functions on Streams

mergef :: (Integer → Integer → Stream → Stream) → Stream → Stream → Stream mergef f (StreamCons x xs) (StreamCons y ys) = f x y (mergef f xs ys) A bad choice of argument yields non-productive defjnitions: badf :: Integer → Integer → Stream → Stream badf x y s = s

slide-6
SLIDE 6

Higher-order Functions on Streams

mergef :: (Integer → Integer → Stream → Stream) → Stream → Stream → Stream mergef f (StreamCons x xs) (StreamCons y ys) = f x y (mergef f xs ys) Coq reports: Sub-expression “f x y (mergef f xs ys)” not in guarded form

slide-7
SLIDE 7

Higher-order Functions on Streams

mergef :: (Integer → Integer → Stream → Stream) → Stream → Stream → Stream mergef f (StreamCons x xs) (StreamCons y ys) = f x y (mergef f xs ys) Get around guardedness check by changing the type of f? f :: Integer → Integer → Integer f :: Integer → Integer → (Integer, [Integer]) but what about: f x y s = StreamCons x (map (+1) s)

slide-8
SLIDE 8

How can we put guardedness constraints into the types?

slide-9
SLIDE 9

Putting things ofg until tomorrow

(Nakano, 2000) (McBride, 2009)

slide-10
SLIDE 10

Putting things ofg until tomorrow

(Nakano, 2000) (McBride, 2009)

slide-11
SLIDE 11

Type-based Guardedness

f :: Integer → Integer → ⊲ Stream → Stream

slide-12
SLIDE 12

Type-based Guardedness

f :: Integer → Integer → ⊲ Stream → Stream

slide-13
SLIDE 13

Type-based Guardedness

⊲Stream − “a stream tomorrow” StreamCons :: Integer → ⊲Stream → Stream deStreamCons :: Stream → (Integer, ⊲Stream) fjx :: (⊲A → A) → A

  • nes

fjx s 1 s fjx x x

slide-14
SLIDE 14

Type-based Guardedness

⊲Stream − “a stream tomorrow” StreamCons :: Integer → ⊲Stream → Stream deStreamCons :: Stream → (Integer, ⊲Stream) fjx :: (⊲A → A) → A

  • nes = fjx (λs. StreamCons 1 s)

fjx (λx. x)

slide-15
SLIDE 15

Type-based Guardedness

⊲Stream − “a stream tomorrow” StreamCons :: Integer → ⊲Stream → Stream deStreamCons :: Stream → (Integer, ⊲Stream) fjx :: (⊲A → A) → A

  • nes = fjx (λs. StreamCons 1 s)

✘✘✘✘✘

fjx (λx. x)

slide-16
SLIDE 16

Applicative Functor

pure :: A → ⊲A (⊛) :: ⊲(A → B) → ⊲A → ⊲B mergef Integer Integer Stream Stream Stream Stream Stream mergef f fjx g xs ys let x xs’ xs let y ys’ ys in f x y g xs’ ys’ g Stream Stream Stream

slide-17
SLIDE 17

Applicative Functor

pure :: A → ⊲A (⊛) :: ⊲(A → B) → ⊲A → ⊲B mergef :: (Integer → Integer → ⊲Stream → Stream) → Stream → Stream → Stream mergef f = fjx (λg xs ys. let (x, xs’) = deStreamCons xs let (y, ys’) = deStreamCons ys in f x y (g ⊛ xs’ ⊛ ys’)) g :: ⊲(Stream → Stream → Stream)

slide-18
SLIDE 18

From Infjnite to Finite

Can we write take :: Natural → Stream → [Integer] by structural recursion on the fjrst argument? take 0 s take n 1 s x take n s’ where x s’ s This type prevents us: Stream Integer Stream We cannot leave the “time stream” of the stream.

slide-19
SLIDE 19

From Infjnite to Finite

Can we write take :: Natural → Stream → [Integer] by structural recursion on the fjrst argument? take 0 s = [] take (n + 1) s = x : take n s’ where (x, s’) = deStreamCons s This type prevents us: Stream Integer Stream We cannot leave the “time stream” of the stream.

slide-20
SLIDE 20

From Infjnite to Finite

Can we write take :: Natural → Stream → [Integer] by structural recursion on the fjrst argument? take 0 s = [] take (n + 1) s = x : take n s’ where (x, s’) = deStreamCons s This type prevents us: deStreamCons :: Stream → (Integer, ⊲Stream) We cannot leave the “time stream” of the stream.

slide-21
SLIDE 21

Clock Variables

slide-22
SLIDE 22

Clock Variables

Annotate with “clock variables”, κ:

◮ A clock κ represents a fjxed amount of time remaining ◮ Streamκ is a stream for at least the time remaining in κ ◮ ⊲ κ removes one unit of time remaining in κ

Integer Stream Stream Stream Integer Stream delay A A A B A B fjx A A A

slide-23
SLIDE 23

Clock Variables

Annotate with “clock variables”, κ:

◮ A clock κ represents a fjxed amount of time remaining ◮ Streamκ is a stream for at least the time remaining in κ ◮ ⊲ κ removes one unit of time remaining in κ

StreamConsκ :: Integer → ⊲

κStreamκ → Streamκ

deStreamConsκ :: Streamκ → (Integer, ⊲

κStreamκ)

delay A A A B A B fjx A A A

slide-24
SLIDE 24

Clock Variables

Annotate with “clock variables”, κ:

◮ A clock κ represents a fjxed amount of time remaining ◮ Streamκ is a stream for at least the time remaining in κ ◮ ⊲ κ removes one unit of time remaining in κ

StreamConsκ :: Integer → ⊲

κStreamκ → Streamκ

deStreamConsκ :: Streamκ → (Integer, ⊲

κStreamκ)

delayκ :: A → ⊲

κA

(⊛κ) :: ⊲

κ(A → B) → ⊲ κA → ⊲ κB

fjx A A A

slide-25
SLIDE 25

Clock Variables

Annotate with “clock variables”, κ:

◮ A clock κ represents a fjxed amount of time remaining ◮ Streamκ is a stream for at least the time remaining in κ ◮ ⊲ κ removes one unit of time remaining in κ

StreamConsκ :: Integer → ⊲

κStreamκ → Streamκ

deStreamConsκ :: Streamκ → (Integer, ⊲

κStreamκ)

delayκ :: A → ⊲

κA

(⊛κ) :: ⊲

κ(A → B) → ⊲ κA → ⊲ κB

fjxκ :: (⊲

κA → A) → A

slide-26
SLIDE 26

Eternity in an Hour

For type A with a free clock variable κ:

◮ Form the type ∀κ. A ◮ A with all possible amounts of “time remaining”

Stream streams that go on forever Quantifjcation allows removal of delays: force A A

slide-27
SLIDE 27

Eternity in an Hour

For type A with a free clock variable κ:

◮ Form the type ∀κ. A ◮ A with all possible amounts of “time remaining”

(∀κ. Streamκ) ≈ streams that go on forever Quantifjcation allows removal of delays: force A A

slide-28
SLIDE 28

Eternity in an Hour

For type A with a free clock variable κ:

◮ Form the type ∀κ. A ◮ A with all possible amounts of “time remaining”

(∀κ. Streamκ) ≈ streams that go on forever Quantifjcation allows removal of delays: force :: (∀κ. ⊲

κA) → (∀κ. A)

slide-29
SLIDE 29

From Infjnite to Finite, again

Can we write take :: Natural → (∀κ. Streamκ) → [Integer] by structural recursion on the fjrst argument? take 0 s take n 1 s x take n force s’ where x s’ s

slide-30
SLIDE 30

From Infjnite to Finite, again

Can we write take :: Natural → (∀κ. Streamκ) → [Integer] by structural recursion on the fjrst argument? take 0 s = [] take (n + 1) s = x : take n (force s’) where (x, s’) = deStreamCons s

slide-31
SLIDE 31

Derivation

Let Γ = s : ∀κ. Streamκ κ; Γ ⊢ s : ∀κ. Streamκ κ; Γ ⊢ s : Streamκ κ; Γ ⊢ deStreamCons s : (Integer, ⊲

κStreamκ)

; Γ ⊢ deStreamCons s : ∀κ. (Integer, ⊲

κStreamκ)

; Γ ⊢ deStreamCons s : (Integer, ∀κ. ⊲

κStreamκ)

slide-32
SLIDE 32

Replace-Min

A classic example (Bird, 1984) replaceMin :: Tree → Tree replaceMin t = let (t’, m) = replaceMinBody (t, m) in t’ where replaceMinBody (Leaf x, m) = (Leaf m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in (Br l’ r’, min ml mr)

slide-33
SLIDE 33

With Clocks

replaceMinBody :: ∀κ. (Tree, ⊲

κ Integer) → ( ⊲ κ Tree, Integer)

replaceMinBody (Leaf x, m) = ( delay Leaf ⊛ m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in ( delay Br ⊛ l’ ⊛ r’, min ml mr) trace A U B U A B replaceMin Tree Tree replaceMin t force trace replaceMinBody t

slide-34
SLIDE 34

With Clocks

replaceMinBody :: ∀κ. (Tree, ⊲

κ Integer) → ( ⊲ κ Tree, Integer)

replaceMinBody (Leaf x, m) = ( delay Leaf ⊛ m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in ( delay Br ⊛ l’ ⊛ r’, min ml mr) trace A U B U A B replaceMin Tree Tree replaceMin t force trace replaceMinBody t

slide-35
SLIDE 35

With Clocks

replaceMinBody :: ∀κ. (Tree, ⊲

κ Integer) → ( ⊲ κ Tree, Integer)

replaceMinBody (Leaf x, m) = ( delay Leaf ⊛ m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in ( delay Br ⊛ l’ ⊛ r’, min ml mr) trace A U B U A B replaceMin Tree Tree replaceMin t force trace replaceMinBody t

slide-36
SLIDE 36

With Clocks

replaceMinBody :: ∀κ. (Tree, ⊲

κ Integer) → ( ⊲ κ Tree, Integer)

replaceMinBody (Leaf x, m) = ( delay Leaf ⊛ m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in ( delay Br ⊛ l’ ⊛ r’, min ml mr) trace A U B U A B replaceMin Tree Tree replaceMin t force trace replaceMinBody t

slide-37
SLIDE 37

With Clocks

replaceMinBody :: ∀κ. (Tree, ⊲

κ Integer) → ( ⊲ κ Tree, Integer)

replaceMinBody (Leaf x, m) = ( delay Leaf ⊛ m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in ( delay Br ⊛ l’ ⊛ r’, min ml mr) trace A U B U A B replaceMin Tree Tree replaceMin t force trace replaceMinBody t

slide-38
SLIDE 38

With Clocks

replaceMinBody :: ∀κ. (Tree, ⊲

κ Integer) → ( ⊲ κ Tree, Integer)

replaceMinBody (Leaf x, m) = ( delay Leaf ⊛ m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in ( delay Br ⊛ l’ ⊛ r’, min ml mr) trace A U B U A B replaceMin Tree Tree replaceMin t force trace replaceMinBody t

slide-39
SLIDE 39

With Clocks

replaceMinBody :: ∀κ. (Tree, ⊲

κ Integer) → ( ⊲ κ Tree, Integer)

replaceMinBody (Leaf x, m) = ( delay Leaf ⊛ m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in ( delay Br ⊛ l’ ⊛ r’, min ml mr) trace :: ∀κ. ((A[κ], ⊲

κU) → (B[κ], U)) → A[κ] → B[κ]

replaceMin Tree Tree replaceMin t force trace replaceMinBody t

slide-40
SLIDE 40

With Clocks

replaceMinBody :: ∀κ. (Tree, ⊲

κ Integer) → ( ⊲ κ Tree, Integer)

replaceMinBody (Leaf x, m) = ( delay Leaf ⊛ m, x) replaceMinBody (Br l r, m) = let (l’, ml) = replaceMinBody l m let (r’, mr) = replaceMinBody r m in ( delay Br ⊛ l’ ⊛ r’, min ml mr) trace :: ∀κ. ((A[κ], ⊲

κU) → (B[κ], U)) → A[κ] → B[κ]

replaceMin :: Tree → Tree replaceMin t = force (trace replaceMinBody t)

slide-41
SLIDE 41

Related Work

slide-42
SLIDE 42

Related Work

A Modality for recursion (Nakano, 2000) Step-indexed Logical Relations (Appel, McAllester, 2001) (Dreyer, Ahmed, Birkedal, 2011) Time Flies like an Applicative Functor (McBride, 2009) First steps in synthetic guarded domain theory: step-indexing in the topos of trees (Birkedal, Møgelberg, Støvring, Schwinghammer, 2011) Ultrametric Semantics of Reactive Programs (Krishnaswami, Benton, 2011) The Logic of Provability (Boolos, 1993)

. . Short of time?

slide-43
SLIDE 43

Formal Calculus

slide-44
SLIDE 44

Types

Well formed types: ∆ ⊢ A where ∆ = κ1, ..., κn ∆ ⊢ 1 ∆ ⊢ A ∆ ⊢ B ∆ ⊢ A → B ∆ ⊢ A ∆ ⊢ B ∆ ⊢ A × B ∆ ⊢ A ∆ ⊢ B ∆ ⊢ A + B κ ∈ ∆ ∆ ⊢ A ∆ ⊢ ⊲

κA

∆, κ ⊢ A ∆ ⊢ ∀κ.A

slide-45
SLIDE 45

Type Equalities

A ≡ B is

◮ refmexive, symmetric, transitive ◮ a congruence

and satisfjes: ∀κ.A ≡ A (κ ∈ fv(A)) ∀κ.A + B ≡ (∀κ.A) + (∀κ.B) ∀κ.A × B ≡ (∀κ.A) × (∀κ.B) ∀κ.A → B ≡ A → ∀κ.B (κ ∈ fv(A)) ∀κ.∀κ′.A ≡ ∀κ′.∀κ.A

slide-46
SLIDE 46

Typing Rules

Well-typed terms: ∆; Γ ⊢ e : A where Γ = x1 : A1, ..., xn : An

◮ The simply-typed λ-calculus with products and sums

∆; Γ ⊢ e : A κ ∈ ∆ ∆; Γ ⊢ delay e : ⊲

κA

∆; Γ ⊢ f : ⊲

κ(A → B)

∆; Γ ⊢ e : ⊲

κA

∆; Γ ⊢ f ⊛ e : ⊲

κB

slide-47
SLIDE 47

Typing Rules

∆, κ; Γ ⊢ e : A κ ∈ fv(Γ) ∆; Γ ⊢ e : ∀κ.A ∆; Γ ⊢ e : ∀κ.A κ′ ∈ ∆ ∆; Γ ⊢ e : A[κ → κ′] ∆; Γ ⊢ e : A ∆ ⊢ A ≡ B ∆; Γ ⊢ e : B ∆; Γ ⊢ f : ⊲

κA → A

∆; Γ ⊢ fix f : A ∆; Γ ⊢ e : ∀κ.⊲

κA

∆; Γ ⊢ force e : ∀κ.A

slide-48
SLIDE 48

Data types

Descriptions of data types: F, G ::= A | F × G | F + G | − AX = A F × GX = FX × GX F + GX = FX + GX −X = X F F F

def

F F F F FA A F A F F F F F F

slide-49
SLIDE 49

Data types

Descriptions of data types: F, G ::= A | F × G | F + G | − AX = A F × GX = FX × GX F + GX = FX + GX −X = X ∆ ⊢ µF κ ∈ ∆ ∆ ⊢ νκF νF

def

= ∀κ.νκF F F F FA A F A F F F F F F

slide-50
SLIDE 50

Data types

Descriptions of data types: F, G ::= A | F × G | F + G | − AX = A F × GX = FX × GX F + GX = FX + GX −X = X ∆ ⊢ µF κ ∈ ∆ ∆ ⊢ νκF νF

def

= ∀κ.νκF consµ : F(µF) → µF foldµ : (FA → A) → µF → A consν : F(⊲

κνκF) → νκF

deConsν : νκF → F(⊲

κνκF)

slide-51
SLIDE 51

Semantics

slide-52
SLIDE 52

Untyped Semantics

data D = Lam (D → D) | Inl D | Inr D | Pair D D | Unit − :: Term → (Var → D) → D x η = η(x) λx. e η = Lam (λv. e(η[x → v])) f e η = df (eη) where Lam df = fη (really in DCPO )

slide-53
SLIDE 53

Untyped Semantics

data D = Lam (D → D) | Inl D | Inr D | Pair D D | Unit − :: Term → (Var → D) → D x η = η(x) λx. e η = Lam (λv. e(η[x → v])) f e η = df (eη) where Lam df = fη delay e η = eη f ⊛ e η = df (eη) where Lam df = fη force e η = eη (really in DCPO )

slide-54
SLIDE 54

Untyped Semantics

data D = Lam (D → D) | Inl D | Inr D | Pair D D | Unit − :: Term → (Var → D) → D x η = η(x) λx. e η = Lam (λv. e(η[x → v])) f e η = df (eη) where Lam df = fη delay e η = eη f ⊛ e η = df (eη) where Lam df = fη force e η = eη fjx f η = fix df where Lam df = fη (really in DCPO )

slide-55
SLIDE 55

Untyped Semantics

data D = Lam (D → D) | Inl D | Inr D | Pair D D | Unit − :: Term → (Var → D) → D x η = η(x) λx. e η = Lam (λv. e(η[x → v])) f e η = df (eη) where Lam df = fη delay e η = eη f ⊛ e η = df (eη) where Lam df = fη force e η = eη fjx f η = fix df where Lam df = fη (really in DCPO⊥)

slide-56
SLIDE 56

Semantics of Types

A type ∆ ⊢ A is interpreted as a collection of subsets of D ∆ ⊢ A : N|∆| → P(D) The interpretation of ∆ ⊢ A is parameterised by ∆-many clocks Satisfying:

◮ (n1, ..., n|∆|) ≤ (n′ 1, ..., n′ |∆|) implies

∆ ⊢ A(n′

1, ..., n′ ∆) ⊆ ∆ ⊢ A(n1, ..., n∆) ◮ If x ∈ ∆ ⊢ Aδ and x ⊑ x′ then x′ ∈ ∆ ⊢ Aδ.

slide-57
SLIDE 57

Semantics of Types

δ = (n1, ..., n|∆|) and also: F : P(D) → P(D) 1δ = {Unit} A → Bδ = {Lam f | ∀δ′ ⊑ δ, x ∈ Aδ′. fx ∈ Bδ′} A × Bδ = {Pair(x, y) | x ∈ Aδ ∧ y ∈ Bδ} A + Bδ = {Inl(x) | x ∈ Aδ} ∪ {Inr(y) | y ∈ Bδ} ⊲

κAδ

= { D if δ(κ) = 0 A(δ[κ → n]) if δ(κ) = n + 1 ∀κ.Aδ = ∩

n∈N

A(δ[κ → n]) νκFδ = Fδ(κ)(D) µFδ = ∪

n∈N

Fn(∅)

slide-58
SLIDE 58

Type Safety

Theorem If −; − ⊢ e : A, then for all η ∈ Var → D, eη ∈ ∆ ⊢ A() This means:

◮ eη = ⊥ ◮ If A = ∀κ.νκ(X × −), then e generates infjnitely many Xs

slide-59
SLIDE 59

Slogan

Well typed programs ramble on forever and never get to the ⊥ of things

slide-60
SLIDE 60

Alternative Ending

slide-61
SLIDE 61

Type Safety

Defjne a semantics where:

◮ delay, ⊛, force are no-ops, and

fjx is interpreted by domain-theoretic fjxpoint If −; − ⊢ e : A, then

◮ eη = ⊥ ◮ If A = ∀κ.νκ(X × −), then e generates infjnitely many Xs

slide-62
SLIDE 62

Slogan

Well typed programs ramble on forever and never get to the ⊥ of things