15-150 Fall 2020 Stephen Brookes Lecture 3 Patterns and - - PowerPoint PPT Presentation

15 150 fall 2020
SMART_READER_LITE
LIVE PREVIEW

15-150 Fall 2020 Stephen Brookes Lecture 3 Patterns and - - PowerPoint PPT Presentation

15-150 Fall 2020 Stephen Brookes Lecture 3 Patterns and specifications Patterns and specifications Patterns and specifications Advice After class, study slides and lecture notes. Start homework early, plan to finish on time.


slide-1
SLIDE 1

15-150 Fall 2020

Stephen Brookes Lecture 3

Patterns and specifications

slide-2
SLIDE 2

Patterns and specifications

slide-3
SLIDE 3

Patterns and specifications

slide-4
SLIDE 4

Advice

  • After class, study slides and lecture notes.
  • Start homework early, plan to finish on time.
  • Don’t use piazza as a first resort,
  • r close to a handin deadline.
  • Ask for help only after you’ve studied, and tried.
  • Think before you write.
slide-5
SLIDE 5

Today

  • A brief remark about equality types
  • Patterns and how to use them
  • Specifying program behavior

evaluation and equivalence

slide-6
SLIDE 6

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

slide-7
SLIDE 7

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list e.g. int list int * bool (int * bool) list

slide-8
SLIDE 8

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

slide-9
SLIDE 9

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list but NOT real or ->

slide-10
SLIDE 10

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

slide-11
SLIDE 11

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

  • 1+1 = 2;

val it = true : bool

slide-12
SLIDE 12

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

  • 1+1 = 2;

val it = true : bool

  • [1,1] = (0+1)::[2-1];

val it = true : bool

slide-13
SLIDE 13

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

  • 1+1 = 2;

val it = true : bool

  • [1,1] = (0+1)::[2-1];

val it = true : bool

  • (fn x => x+x) = (fn y => 2*y);

Error: operator and operand don't agree [equality type required]

slide-14
SLIDE 14

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

  • 1+1 = 2;

val it = true : bool

  • [1,1] = (0+1)::[2-1];

val it = true : bool

slide-15
SLIDE 15

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

  • 1+1 = 2;

val it = true : bool

  • [1,1] = (0+1)::[2-1];

val it = true : bool

  • fun equal(x,y) = (x=y);

val equal = fn - : ”a * ”a -> bool

slide-16
SLIDE 16

equality in ML

e1 = e2

  • Only for expressions whose type is an equality type
  • Equality types are built from

int, bool, - * -, and -list

  • 1+1 = 2;

val it = true : bool

  • [1,1] = (0+1)::[2-1];

val it = true : bool

  • fun equal(x,y) = (x=y);

val equal = fn - : ”a * ”a -> bool

type variable ’’a stands for any equality type

slide-17
SLIDE 17

notation overload

  • ML syntax uses = for several purposes

fn x => e fun f(x) = e val x = 2 val even = fn x => (x mod 2 = 0) fun leq(x, y) = (x <= y) fun geq(x, y) = (x >= y) We also use = in math for “equality”

slide-18
SLIDE 18

patterns

  • ML includes patterns, for matching with values
  • Matching p to value v either fails,
  • r succeeds and binds names to values

p ::= _ | x | n | true | false | (p1, …, pk) | p1::p2 | [p1, …, pk] (can attach type : t if desired) Syntactic restriction: each x occurs at most once in p

slide-19
SLIDE 19

pattern matching

  • _ always matches v
  • x always matches v (and binds x to v)
  • n only matches n, true only matches true
  • (p1, p2) matches (v1, v2)

if p1 matches v1 and p2 matches v2 (combines the bindings)

  • nil only matches the empty list
  • p1::p2 matches non-empty lists v1::v2 for

which p1 matches v1 and p2 matches v2 (combines the bindings) with values

no ambiguity, because of variable constraint no ambiguity, because of variable constraint

