Preliminaries Programming Coprogramming Advanced Coprogramming - - PowerPoint PPT Presentation

preliminaries programming coprogramming advanced
SMART_READER_LITE
LIVE PREVIEW

Preliminaries Programming Coprogramming Advanced Coprogramming - - PowerPoint PPT Presentation

Certified Functional (Co)programming with Jasmin Andreas Andrei Dmitriy Blanchette Lochbihler Popescu Traytel Partly based on material by Tobias Nipkow Preliminaries Programming Coprogramming Advanced Coprogramming Preliminaries


slide-1
SLIDE 1

Certified Functional (Co)programming with

Jasmin Blanchette Andreas Lochbihler Andrei Popescu Dmitriy Traytel Partly based on material by Tobias Nipkow

slide-2
SLIDE 2

Preliminaries Programming Coprogramming Advanced Coprogramming

slide-3
SLIDE 3

Preliminaries

Applications Higher-Order Logic Proving

Programming Coprogramming Advanced Coprogramming

slide-4
SLIDE 4

Big proofs about programs

(an incomplete list)

seL4

Microkernel Klein et al.

Flyspeck

Programs in Hales’s proof

  • f the Kepler conjecture

Bauer, Nipkow, Obua

JinjaThreads

Java compiler & JMM Lochbihler

CAVA

LTL model checker Lammich, Nipkow et al.

CoCon

Conference management system Lammich, Popescu et al.

IsaFoR/CeTA

Termination proof certifier Sternagel, Thiemann et al.

Markov_Models

pCTL model checker Hölzl, Nipkow

PDF-Compiler

Probability density functions compiler Eberl, Hölzl, Nipkow

IsaSAT

SAT solver with 2WL Fleury, Blanchette et al.

slide-5
SLIDE 5

HOL = Higher-Order Logic

slide-6
SLIDE 6

HOL = Higher-Order Logic HOL = Functional Programming + Logic

slide-7
SLIDE 7

HOL = Higher-Order Logic HOL = Functional Programming + Logic HOL has

  • (co)datatypes
  • (co)recursive functions
  • logical operators
slide-8
SLIDE 8

HOL = Higher-Order Logic HOL = Functional Programming + Logic HOL has

  • (co)datatypes
  • (co)recursive functions
  • logical operators

HOL is a programming language! Higher-order = functions are values, too

slide-9
SLIDE 9

HOL = Higher-Order Logic HOL = Functional Programming + Logic HOL has

  • (co)datatypes
  • (co)recursive functions
  • logical operators

HOL is a programming language! Higher-order = functions are values, too HOL formulas:

  • Equations: term = term,

e.g. 1+ 2 = 4

  • Also: ∧, ∨, −

→, ∀, ∃, . . .

slide-10
SLIDE 10

Types

Basic syntax τ

::=

(τ) |

bool | nat | int | ···

base types

|

’a | ’b | ···

type variables

| τ ⇒ τ

functions (ASCII: =>)

| τ×τ

pairs (ASCII: *)

| τ list

lists

| τ set

sets

|

. . . user-defined types

slide-11
SLIDE 11

Terms

Basic syntax

t ::=

(t) |

a constant or variable (identifier)

|

t t function application

| λx. t

function abstraction

|

. . . lots of syntactic sugar Examples:

f (g x) y h (%x. f (g x))

slide-12
SLIDE 12

Terms must be well-typed

(the argument of every function call must be of the right type)

slide-13
SLIDE 13

Terms must be well-typed

(the argument of every function call must be of the right type)

Notation: t :: τ means “t is a well-typed term of type τ”. t :: τ1 ⇒ τ2 u :: τ1 t u :: τ2

slide-14
SLIDE 14

Type inference

Isabelle automatically computes the type of each variable in a term. In the presence of overloaded functions (functions with multiple types) this is not always possible. Users can help with type annotations inside the term. Example:

f (x::nat)

slide-15
SLIDE 15

Currying

Thou shalt curry thy functions

  • Curried:

f :: τ1 ⇒ τ2 ⇒ τ

  • Tupled:

f’ :: τ1 ×τ2 ⇒ τ

slide-16
SLIDE 16

Currying

Thou shalt curry thy functions

  • Curried:

f :: τ1 ⇒ τ2 ⇒ τ

  • Tupled:

f’ :: τ1 ×τ2 ⇒ τ

Advantage: Currying allows partial application

f a1 where a1 :: τ1

slide-17
SLIDE 17

Formulas

Metalogic (Pure):

  • Type prop
  • Constants:

:: (’a ⇒ prop) ⇒ prop

= ⇒ :: prop ⇒ prop ⇒ prop ≡ :: ’a ⇒ ’a ⇒ prop

slide-18
SLIDE 18

Formulas

Metalogic (Pure):

  • Type prop
  • Constants:

:: (’a ⇒ prop) ⇒ prop

= ⇒ :: prop ⇒ prop ⇒ prop ≡ :: ’a ⇒ ’a ⇒ prop

Object logic (HOL):

  • Type bool
  • Constants:

Trueprop :: bool ⇒ prop

(implicit)

∀,∃ :: (’a ⇒ bool) ⇒ bool − →,∧,∨,... :: bool ⇒ bool ⇒ bool = :: ’a ⇒ ’a ⇒ bool

