# Correcting a Widespread Error in Unification Algorithms

## Sandy Vanderbleek

Data Scientist, Publicis Media

sandy.vanderbleek@publicismedia.com

hiring data engineers/data scientists/web developers 🙏

## Approach

• 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

## Examples

(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)

## Problem

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

Syntactic Unification

## Error

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

## Correct

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

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

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

## Wrong

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]

## Correct

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]

## Evaluation

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 😱

## Evaluation

...

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 😇

## Norving's Hot Take

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 approach is error-prone, while the procedural, state-modification approach tends to lead to a correct solution.

🔥

They all failed to either test the resulting code sufficiently or attempt even an informal proof of correctness. Either approach could have uncovered the bug that has remained hidden until now.

## Future Work

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