slide-20
SLIDE 20

utility

  • When a value of a given type is expected,

code can use patterns specific to that type integers… booleans… 3-tuples… lists… 0, 42, …, x, x:int… true, false, x, x:bool… (x, y, z), (0, true, _), … nil, x::L, [x, y, z], … (x:int, L:int list) x::(y::L)

slide-21
SLIDE 21

syntax

d ::= val p : t = e | fun f (p:t1):t2 = e | fun f (p1 : t) : t’= e1 | f p2 = e2 e ::= fn (p:t1):t2 => e2 | case e0 : t of p1 => e1 | p2 => e2

  • ptional : type annotations

fun, fn and case syntax allows k clauses declarations expressions using patterns

(all clauses must have the same type)

et cetera et cetera

slide-22
SLIDE 22

functions using patterns

fun f p1 = e1 | … | f pk = ek fn p1 => e1 | … | pk => ek

tries matching p1 to v, then p2,…, pk until the first match

f v

slide-23
SLIDE 23

functions using patterns

fun len [ ] = 0 | len (_::L) = 1 + len L fun f p1 = e1 | … | f pk = ek fn p1 => e1 | … | pk => ek

tries matching p1 to v, then p2,…, pk until the first match

f v

slide-24
SLIDE 24

functions using patterns

fun len [ ] = 0 | len (_::L) = 1 + len L len [3]

[3] doesn’t match pattern [ ] [3] matches pattern _::L, binding L to [ ]

= 1 + len [ ] = 1 + 0 fun f p1 = e1 | … | f pk = ek fn p1 => e1 | … | pk => ek

tries matching p1 to v, then p2,…, pk until the first match

f v

slide-25
SLIDE 25

examples

fun fact 0 = 1 | fact 1 = 1 | fact n = n * fact (n-1) fun length [ ] = 0 | length (_::L) = 1 + length L fn [ ] => true | _ => false

length : ’a list -> int

fact : int -> int

: ’a list -> bool

val x::L = [1,2,3]

binds x to 1, L to [2,3]

using patterns

slide-26
SLIDE 26

rules of thumb

  • Pay attention to clause order
  • Use exhaustive patterns
  • Avoid overlapping patterns (unless it’s safe)
  • Can use _ when the binding is irrelevant

fun f(p1:t):t’ = e1 | f(p2) = e2 | f(p3) = e3 case e:t of p1 => e1 | p2 => e2 | p3 => e3

Tries p1, then p2, then p3 Every value of type t matches at least one of p1, p2, p3 Every value of type t matches at most one of p1, p2, p3 Or, if v matches pi and pj make sure ei and ej will be equal First match “wins” Sometimes it’s convenient to use _ in the final clause

slide-27
SLIDE 27

Constant patterns can only be used to match values

  • f an equality type

fun f(0) = 1 | f(1) = 1 | f(n) = f(n-1) + f(n-2) case e of true => e1 | false => e2

int bool

slide-28
SLIDE 28

Constant patterns can only be used to match values

  • f an equality type

fun f(0) = 1 | f(1) = 1 | f(n) = f(n-1) + f(n-2) case e of true => e1 | false => e2 if e then e1 else e2

int bool

slide-29
SLIDE 29

Using patterns

fun divmod (x:int, y:int): int*int = (x div y, x mod y) divmod : int * int -> int * int fun check (m:int, n:int): bool = let val (q, r) = divmod (m, n) in (q * n + r = m) end

slide-30
SLIDE 30

Using patterns

fun divmod (x:int, y:int): int*int = (x div y, x mod y) What does this function do? divmod : int * int -> int * int fun check (m:int, n:int): bool = let val (q, r) = divmod (m, n) in (q * n + r = m) end

slide-31
SLIDE 31

decimal : int -> int list

fun decimal (n:int) : int list = if n < 10 then [n] else (n mod 10) :: decimal (n div 10)