slide-19
SLIDE 19

Syntactic sugar

  • Infix:

+, -, *, #, @, . . .

  • Mixfix:

if _ then _ else _, case _ of, . . .

  • Binders:

_. _, ∀_. _, ∃_. _, . . .

slide-20
SLIDE 20

Syntactic sugar

  • Infix:

+, -, *, #, @, . . .

  • Mixfix:

if _ then _ else _, case _ of, . . .

  • Binders:

_. _, ∀_. _, ∃_. _, . . . Prefix binds more strongly than infix:

f x + y ≡ (f x) + y ≡ f (x + y)

Enclose if and case in parentheses:

(if _ then _ else _)

slide-21
SLIDE 21

Theory = Isabelle Module

slide-22
SLIDE 22

Theory = Isabelle Module

Syntax

theory MyTh imports T1 . . . Tn begin

(definitions, theorems, proofs, ...)∗

end

slide-23
SLIDE 23

Theory = Isabelle Module

Syntax

theory MyTh imports T1 . . . Tn begin

(definitions, theorems, proofs, ...)∗

end

MyTh: name of theory. Must live in file MyTh.thy Ti: names of imported theories. Import transitive. Typically:

imports Main

slide-24
SLIDE 24

Concrete syntax

In .thy files: Types, terms and formulas need to be inclosed in double quotes (")

slide-25
SLIDE 25

Concrete syntax

In .thy files: Types, terms and formulas need to be inclosed in double quotes (") except for single identifiers.

slide-26
SLIDE 26

Concrete syntax

In .thy files: Types, terms and formulas need to be inclosed in double quotes (") except for single identifiers. Double quotes are not always shown on slides.

slide-27
SLIDE 27

Isabelle/jEdit

  • Based on the jEdit editor
  • Processes Isabelle text automatically

when editing .thy files (like modern Java IDEs)

  • Bottom panels: Output, Query (Find Theorems), . . .
  • Side panels: State, Theories, . . .
slide-28
SLIDE 28

The proof state

  • 1. x1 ...xm. A1 =

⇒ ··· = ⇒ An = ⇒ C

x1,...,xm fixed local variables A1,...,An local assumptions C actual (sub)goal

slide-29
SLIDE 29

Apply scripts

General schema:

lemma name: "..." lemma name: "..." apply (...) apply (...)

. . . . . .

apply (...) apply (...) apply (...) by (...) done

slide-30
SLIDE 30

Apply scripts

General schema:

lemma name: "..." lemma name: "..." apply (...) apply (...)

. . . . . .

apply (...) apply (...) apply (...) by (...) done

If the lemma is suitable as a simplification rule:

lemma name[simp]: "..."

slide-31
SLIDE 31

Delayed gratification

The command oops gives up the current proof attempt. The command sorry “completes” any proof. It makes top-down development possible: Assume lemma first, prove it later.

slide-32
SLIDE 32

Isar Proofs

Apply script = assembly language program

slide-33
SLIDE 33

Isar Proofs

Apply script = assembly language program Isar proof = structured program with comments

slide-34
SLIDE 34

Isar Proofs

Apply script = assembly language program Isar proof = structured program with comments But apply still useful for proof exploration.

slide-35
SLIDE 35

A typical Isar proof

A proof of ϕ0 =

⇒ ϕn+1:

proof assume ϕ0 have ϕ1 by simp

. . .

have ϕn by blast show ϕn+1 by ... qed

slide-36
SLIDE 36

Isar core syntax

proof =

proof [method] step∗ qed

|

by method

method =

(simp ...) | (blast ...) | (induction ...) | ···

step =

fix variables

()

|

assume prop

(=

⇒) |

[from fact+] (have | show) prop proof prop = [name:] "formula" fact = name | ···

slide-37
SLIDE 37

Example: Cantor’s theorem

lemma "¬ surj (f :: ’a ⇒ ’a set)" proof assume a: "surj f" from a have b: "∀A. ∃a. A = f a" by (simp add: surj_def) from b have c: "∃a. {x. x /

∈ f x} = f a"

by blast from c show False by blast qed

slide-38
SLIDE 38

Abbreviations

this = the previous proposition proved or assumed

then

=

from this

slide-39
SLIDE 39

using and with

(have | show) prop using facts

slide-40
SLIDE 40

using and with

(have | show) prop using facts =

from facts (have | show) prop

slide-41
SLIDE 41

using and with

(have | show) prop using facts =

from facts (have | show) prop with facts

=

from facts this

slide-42
SLIDE 42

Structured lemma statement

lemma fixes f :: "’a ⇒ ’a set" assumes s: "surj f" shows False proof - have "∃a. {x. x /

∈ f x} = f a"

using s by (auto simp: surj_def) then show False by blast qed

slide-43
SLIDE 43

Structured lemma statement

lemma fixes f :: "’a ⇒ ’a set" assumes s: "surj f" shows False proof - have "∃a. {x. x /

∈ f x} = f a"

using s by (auto simp: surj_def) then show False by blast qed

Proves surj f =

⇒ False

but surj f becomes local fact s in proof.

slide-44
SLIDE 44

Structured lemma statements

fixes x :: τ1 and y :: τ2 . . . assumes a: P and b: Q . . . shows R

slide-45
SLIDE 45

Structured lemma statements

