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 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 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
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
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
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
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
How can we put guardedness constraints into the types?
SLIDE 9
Putting things ofg until tomorrow
(Nakano, 2000) (McBride, 2009)
SLIDE 10
Putting things ofg until tomorrow
(Nakano, 2000) (McBride, 2009)
SLIDE 11
Type-based Guardedness
f :: Integer → Integer → ⊲ Stream → Stream
SLIDE 12
Type-based Guardedness
f :: Integer → Integer → ⊲ Stream → Stream
SLIDE 13 Type-based Guardedness
⊲Stream − “a stream tomorrow” StreamCons :: Integer → ⊲Stream → Stream deStreamCons :: Stream → (Integer, ⊲Stream) fjx :: (⊲A → A) → A
fjx s 1 s fjx x x
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 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
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
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
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
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
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
Clock Variables
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
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
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
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
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
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
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
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
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
Derivation
Let Γ = s : ∀κ. Streamκ κ; Γ ⊢ s : ∀κ. Streamκ κ; Γ ⊢ s : Streamκ κ; Γ ⊢ deStreamCons s : (Integer, ⊲
κStreamκ)
; Γ ⊢ deStreamCons s : ∀κ. (Integer, ⊲
κStreamκ)
; Γ ⊢ deStreamCons s : (Integer, ∀κ. ⊲
κStreamκ)
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
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
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
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
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
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
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
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
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
Related Work
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
Formal Calculus
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 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
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
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
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
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
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
Semantics
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
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
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
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
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
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
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
Slogan
Well typed programs ramble on forever and never get to the ⊥ of things
SLIDE 60
Alternative Ending
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
Slogan
Well typed programs ramble on forever and never get to the ⊥ of things