slide-32
SLIDE 32

decimal : int -> int list

fun decimal (n:int) : int list = if n < 10 then [n] else (n mod 10) :: decimal (n div 10) What does this function do?

slide-33
SLIDE 33

decimal : int -> int list

decimal 42 = [2,4] decimal 0 = [0] fun decimal (n:int) : int list = if n < 10 then [n] else (n mod 10) :: decimal (n div 10) What does this function do?

slide-34
SLIDE 34

eval : int list -> int

This definition uses list patterns

  • [ ] matches (only) the empty list
  • d::L matches a non-empty list,

binds d to head of the list, L to its tail fun eval ([ ]:int list) : int = 0 | eval (d::L) = d + 10 * (eval L) eval [2,4] ⟹* 2 + 10 * (eval [4]) ⟹* 42

slide-35
SLIDE 35

eval : int list -> int

This definition uses list patterns

  • [ ] matches (only) the empty list
  • d::L matches a non-empty list,

binds d to head of the list, L to its tail fun eval ([ ]:int list) : int = 0 | eval (d::L) = d + 10 * (eval L) eval [2,4] ⟹* 2 + 10 * (eval [4]) ⟹* 42 What does this function do?

slide-36
SLIDE 36

log : int -> int

fun log (x:int) : int = if x = 1 then 0 else 1 + log (x div 2) log 3 = ???

slide-37
SLIDE 37

log : int -> int

  • Q: How can we describe this function?
  • A: Specify its applicative behavior…

fun log (x:int) : int = if x = 1 then 0 else 1 + log (x div 2) log 3 = ???

slide-38
SLIDE 38

log : int -> int

  • Q: How can we describe this function?
  • A: Specify its applicative behavior…

fun log (x:int) : int = if x = 1 then 0 else 1 + log (x div 2)

  • For what argument values does it terminate?

log 3 = ???

slide-39
SLIDE 39

log : int -> int

  • Q: How can we describe this function?
  • A: Specify its applicative behavior…

fun log (x:int) : int = if x = 1 then 0 else 1 + log (x div 2)

  • For what argument values does it terminate?
  • How does the output relate to the input?

log 3 = ???

slide-40
SLIDE 40

Specifications

  • Type

(showing argument type and result type)

  • Assumption

(about argument value)

  • Guarantee

(about result value, when assumption holds) For each function definition we specify:

slide-41
SLIDE 41

Format

fun log (x:int) : int = if x=1 then 0 else 1 + log (x div 2) (* TYPE log : int -> int *) (* REQUIRES … x … *) (* ENSURES … log x …. *) type assumption guarantee

Any ideas?

For all values x : int satisfying the assumption, log x : int and its value satisfies the guarantee

slide-42
SLIDE 42

log spec

fun log (x:int) : int = if x=1 then 0 else 1 + log (x div 2) (* TYPE log : int -> int *) (* REQUIRES x > 0 *) (* ENSURES log x = the integer k ≥ 0 *) (* such that 2k ≤ x < 2k+1 *)

slide-43
SLIDE 43

log spec

fun log (x:int) : int = if x=1 then 0 else 1 + log (x div 2) (* TYPE log : int -> int *) (* REQUIRES x > 0 *) (* ENSURES log x = the integer k ≥ 0 *) (* such that 2k ≤ x < 2k+1 *)

For all integers x such that x>0, the value of log x is an integer k such that 2k ≤ x < 2k+1

slide-44
SLIDE 44

notes

  • Can use ⟹* or = in specs
  • Use math and logic accurately!
  • A function can have several specs…

different assumptions may lead to different guarantee

slide-45
SLIDE 45

another log spec

fun log (x:int) : int = if x=1 then 0 else 1 + log (x div 2) (* log : int -> int *) (* REQUIRES x is a power of 2 *) (* ENSURES log x = the integer k *) (* such that 2k = x *)