fixes x :: τ1 and y :: τ2 . . . assumes a: P and b: Q . . . shows R

  • fixes and assumes sections optional
  • shows optional if no fixes and assumes
slide-46
SLIDE 46

Case distinction

show "R" proof cases assume "P" ... show "R" ... next assume "¬ P" ... show "R" ... qed

slide-47
SLIDE 47

Case distinction

show "R" proof cases assume "P" ... show "R" ... next assume "¬ P" ... show "R" ... qed have "P ∨ Q" ... then show "R" proof assume "P" ... show "R" ... next assume "Q" ... show "R" ... qed

slide-48
SLIDE 48

Contradiction

show "¬ P" proof assume "P" ... show False ... qed

slide-49
SLIDE 49

Contradiction

show "¬ P" proof assume "P" ... show False ... qed show "P" proof (rule ccontr) assume "¬ P" ... show False ... qed

slide-50
SLIDE 50

← →

show "P ←

→ Q"

proof assume "P" ... show "Q" ... next assume "Q" ... show "P" ... qed

slide-51
SLIDE 51

∀ and ∃ introduction

show "∀x. P x" proof fix x show "P x" ... qed

slide-52
SLIDE 52

∀ and ∃ introduction

show "∀x. P x" proof fix x show "P x" ... qed show "∃x. P x" proof ... show "P witness" ... qed

slide-53
SLIDE 53

Preliminaries Programming

Datatypes Recursion Induction

Coprogramming Advanced Coprogramming

slide-54
SLIDE 54

Natural numbers

datatype nat = | Suc nat

slide-55
SLIDE 55

Natural numbers

datatype nat = | Suc nat

This introduces:

  • The type nat
  • The constructors 0 :: nat and Suc :: nat ⇒ nat
  • A case combinator case_nat
  • A (primitive) recursor constant rec_nat
  • Various theorems about the above, including an induction rule

Numeral notations are also supported:

