Data Scientist, Publicis Media

sandy.vanderbleek@publicismedia.com

hiring data engineers/data scientists/web developers 🙏

twitter.com/haskellandchill

- Establish notation
- Define problem
- Identify error and correct result
- Analyze error and correct algorithm

(a b c)

p'

p''

p?

{p => q, r => s}

{}[p => q]

{}[p]

{}/p

a \in b

pattern

first

rest

check single

substitution

update

lookup

apply

element

(a) \in {(a) => (b)} == true

(a) \in (a b) == true

(a b c)' == (a)

(a b c)'' == (b c)

(a)? == true

{a => b}/(a) == (b)

(a) \in {} == false

(a) \in (b c) == false

(a)' == (a)

(a)'' == ()

()' == ()

()'' == ()

(a b)? == false

()? == false

{a => b}/(c) == (c)

unify a b == s

unify a b == fail

.:. s/a == s/b

.:. ~E s | s/a == s/b

unify (a) (a) == {}

unify (a) (b) == {a => b}

unify (a a) (a) == fail

unify (a) (b b) == {a => b b}

- Typically many answers possible, most general unifier can generate them
- Wikipedia page is a good overview

Syntactic Unification

unify (x y) (y x) == fail

Present in algorithm in several popular textbooks including Norvig's (twice) and SICP

Caused by failing to dereference bindings

unify (x y) (y x) == {(x) => (y)}

{x => y}/(x y) == (y y)

{x => y}/(y x) == (y y)

unify p q s =

p == q -> s

p? -> variable p q s

q? -> variable q p s

_ -> unify p'' q'' (unify p' q' s)

variable a p s =

a \in s -> unify s[a] p s

a \in s[p] -> fail

_ -> s[a => p]

unify p q s =

p == q -> s

p? -> variable p q s

q? -> variable q p s

_ -> unify p'' q'' (unify p' q' s)

variable a p s =

a \in s -> unify s[a] p s

** p \in s -> unify a s[p] s**

a \in s[p] -> fail

_ -> s[a => p]

unify (y) (x) (unify (x) (y) {})

**by** _ -> unify p'' q'' (unify p' q' s)

**as** unify (y) (x) (unify (y) (x))

unify (y) (x) {x => y}

**by** p? -> variable p q s

**as** (y)? -> variable (y) (x) {}

**by** _ -> s[a => p]

**as** _ -> {}[y => x]

fail

**by** a \in s[p] -> fail

**as** (y) \in {x => y}[x] -> fail

Error 😱

...

unify (y) (y) {x => y}

**by** p \in s -> unify a s[p] s

**as **(x) \in {x => y} -> unify (y) {x => y}[x] {x => y}

{(x) => (y)}

**by** p == q -> s

**as** (y) == (y) -> {x => y}

Correct 😇

Functional Programming advocates have claimed that assignment (to a variable or data structure) is dangerous because it violates referential transparency. Curiously, this note shows that for unification, the

functional approachis error-prone, while theprocedural, state-modification approachtends to lead to a correct solution.

🔥

They all failed to either

test the resulting codesufficiently or attempt even an informalproof of correctness. Either approach could have uncovered the bug that has remained hidden until now.

✅

A proof of correctness for unification in Athena

in my talk "Athena: An Educational Language For Proofs In Computer Science"

to be delivered in Boulder June 4th 2018 and put online... someday 🙃

http://proofcentral.org/athena/

Fundamental Proof Methods in Computer Science