slide-46
SLIDE 46

another log spec

fun log (x:int) : int = if x=1 then 0 else 1 + log (x div 2) (* log : int -> int *) (* REQUIRES x is a power of 2 *) (* ENSURES log x = the integer k *) (* such that 2k = x *) (a weaker spec … why?)

slide-47
SLIDE 47

another log spec

fun log (x:int) : int = if x=1 then 0 else 1 + log (x div 2) (* log : int -> int *) (* REQUIRES x is a power of 2 *) (* ENSURES log x = the integer k *) (* such that 2k = x *) (a weaker spec … why?) (it’s actually implied by the previous spec)

slide-48
SLIDE 48

decimal spec

TYPE decimal : int -> int list REQUIRES n ≥ 0 ENSURES decimal n = the decimal digit list for n fun decimal (n:int) : int list = if n<10 then [n] else (n mod 10) :: decimal (n div 10) (with least significant digit first)

decimal 42 = [2,4]

slide-49
SLIDE 49

eval spec

TYPE eval : int list -> int REQUIRES R = the decimal digit list for n ENSURES eval R = n fun eval ([ ] : int list) : int = 0 | eval (d::L) = d + 10 * (eval L)

slide-50
SLIDE 50

connection

  • eval and decimal are designed to fit together
  • They satisfy a combined spec

TYPE decimal : int -> int list eval : int list -> int REQUIRES n ≥ 0 ENSURES eval(decimal n) = n

slide-51
SLIDE 51

connection

  • eval and decimal are designed to fit together
  • They satisfy a combined spec

TYPE decimal : int -> int list eval : int list -> int REQUIRES n ≥ 0 ENSURES eval(decimal n) = n NOTE: this spec tells us that decimal n evaluates to a value, for n ≥ 0

slide-52
SLIDE 52

Evaluation

  • Expression evaluation produces a value if it terminates
  • e ⟹k e’ e evaluates to e’ in k steps
  • e ⟹* v e evaluates to v in finitely many steps
  • Declarations produce value bindings
  • d ⟹* x1:v1, ..., xk:vk
  • Matching a pattern to a value

either succeeds with bindings, or fails

  • match(p, v) ⟹* x1:v1, ..., xk:vk | fail

TYPE SAFE

slide-53
SLIDE 53

Substitution

For bindings x1:v1, ..., xk:vk and expression e we write [ x1:v1, ..., xk:vk ] e for the expression obtained by substituting v1 for x1, ..., vk for xk in e [ x:2 ] (x + x) is 2 + 2 [ x:2 ] (fn y => x + y) is fn y => 2 + y

(substitute for free occurrences, only)

[ x:2 ] (fn x => x + x) fn x => x + x is

slide-54
SLIDE 54

rules

  • For each syntactic construct we give

evaluation rules for ⟹

  • showing order-of-evaluation
  • We derive evaluation laws for ⟹
  • how expressions evaluate
  • what is the value, if it terminates
  • We can also count number of steps ⟹

(n) *

(“one-step-to”) (“many-steps-to”) (“takes n steps to”)

(mostly for sequential evaluation)

slide-55
SLIDE 55

addition rules

e1 ⟹ e1’

e1+e2 evaluates from left-to-right

e1 + e2 ⟹ e1’ + e2 e2 ⟹ e2’ v1 + e2 ⟹ v1 + e2’ v1 + v2 ⟹ v ei, vi : int

where v = v1 + v2

if e1 steps to e1’, then e1+e2 steps to e1’+e2 v1+v2 steps to the numeral for v1+v2

slide-56
SLIDE 56

addition law

If e1 ⟹* v1 and e2 ⟹* v2 e1 + e2 ⟹* v then and v = v1 + v2 (follows from the rules) e1 + e2 ⟹* v1 + e2 ⟹* v1 + v2 ⟹ v

slide-57
SLIDE 57

addition law