3 = Suc (Suc (Suc 0) is a theorem

slide-56
SLIDE 56

Lists

datatype ’a list = Nil | Cons ’a "’a list"

slide-57
SLIDE 57

Lists

datatype ’a list = Nil | Cons ’a "’a list"

More honest

datatype (set: ’a) list = Nil ("[]") | Cons ’a "’a list" (infixr "#" 65) for map: map

slide-58
SLIDE 58

Lists

datatype ’a list = Nil | Cons ’a "’a list"

More honest

datatype (set: ’a) list = Nil ("[]") | Cons ’a "’a list" (infixr "#" 65) for map: map

This introduces:

  • The type ’a list and the constructors Nil and Cons
  • A functorial action: map :: (’a ⇒ ’b) ⇒ ’a list ⇒ ’b list
  • A natural transformation: set :: ’a list ⇒ ’a set
  • A size function: size :: ’a list ⇒ nat
  • etc.
slide-59
SLIDE 59

List notations

Empty list:

[]

Cons:

x # xs

Enumeration:

[x1, x2, ..., xn]

Head:

hd (x # xs) = x

Tail:

tl (x # xs) = xs tl [] = []

Case:

(case xs of [] ⇒ ... | y # ys ⇒ ...)

slide-60
SLIDE 60

Primitive recursion

Definition using primrec or fun:

primrec append :: ’a list ⇒ ’a list ⇒ ’a list (infixr "@" 65) where [] @ ys = ys | (x # xs) @ ys = x # (xs @ ys)

slide-61
SLIDE 61

Primitive recursion

Definition using primrec or fun:

primrec append :: ’a list ⇒ ’a list ⇒ ’a list (infixr "@" 65) where [] @ ys = ys | (x # xs) @ ys = x # (xs @ ys)

Code export:

export_code append in Haskell

slide-62
SLIDE 62

Primitive recursion

Definition using primrec or fun:

primrec append :: ’a list ⇒ ’a list ⇒ ’a list (infixr "@" 65) where [] @ ys = ys | (x # xs) @ ys = x # (xs @ ys)

Code export:

export_code append in Haskell

Symbolic evaluation in Isabelle:

value "[1,2,3] @ [4,5,6] :: int list"

slide-63
SLIDE 63

Structural induction

We want to prove xs @ [] = xs.

slide-64
SLIDE 64

Structural induction

We want to prove xs @ [] = xs.

Structural induction rule (thm list.induct)

?P [] =

(base case)

( x xs. ?P xs =

⇒ ?P (x # xs)) = ⇒

(induction step)

?P ?list

slide-65
SLIDE 65

Structural induction

We want to prove xs @ [] = xs.

Structural induction rule (thm list.induct)

?P [] =

(base case)

( x xs. ?P xs =

⇒ ?P (x # xs)) = ⇒

(induction step)

?P ?list

Base case:

[] @ [] = []

(by definition of @)

slide-66
SLIDE 66

Structural induction

We want to prove xs @ [] = xs.

Structural induction rule (thm list.induct)

?P [] =

(base case)

( x xs. ?P xs =

⇒ ?P (x # xs)) = ⇒

(induction step)

?P ?list

Base case:

[] @ [] = []

(by definition of @) Induction step:

(x # xs) @ [] = x # (xs @ [])

(by definition of @)

= x # xs

(by induction hypothesis)

slide-67
SLIDE 67

List reversal

[1,2,3,4]

rev

− − − →

[4,3,2,1]

slide-68
SLIDE 68

List reversal

[1,2,3,4]

rev

− − − →

[4,3,2,1]

Naive list reversal

primrec rev :: ’a list ⇒ ’a list where rev [] = [] | rev (x # xs) = rev xs @ [x]

slide-69
SLIDE 69

List reversal

[1,2,3,4]

rev

− − − →

[4,3,2,1]

Naive list reversal

primrec rev :: ’a list ⇒ ’a list where rev [] = [] | rev (x # xs) = rev xs @ [x]

Fast list reversal

primrec qrev :: ’a list ⇒ ’a list ⇒ ’a list where qrev [] ys = ys | qrev (x # xs) ys = qrev xs (x # ys)

  • 1. What is rev (rev xs)?
  • 2. Are rev and qrev equivalent? What is the relationship?
slide-70
SLIDE 70

Well-founded recursion

[a,b,c,d,e] [X,Y,Z] merge [a,X,b,Y,c,Z,d,e]

Merge two lists

function merge :: ’a list ⇒ ’a list ⇒ ’a list where merge [] ys = ys | merge (x # xs) ys = x # merge ys xs

Not primitively recursive! We need a termination proof:

termination proof(relation "measure (λ(xs, ys). size xs + size ys)") qed simp_all

slide-71
SLIDE 71

Well-founded recursion

[a,b,c,d,e] [X,Y,Z] merge [a,X,b,Y,c,Z,d,e]

Merge two lists

function merge :: ’a list ⇒ ’a list ⇒ ’a list where merge [] ys = ys | merge (x # xs) ys = x # merge ys xs

Not primitively recursive! We need a termination proof:

termination proof(relation "measure (λ(xs, ys). size xs + size ys)") qed simp_all

With proof automation:

termination by size_change

slide-72
SLIDE 72

Termination proofs yield induction rules

merge [] ys = ys merge (x # xs) ys = x # merge ys xs

How can we prove size (merge xs ys) = size xs + size ys?

slide-73
SLIDE 73

Termination proofs yield induction rules

merge [] ys = ys merge (x # xs) ys = x # merge ys xs

How can we prove size (merge xs ys) = size xs + size ys?

Structural induction on xs does not work!

Induction hypothesis: size (merge xs ys) = size xs + size ys

size (merge (x # xs) ys) = size (x # merge ys xs) = 1 + size (merge ys xs) = ...

slide-74
SLIDE 74

Termination proofs yield induction rules

merge [] ys = ys merge (x # xs) ys = x # merge ys xs

How can we prove size (merge xs ys) = size xs + size ys?

Structural induction on xs does not work!

Induction hypothesis: size (merge xs ys) = size xs + size ys

size (merge (x # xs) ys) = size (x # merge ys xs) = 1 + size (merge ys xs) = ...

Induction rule for merge

(

  • ys. ?P [] ys) =

(1st equation)

( x xs ys. ?P ys xs =

⇒ ?P (x # xs) ys) = ⇒

(2nd equation)

?P ?xs ?ys

slide-75
SLIDE 75

Finitely-branching Rose trees

C [] A [•] D [] E [•,•] X [] Y [] Z [] T [•,•,•,•]

datatype ’a rtree = Node ’a "’a rtree list"

slide-76
SLIDE 76

Finitely-branching Rose trees

C [] A [•] D [] E [•,•] X [] Y [] Z [] T [•,•,•,•]

datatype ’a rtree = Node ’a "’a rtree list"

Structural induction

( x ts. (

  • t. t ∈ set ts =

⇒ ?P t) = ⇒ ?P (Node x ts)) = ⇒

?P ?tree

slide-77
SLIDE 77

Mirroring rose trees

C [] A [•] D [] E [•,•] X [] Y [] Z [] T [•,•,•,•]

rmirror

− − − − − →

C [] A [•] D [] E [•,•] X [] Y [] Z [] T [•,•,•,•]

primrec rmirror :: ’a tree ⇒ ’a tree where rmirror (Node x ts) = Node x (rev (map rmirror ts))

slide-78
SLIDE 78

Mirroring rose trees

C [] A [•] D [] E [•,•] X [] Y [] Z [] T [•,•,•,•]

rmirror

− − − − − →

C [] A [•] D [] E [•,•] X [] Y [] Z [] T [•,•,•,•]

primrec rmirror :: ’a tree ⇒ ’a tree where rmirror (Node x ts) = Node x (rev (map rmirror ts))

Prove rmirror (rmirror t) = t by structural induction

IH: rmirror (rmirror t) = t for all t ∈ set ts

rmirror (rmirror (Node x ts)) = rmirror (Node x (rev (map rmirror ts))) = Node x (rev (map rmirror (rev (map rmirror ts)))) = Node x (rev (rev (map rmirror (map rmirror ts)))) = Node x (map (rmirror ◦ rmirror) ts)

by IH?

= Node x (map id ts) = Node x ts

slide-79
SLIDE 79

Conditional term rewriting

Congruence rule for map

?xs = ?ys =

(

  • y. y ∈ set ?ys =

⇒ ?f y = ?g y) = ⇒

map ?f ?xs = map ?g ?ys

Assume: rmirror (rmirror t) = t for all t ∈ set ts Show: map (rmirror ◦ rmirror) ts = map id ts

map (rmirror ◦ rmirror) ts = ??

slide-80
SLIDE 80

Conditional term rewriting

Congruence rule for map

?xs = ?ys =

(

  • y. y ∈ set ?ys =

⇒ ?f y = ?g y) = ⇒

map ?f ?xs = map ?g ?ys

Assume: rmirror (rmirror t) = t for all t ∈ set ts Show: map (rmirror ◦ rmirror) ts = map id ts

ts = ??

  • t. t ∈ set ?? =

⇒ (rmirror ◦ rmirror) t =

?? t map (rmirror ◦ rmirror) ts = map ?? ??

slide-81
SLIDE 81

Conditional term rewriting

Congruence rule for map

?xs = ?ys =

(

  • y. y ∈ set ?ys =

⇒ ?f y = ?g y) = ⇒

map ?f ?xs = map ?g ?ys

Assume: rmirror (rmirror t) = t for all t ∈ set ts Show: map (rmirror ◦ rmirror) ts = map id ts

ts = ts

  • t. t ∈ set ts =

⇒ (rmirror ◦ rmirror) t =

?? t map (rmirror ◦ rmirror) ts = map ?? ts

slide-82
SLIDE 82

Conditional term rewriting

Congruence rule for map

?xs = ?ys =

(

  • y. y ∈ set ?ys =

⇒ ?f y = ?g y) = ⇒

map ?f ?xs = map ?g ?ys

Assume: rmirror (rmirror t) = t for all t ∈ set ts Show: map (rmirror ◦ rmirror) ts = map id ts

ts = ts

  • t. t ∈ set ts =

rmirror (rmirror t) = ?? t map (rmirror ◦ rmirror) ts = map ?? ts

slide-83
SLIDE 83

Conditional term rewriting

Congruence rule for map

?xs = ?ys =

(

  • y. y ∈ set ?ys =

⇒ ?f y = ?g y) = ⇒

map ?f ?xs = map ?g ?ys

Assume: rmirror (rmirror t) = t for all t ∈ set ts Show: map (rmirror ◦ rmirror) ts = map id ts

ts = ts

  • t. t ∈ set ts =

⇒ t ∈ set ts

  • t. t ∈ set ts =

rmirror (rmirror t) = (λx. x) t map (rmirror ◦ rmirror) ts = map (λx. x) ts

slide-84
SLIDE 84

Now it’s your turn

  • 1. Download Programming.thy from the tutorial webpage and
  • pen it in Isabelle/jEdit.
  • 2. Define concat :: ’a list list ⇒ ’a list

Find out how concat behaves w.r.t. @ and rev and prove it.

  • 3. Define pre-order and post-order traversals for rose trees.

Prove that preorder (rmirror t) = rev (postorder t).

slide-85
SLIDE 85

Preliminaries Programming Coprogramming

Codatatypes Primitive Corecursion Coinduction

Advanced Coprogramming

slide-86
SLIDE 86

Types with infinite values

type finite values infinite values nat 0, 1, 2, 3, ... enat 0, 1, 2, 3, ...

slide-87
SLIDE 87

Types with infinite values

type finite values infinite values

0, S(0), S(S(0)), S(S(S(0))), ...

nat 0, 1, 2, 3, ... enat 0, 1, 2, 3, ...

0, S(0), S(S(0)), S(S(S(0))), ... S(S(S(S(S(...)))))

slide-88
SLIDE 88

Types with infinite values

type finite values infinite values

0, S(0), S(S(0)), S(S(S(0))), ...

nat 0, 1, 2, 3, ... enat 0, 1, 2, 3, ...

0, S(0), S(S(0)), S(S(S(0))), ... S(S(S(S(S(...)))))

list

[], [0], [0,0], [0,1,2,3,4], ...

stream

[0,0,0,...], [1,2,3,...], [0,1,0,1,...], ...

llist

[], [0], [0,0], [0,1,2,3,4], ... [0,0,0,...], [1,2,3,...], [0,1,0,1,...], ...

slide-89
SLIDE 89

Types with infinite values

type finite values infinite values

0, S(0), S(S(0)), S(S(S(0))), ...

nat 0, 1, 2, 3, ... enat 0, 1, 2, 3, ...

0, S(0), S(S(0)), S(S(S(0))), ... S(S(S(S(S(...)))))

list

[], [0], [0,0], [0,1,2,3,4], ...

stream

[0,0,0,...], [1,2,3,...], [0,1,0,1,...], ...

llist

[], [0], [0,0], [0,1,2,3,4], ... [0,0,0,...], [1,2,3,...], [0,1,0,1,...], ...

tree

·

4

· ·

5 3

· ·

8 6

· · ·

5 3

· ·

8 5 3

· ·

8 5 . . . . . .

· ·

slide-90
SLIDE 90

Codatatypes in Isabelle/HOL

datatype nat = | Suc nat codatatype enat = Zero | eSuc enat

slide-91
SLIDE 91

Codatatypes in Isabelle/HOL

datatype nat = | Suc nat codatatype enat = is_zero: Zero | eSuc (epred: enat) where "epred Zero = Zero"

discriminator selector defaults

slide-92
SLIDE 92

Codatatypes in Isabelle/HOL

datatype nat = | Suc nat codatatype enat = is_zero: Zero | eSuc (epred: enat) where "epred Zero = Zero"

discriminator selector defaults

datatype ’a list = Nil | Cons ’a "’a list" codatatype ’a stream = SCons ’a "’a stream" codatatype ’a llist = LNil | LCons ’a "’a llist"

slide-93
SLIDE 93

Codatatypes in Isabelle/HOL

datatype nat = | Suc nat codatatype enat = is_zero: Zero | eSuc (epred: enat) where "epred Zero = Zero"

discriminator selector defaults

datatype ’a list = Nil | Cons ’a "’a list" codatatype ’a stream = SCons ’a "’a stream" codatatype ’a llist = LNil | LCons ’a "’a llist" codatatype ’a tree = is_Leaf: Leaf | Node (left: ’a tree) (val: ’a) (right: ’a tree) where "left Leaf = Leaf" | "right Leaf = Leaf"

slide-94
SLIDE 94

No recursion on codatatypes

datatype nat = 0 | Suc nat codatatype enat = Zero | eSuc enat

Suppose we could do recursion on codatatypes . . .

primrec to_nat :: enat ⇒ nat where to_nat Zero = 0 | to_nat (eSuc n) = Suc (to_nat n)

slide-95
SLIDE 95

No recursion on codatatypes

datatype nat = 0 | Suc nat codatatype enat = Zero | eSuc enat

Suppose we could do recursion on codatatypes . . .

primrec to_nat :: enat ⇒ nat where to_nat Zero = 0 | to_nat (eSuc n) = Suc (to_nat n)

. . . but codatatypes are not well-founded: ∞ = eSuc ∞

to_nat ∞ = to_nat (eSuc ∞) = Suc (to_nat ∞)

n

=

1+ n

False

slide-96
SLIDE 96

Building infinite values by primitive corecursion

primitive recursion

  • datatype as argument
  • peel off one constructor
  • recursive call only on

arguments of the constructor

primitive corecursion

  • codatatype as result
  • produce one constructor
  • corecursive call only in

arguments to the constructor

codatatype enat = Zero | eSuc enat primcorec infty :: enat ("∞") where ∞ = eSuc ∞

slide-97
SLIDE 97

Building infinite values by primitive corecursion

primitive recursion

  • datatype as argument
  • peel off one constructor
  • recursive call only on

arguments of the constructor

primitive corecursion

  • codatatype as result
  • produce one constructor
  • corecursive call only in

arguments to the constructor

codatatype enat = Zero | eSuc enat primcorec infty :: enat ("∞") where ∞ = eSuc ∞

Derive destructor characterisation:

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

slide-98
SLIDE 98

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

slide-99
SLIDE 99

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call

slide-100
SLIDE 100

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument

slide-101
SLIDE 101

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

slide-102
SLIDE 102

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

Evaluate ∞ ⊕ 3

slide-103
SLIDE 103

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

Evaluate ∞ ⊕ 3 by observing!

is_zero (

∞ ⊕ 3) =

slide-104
SLIDE 104

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

Evaluate ∞ ⊕ 3 by observing!

is_zero (

∞ ⊕ 3) = False

slide-105
SLIDE 105

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

Evaluate ∞ ⊕ 3 by observing!

is_zero (

∞ ⊕ 3) = False

epred (

∞ ⊕ 3) =

slide-106
SLIDE 106

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

Evaluate ∞ ⊕ 3 by observing!

is_zero (

∞ ⊕ 3) = False

epred (

∞ ⊕ 3) = epred ∞ ⊕ 3

slide-107
SLIDE 107

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

Evaluate ∞ ⊕ 3 by observing!

is_zero (

∞ ⊕ 3) = False

epred (

∞ ⊕ 3) = epred ∞ ⊕ 3

is_zero (epred ∞ ⊕ 3) =

slide-108
SLIDE 108

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

Evaluate ∞ ⊕ 3 by observing!

is_zero (

∞ ⊕ 3) = False

epred (

∞ ⊕ 3) = epred ∞ ⊕ 3

is_zero (epred ∞ ⊕ 3) = is_zero (∞ ⊕ 3) = False epred (epred ∞ ⊕ 3) = . . .

slide-109
SLIDE 109

Computing with infinite values

Computing with codatatypes is pattern matching on results: We can inspect arbitrary finite amounts of output in finitely many steps.

Addition on enat

primcorec eplus :: "enat ⇒ enat ⇒ enat" (infixl "⊕" 65) where "m ⊕ n = (if is_zero m then n else eSuc (epred m ⊕ n))"

corecursive call guard corecursive argument corecursion stops

lemma infty.sel: "is_zero ∞ = False" "epred

∞ = ∞"

Evaluate ∞ ⊕ 3 by observing!

is_zero (

∞ ⊕ 3) = False

epred (

∞ ⊕ 3) = epred ∞ ⊕ 3

is_zero (epred ∞ ⊕ 3) = is_zero (∞ ⊕ 3) = False epred (epred ∞ ⊕ 3) = . . .

Conjecture: ∞ ⊕ 3 = ∞

slide-110
SLIDE 110

When are two extended naturals equals?

If we can make the same observations!

2 =? 2⊕ 0

slide-111
SLIDE 111

When are two extended naturals equals?

If we can make the same observations!

2 =? 2⊕ 0 is-zero 2 = False = is-zero (1⊕ 0) = False epred 2 = 1 =? epred (2⊕ 0) = epred 2⊕ 0 = 1⊕ 0

slide-112
SLIDE 112

When are two extended naturals equals?

If we can make the same observations!

2 =? 2⊕ 0 is-zero 2 = False = is-zero (1⊕ 0) = False epred 2 = 1 =? epred (2⊕ 0) = epred 2⊕ 0 = 1⊕ 0 is-zero 1 = False = is-zero (1⊕ 0) = False epred 1 = 0 =? epred (1⊕ 0) = epred 1⊕ 0 = 0⊕ 0

slide-113
SLIDE 113

When are two extended naturals equals?

If we can make the same observations!

2 =? 2⊕ 0 is-zero 2 = False = is-zero (1⊕ 0) = False epred 2 = 1 =? epred (2⊕ 0) = epred 2⊕ 0 = 1⊕ 0 is-zero 1 = False = is-zero (1⊕ 0) = False epred 1 = 0 =? epred (1⊕ 0) = epred 1⊕ 0 = 0⊕ 0 is-zero 0 = True = is-zero (0⊕ 0) = True

slide-114
SLIDE 114

When are two extended naturals equals?

If we can make the same observations!

2 =? 2⊕ 0 is-zero 2 = False = is-zero (1⊕ 0) = False epred 2 = 1 =? epred (2⊕ 0) = epred 2⊕ 0 = 1⊕ 0 is-zero 1 = False = is-zero (1⊕ 0) = False epred 1 = 0 =? epred (1⊕ 0) = epred 1⊕ 0 = 0⊕ 0 is-zero 0 = True = is-zero (0⊕ 0) = True

Coinduction rule for equality

R n m

∀n m. R n m − → is-zero n = is-zero m ∧ (¬is-zero m − → R (epred n) (epred m))

n = m

slide-115
SLIDE 115

When are two extended naturals equals?

If we can make the same observations!

2 R 2⊕ 0 is-zero 2 = False = is-zero (1⊕ 0) = False epred 2 = 1 R epred (2⊕ 0) = epred 2⊕ 0 = 1⊕ 0 is-zero 1 = False = is-zero (1⊕ 0) = False epred 1 = 0 R epred (1⊕ 0) = epred 1⊕ 0 = 0⊕ 0 is-zero 0 = True = is-zero (0⊕ 0) = True

Coinduction rule for equality

R n m

∀n m. R n m − → is-zero n = is-zero m ∧ (¬is-zero m − → R (epred n) (epred m))

n = m

slide-116
SLIDE 116

Prove that ∞⊕ x = ∞

Coinduction rule for equality

R n m

∀n m. R n m − → is-zero n = is-zero m ∧ (¬is-zero m − → R (epred n) (epred m))

n = m

  • 1. Define R n m ←

→ n = ∞⊕ x ∧ m = ∞

  • 2. Show that R (∞⊕ x) ∞.
  • 3. Show bisimulation property of R:
  • Assume R n m for arbitrary n, m.

So n = ∞⊕ x and m = ∞.

  • is-zero n = is-zero (∞⊕ x) = False = is-zero ∞
  • Show R (epred n) (epred m):
  • epred n = epred (∞⊕ x) = epred ∞⊕ x
  • epred m = epred ∞ = ∞
slide-117
SLIDE 117

Isabelle demo

slide-118
SLIDE 118

From lazy lists to trees and back

codatatype ’a llist = lnull: LNil | LCons (lhd: ’a) (ltl: ’a llist)

tree_of

− − − − − →

llist_of

← − − − − −

codatatype ’a tree = is_Leaf: Leaf | Node (left: ’a tree) (val: ’a) (right: ’a tree)

[0,1,2,...]

tree_of

− − − − − →

slide-119
SLIDE 119

From lazy lists to trees and back

codatatype ’a llist = lnull: LNil | LCons (lhd: ’a) (ltl: ’a llist)

tree_of

− − − − − →

llist_of

← − − − − −

codatatype ’a tree = is_Leaf: Leaf | Node (left: ’a tree) (val: ’a) (right: ’a tree)

[0,1,2,...]

tree_of

− − − − − → ·

1

·

2

·

. . .

slide-120
SLIDE 120

From lazy lists to trees and back

codatatype ’a llist = lnull: LNil | LCons (lhd: ’a) (ltl: ’a llist)

tree_of

− − − − − →

llist_of

← − − − − −

codatatype ’a tree = is_Leaf: Leaf | Node (left: ’a tree) (val: ’a) (right: ’a tree)

[0,1,2,...]

tree_of

− − − − − → ·

1

·

2

·

. . .

[0,1,2,3,4,5,6,...]

llist_of

← − − − − −

1 3 . . . . . . 5 . . . . . . 2 4 . . . . . . 6 . . . . . .

slide-121
SLIDE 121

Tree chopping

Remove the root of a tree:

chop

      

x y

       =

slide-122
SLIDE 122

Tree chopping

Remove the root of a tree:

chop

      

x y

       =

y

chop

  

y

  

slide-123
SLIDE 123

Tree chopping

Remove the root of a tree:

chop

      

x y

       =

y

chop

  

y

  

What if there is a Leaf?

slide-124
SLIDE 124

Preliminaries Programming Coprogramming Advanced Coprogramming

Corecursion Up To Friends Coinduction Up To Friends Mixed Recursion- Corecursion

slide-125
SLIDE 125

Am I productive?

slide-126
SLIDE 126

s = 0 ## s

primitive corecusion

slide-127
SLIDE 127

s = 0 ## s

primitive corecusion

slide-128
SLIDE 128

s = 0 ## stl s

stl evil

slide-129
SLIDE 129

s = 0 ## stl s

stl evil

slide-130
SLIDE 130

s = 0 ## 1 ## s

corecursion up to constructors

slide-131
SLIDE 131

s = 0 ## 1 ## s

corecursion up to constructors

slide-132
SLIDE 132

eo s = shd s ## eo (stl (stl s))

primitive corecusion

slide-133
SLIDE 133

eo s = shd s ## eo (stl (stl s))

primitive corecusion

slide-134
SLIDE 134

s = 0 ## 1 ## eo s

eo evil

slide-135
SLIDE 135

s = 0 ## 1 ## eo s

eo evil

slide-136
SLIDE 136

s ⊕ t = (shd s + shd t) ## (stl s ⊕ stl t)

primitive corecusion

slide-137
SLIDE 137

s ⊕ t = (shd s + shd t) ## (stl s ⊕ stl t)

primitive corecusion

slide-138
SLIDE 138

s ⊗ t = (shd s * shd t) ## (stl s ⊗ t ⊕ s ⊗ stl t) corecursion up to ⊕

slide-139
SLIDE 139

s ⊗ t = (shd s * shd t) ## (stl s ⊗ t ⊕ s ⊗ stl t) corecursion up to ⊕

slide-140
SLIDE 140

The standard definition

slide-141
SLIDE 141

s = 0 ## ((1 ## s) ⊕ s)

corecursion up-to constructors and ⊕

slide-142
SLIDE 142

s = 0 ## ((1 ## s) ⊕ s)

corecursion up-to constructors and ⊕

slide-143
SLIDE 143

s = (0 ## 1 ## s) ⊕ (0 ## s)

corecursion up to constructors and ⊕

⊕ comes before the guard

slide-144
SLIDE 144

s = (0 ## 1 ## s) ⊕ (0 ## s)

corecursion up to constructors and ⊕

⊕ comes before the guard

slide-145
SLIDE 145

s = (1 ## s) ⊗ (1 ## s)

corecursion up to constructors and ⊗

⊗ comes before the guard

slide-146
SLIDE 146

s = (1 ## s) ⊗ (1 ## s)

corecursion up to constructors and ⊗

⊗ comes before the guard

slide-147
SLIDE 147

pow2 t = (2 ˆ shd t) ## (stl s ⊗ pow2 t)

corecursion up to ⊗

slide-148
SLIDE 148

pow2 t = (2 ˆ shd t) ## (stl s ⊗ pow2 t)

corecursion up to ⊗

slide-149
SLIDE 149

s = pow2 (0 ## s)

corecursion up to constructors and pow2

pow2 comes before the guard

slide-150
SLIDE 150

s = pow2 (0 ## s)

corecursion up to constructors and pow2

pow2 comes before the guard

slide-151
SLIDE 151

selfie s = shd s ## selfie (selfie (stl s) ⊕ selfie s) corecursion up to ⊕ and selfie [sic!]

slide-152
SLIDE 152

selfie s = shd s ## selfie (selfie (stl s) ⊕ selfie s) corecursion up to ⊕ and selfie [sic!]

slide-153
SLIDE 153

s m n = if (m == 0 && n > 1) || gcd m n == 1 then n ## s (m * n) (n + 1) else s m (n + 1)

mixed recursion/primitive corecursion

slide-154
SLIDE 154

s m n = if (m == 0 && n > 1) || gcd m n == 1 then n ## s (m * n) (n + 1) else s m (n + 1)

mixed recursion/primitive corecursion

slide-155
SLIDE 155

s n = if n > 0 then s (n - 1) ⊕ (0 ## s (n + 1)) else 1 ## s 1

mixed recursion/corecursion up to ⊕

slide-156
SLIDE 156

s n = if n > 0 then s (n - 1) ⊕ (0 ## s (n + 1)) else 1 ## s 1

mixed recursion/corecursion up to ⊕

slide-157
SLIDE 157

s n = if n > 0 then stl (s (n - 1)) ⊕ (0 ## s (n + 1)) else 1 ## s 1

stl really evil

slide-158
SLIDE 158

s n = if n > 0 then stl (s (n - 1)) ⊕ (0 ## s (n + 1)) else 1 ## s 1

stl really evil

slide-159
SLIDE 159

Isabelle demo

slide-160
SLIDE 160

Exercises Languages as Infinite Tries

. . . . . . . . . . . . a b a b a b a b a b a b a b

Growing a Tree

✽✽

[0,1,2,3,4,5,6,...]

llist_of

← − − − − −

1 3 . . . . . . 5 . . . . . . 2 4 . . . . . . 6 . . . . . .

Factorial via Shuffle

✽✽✽

Prove that s = 1 ## (s ⊗ s) defines the stream of factorials.

slide-161
SLIDE 161

A glimpse with