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