If e1 ⟹* v1 and e2 ⟹* v2 e1 + e2 ⟹* v then and v = v1 + v2 (2+2) + (3+3) ⟹ 4 + (3+3)

⟹ 4 + 6 ⟹ 10

(follows from the rules) e1 + e2 ⟹* v1 + e2 ⟹* v1 + v2 ⟹ v

slide-58
SLIDE 58

addition law

If e1 ⟹* v1 and e2 ⟹* v2 e1 + e2 ⟹* v then and v = v1 + v2 (2+2) + (3+3) ⟹ 4 + (3+3)

⟹ 4 + 6 ⟹ 10

(2+2) + (3+3) ⟹* 10 (follows from the rules) e1 + e2 ⟹* v1 + e2 ⟹* v1 + v2 ⟹ v

slide-59
SLIDE 59

addition law

If e1 ⟹* v1 and e2 ⟹* v2 e1 + e2 ⟹* v then and v = v1 + v2 (2+2) + (3+3) ⟹ 4 + (3+3)

⟹ 4 + 6 ⟹ 10

(2+2) + (3+3) ⟹* 10 (2+2) + (3+3) ⟹(3) 10 (follows from the rules) e1 + e2 ⟹* v1 + e2 ⟹* v1 + v2 ⟹ v

slide-60
SLIDE 60

addition law

If e1 + e2 ⟹* v there must be v1 : int and v2 : int such that and v = v1 + v2 (also follows from the rules) e1 ⟹* v1 and e2 ⟹* v2 e1 + e2 ⟹* v1 + e2 ⟹* v1 + v2 ⟹ v and the evaluation looks like (this shows the order of evaluation clearly!)

slide-61
SLIDE 61

application rules

“a function always evaluates its argument”

e1 ⟹ e1’ e1 e2 ⟹ e1’ e2 e2 ⟹ e2’ (fn x => e) e2 ⟹ (fn x => e) e2’ (fn x => e) v ⟹ [ x:v ] e

(this rule only applicable when function and argument have been evaluated to values) (call-by-value)

e1 e2 evaluates e1 to a function, evaluates e2 to a value, substitutes the value into the function body, then evaluates the body

slide-62
SLIDE 62

application law

If e1 ⟹* (fn x => e) and e2 ⟹* v then e1 e2 ⟹* [x:v]e (follows from the rules)

slide-63
SLIDE 63

application law

If e1 ⟹* (fn x => e) and e2 ⟹* v then e1 e2 ⟹* [x:v]e (follows from the rules)

this expression may need further evaluation

slide-64
SLIDE 64

application law

If e1 e2 ⟹* v there must be values (fn x => e) : t1->t2 and v2 : t1 such that e1 ⟹* (fn x => e) and e2 ⟹* v2 and e1 e2 ⟹* (fn x => e) e2 ⟹* (fn x => e) v2 ⟹ [x:v2]e ⟹* v (also follows from the rules)

slide-65
SLIDE 65

More rules

  • div and mod evaluate from left to right
  • List expressions

[e1,…,en], e1::e2, and e1@e2 all evaluate from left to right

  • Tuple expressions (e1,…,en)

can be evaluated from left to right,

  • r (as we’ll see later) in parallel.
slide-66
SLIDE 66

More rules

  • div and mod evaluate from left to right
  • List expressions

[e1,…,en], e1::e2, and e1@e2 all evaluate from left to right

  • Tuple expressions (e1,…,en)

can be evaluated from left to right,

  • r (as we’ll see later) in parallel.
slide-67
SLIDE 67

Declaration rule

In the scope of fun f(p) = e, f ⟹ (fn p => e)

slide-68
SLIDE 68

Declaration rule

In the scope of fun f(p) = e, f ⟹ (fn p => e) fun divmod(x, y) = (x div y, x mod y)

slide-69
SLIDE 69

Declaration rule

In the scope of fun f(p) = e, f ⟹ (fn p => e) fun divmod(x, y) = (x div y, x mod y) divmod (3,2)

slide-70
SLIDE 70

Declaration rule

In the scope of fun f(p) = e, f ⟹ (fn p => e) fun divmod(x, y) = (x div y, x mod y) divmod (3,2) ⟹ (fn(x, y) => (x div y, x mod y)) (3,2)

slide-71
SLIDE 71

Declaration rule

In the scope of fun f(p) = e, f ⟹ (fn p => e) fun divmod(x, y) = (x div y, x mod y) divmod (3,2) ⟹ (fn(x, y) => (x div y, x mod y)) (3,2) ⟹ (3 div 2, 3 mod 2)

slide-72
SLIDE 72

Declaration rule

In the scope of fun f(p) = e, f ⟹ (fn p => e) fun divmod(x, y) = (x div y, x mod y) divmod (3,2) ⟹ (fn(x, y) => (x div y, x mod y)) (3,2) ⟹ (3 div 2, 3 mod 2) ⟹ (1, 3 mod 2)

slide-73
SLIDE 73

Declaration rule

In the scope of fun f(p) = e, f ⟹ (fn p => e) fun divmod(x, y) = (x div y, x mod y) divmod (3,2) ⟹ (fn(x, y) => (x div y, x mod y)) (3,2) ⟹ (3 div 2, 3 mod 2) ⟹ (1, 3 mod 2) ⟹ (1, 1)

slide-74
SLIDE 74

example

fun silly x = silly x; (fn y => 0) (silly 42) doesn’t terminate

slide-75
SLIDE 75

example

fun silly x = silly x; (fn y => 0) (silly 42) doesn’t terminate (fn y => 0) (silly 42)

slide-76
SLIDE 76

example

fun silly x = silly x; (fn y => 0) (silly 42) doesn’t terminate (fn y => 0) (silly 42) ⟹

slide-77
SLIDE 77

example

fun silly x = silly x; (fn y => 0) (silly 42) doesn’t terminate (fn y => 0) (silly 42) (fn y => 0) ((fn x => silly x) 42) ⟹

slide-78
SLIDE 78

example

fun silly x = silly x; (fn y => 0) (silly 42) doesn’t terminate (fn y => 0) (silly 42) (fn y => 0) ((fn x => silly x) 42) ⟹ ⟹

slide-79
SLIDE 79

example

fun silly x = silly x; (fn y => 0) (silly 42) doesn’t terminate (fn y => 0) (silly 42) (fn y => 0) ((fn x => silly x) 42) (fn y => 0) (silly 42) ⟹ ⟹

slide-80
SLIDE 80

example

fun silly x = silly x; (fn y => 0) (silly 42) doesn’t terminate (fn y => 0) (silly 42) (fn y => 0) ((fn x => silly x) 42) (fn y => 0) (silly 42) ⟹ ⟹

ad infinitum

slide-81
SLIDE 81

example

fun silly x = silly x; (fn y => 0) (silly 42) doesn’t terminate (fn y => 0) (silly 42) (fn y => 0) ((fn x => silly x) 42) (fn y => 0) (silly 42) ⟹ ⟹

ad infinitum

functions evaluate their argument

slide-82
SLIDE 82

Comments

  • Using ⟹ we can talk about evaluation order

and the number of steps

  • But we may want to ignore such details...

For all expressions e1, e2 : int and all values v:int, if e1 + e2 ⟹* v then e2 + e1 ⟹* v Here we only care about the value e1 + e2 = e2 + e1 For all expressions e1, e2 : int,

the same, more succinctly

slide-83
SLIDE 83

Equivalence

  • For each type t there is a mathematical notion of

equivalence (or equality) =t for values of type t

(it’s all about the value…)

  • Expressions of type t are equivalent iff

they evaluate to equivalent values, or both diverge

slide-84
SLIDE 84

Equivalence

  • For each type t there is a mathematical notion of

equivalence (or equality) =t for values of type t v1 =int v2 ⇔ v1 = v2

(as expected!) (it’s all about the value…)

  • Expressions of type t are equivalent iff

they evaluate to equivalent values, or both diverge

slide-85
SLIDE 85

Equivalence

  • For each type t there is a mathematical notion of

equivalence (or equality) =t for values of type t

(it’s all about the value…)

  • Expressions of type t are equivalent iff

they evaluate to equivalent values, or both diverge

slide-86
SLIDE 86

Equivalence

  • For each type t there is a mathematical notion of

equivalence (or equality) =t for values of type t f1 =int->int f2 ⇔

∀v1,v2:int. (v1 =int v2 implies f1 v1 =int f2 v2)

(it’s all about the value…)

  • Expressions of type t are equivalent iff

they evaluate to equivalent values, or both diverge

slide-87
SLIDE 87

Equivalence

  • For each type t there is a mathematical notion of

equivalence (or equality) =t for values of type t f1 =int->int f2 ⇔

∀v1,v2:int. (v1 =int v2 implies f1 v1 =int f2 v2)

(equivalent functions map equal arguments to equal results) (it’s all about the value…)

  • Expressions of type t are equivalent iff

they evaluate to equivalent values, or both diverge

slide-88
SLIDE 88

Equations

  • Arithmetic
  • Boolean

e1 + e2 =int e2 + e1 e1 + (e2 + e3) =int (e1 + e2) + e3 e + 0 =int e if true then e1 else e2 =t e1 if false then e1 else e2 =t e2 21 + 21 =int 42 (0 < 1) =bool true

slide-89
SLIDE 89

Equations

  • Application
  • Declaration

(fn x => e) v = [x:v]e In the scope of f =t1->t2 (fn x => e) the equation fun f(x:t1):t2 = e holds

  • nly when

the argument is a value

slide-90
SLIDE 90

Equations

  • Application
  • Declaration

(fn x => e) v = [x:v]e In the scope of f =t1->t2 (fn x => e) the equation fun f(x:t1):t2 = e holds

slide-91
SLIDE 91

Equations

  • Application
  • Declaration

(fn x => e) v = [x:v]e In the scope of f =t1->t2 (fn x => e) the equation fun f(x:t1):t2 = e holds let val x = v in e end = [x:v]e

slide-92
SLIDE 92

Compositionality

  • Substitution of equals
  • If e1 = e2 and e1’ = e2’

then (e1 e1’) = (e2 e2’)

  • If e1 = e2 and e1’ = e2’

then (e1 + e1’) = (e2 + e2’) and so on

slide-93
SLIDE 93

Key facts

evaluation is consistent with equivalence

slide-94
SLIDE 94

Key facts

  • e : t and e ⟹* v implies v : t and e =t v
  • e ⟹* v implies (fn x => E) e = [x:v] E

evaluation is consistent with equivalence

slide-95
SLIDE 95

Key facts

  • e : t and e ⟹* v implies v : t and e =t v
  • e ⟹* v implies (fn x => E) e = [x:v] E

evaluation is consistent with equivalence

  • f 3;
  • val it = 0 : int

f 3 ⟹* 0 f 3 =int 0

Standard ML of New Jersey

fun f(x:int) = 0; …

slide-96
SLIDE 96

Summary

  • Patterns allow elegant function design

patterns match subset of values function tries its clauses in order so be careful about clause order

  • Specifications can serve as clear documentation

TYPE + REQUIRES and ENSURES equality and evaluation

slide-97
SLIDE 97
  • Testing may be helpful,

but usually cannot cover all cases

  • How to prove that a function

meets its specification...

  • Proof methods use induction

Coming soon

slide-98
SLIDE 98
  • Testing may be helpful,

but usually cannot cover all cases

  • How to prove that a function

meets its specification...

  • Proof methods use induction

Coming soon