Well Founded Recursion
Well Founded Recursion
Eric Mertens
Galois Inc
1 / 24
This Talk
Introduction to Agda Implementing Quicksort Dening Relations Building a better recursion Back to Implementing Quicksort
2 / 24
Introduction to Agda
Agda is a dependently typed functional programming language. Agda is a proof assistant based on intuitionistic type theory. Agda has similar syntax to Haskell.
3 / 24
Introduction to Agda
Programs as Proofs
4 / 24
Introduction to Agda
Programs as Proofs
Types are propositions. Inhabited types are true propositions. data : Set where unit :
4 / 24
Introduction to Agda
Programs as Proofs
Types are propositions. Inhabited types are true propositions. data : Set where unit :
4 / 24
Introduction to Agda
Programs as Proofs
Types are propositions. Inhabited types are true propositions. data : Set where unit :
Uninhabited types are false propositions. data : Set where Implementations are proofs.
4 / 24
Introduction to Agda
5 / 24
Introduction to Agda
5 / 24
Introduction to Agda
5 / 24
Introduction to Agda
5 / 24
Introduction to Agda
Agda uses a termination checking algorithm when loading source les. Structural recursion is supported by the termination checker. Structural recursion allows us to make recursive calls on a structrually smaller argument.
6 / 24
Introduction to Agda
Agda uses a termination checking algorithm when loading source les. Structural recursion is supported by the termination checker. Structural recursion allows us to make recursive calls on a structrually smaller argument. Example foldl : {a b : Set} List a (b a b) b b foldl [ ] f z = z foldl (x :: xs) f z = foldl xs f (f z x)
6 / 24
Introduction to Agda
Agda uses a termination checking algorithm when loading source les. Structural recursion is supported by the termination checker. Structural recursion allows us to make recursive calls on a structrually smaller argument. Example foldl : {a b : Set} List a (b a b) b b foldl [ ] f z = z foldl (x :: xs) f z = foldl xs f (f z x) But not all recursive functions are structurally recursive...
6 / 24
Introduction to Agda
7 / 24
Introduction to Agda
Agda can nd termination orders across mutually recursive functions. Agda can nd lexicographic termination orders.
7 / 24
Introduction to Agda
Agda can nd termination orders across mutually recursive functions. Agda can nd lexicographic termination orders. Example ack : N N N ack 0 n = 1 ack (suc m) 0 = ack m 1 ack (suc m) (suc n) = ack m (ack (suc m) n)
7 / 24
Introduction to Agda
Agda can nd termination orders across mutually recursive functions. Agda can nd lexicographic termination orders. Example ack : N N N ack 0 n = 1 ack (suc m) 0 = ack m 1 ack (suc m) (suc n) = ack m (ack (suc m) n) Is this enough?
7 / 24
Implementing Quicksort
Introduction to Agda Implementing Quicksort Dening Relations Building a better recursion Back to Implementing Quicksort
8 / 24
Implementing Quicksort
Quicksort in Haskell
Nave functional-programming quicksort quicksort :: (a a Bool) List a List a quicksort p [ ] = [ ] quicksort p (x : xs) = case partition (p x) xs of (small, big) small + [x] + big + + where small = quicksort p small big = quicksort p big
9 / 24
Implementing Quicksort
Quicksort in Haskell
Nave functional-programming quicksort quicksort :: (a a Bool) List a List a quicksort p [ ] = [ ] quicksort p (x : xs) = case partition (p x) xs of (small, big) small + [x] + big + + where small = quicksort p small big = quicksort p big Why does this terminate (on nite lists)?
9 / 24
Implementing Quicksort
Quicksort in Agda
Nave functional-programming quicksort in Agda quicksort : {A : Set} (A A Bool) List A List A quicksort p [ ] = [ ] quicksort p (x :: xs) with partition (p x) xs ... | small, big = small + [x] + big + + where small = quicksort p small big = quicksort p big
10 / 24
Implementing Quicksort
Quicksort in Agda
Nave functional-programming quicksort in Agda quicksort : {A : Set} (A A Bool) List A List A quicksort p [ ] = [ ] quicksort p (x :: xs) with partition (p x) xs ... | small, big = small + [x] + big + + where small = quicksort p small big = quicksort p big The termination checker fails on this function.
10 / 24
Implementing Quicksort
Well-founded Recursion
Recursive calls are on "smaller" arguments. No intinte descending chains of recursive calls; we always reach a smallest element. We can capture this relation between elements in Agda.
11 / 24
Implementing Quicksort
Well-founded Relations
12 / 24
Implementing Quicksort
Well-founded Relations
A relation is well-founded if it contains no innite descending chains. Example: "Less than" on natural numbers (<).
12 / 24
Implementing Quicksort
Well-founded Relations
A relation is well-founded if it contains no innite descending chains. Example: "Less than" on natural numbers (<). 0 < 1 < 2 < 5 < 8 < 10
12 / 24
Implementing Quicksort
Well-founded Relations
A relation is well-founded if it contains no innite descending chains. Example: "Less than" on natural numbers (<). 0 < 1 < 2 < 5 < 8 < 10 Example: "Proper subset" on sets ().
12 / 24
Implementing Quicksort
Well-founded Relations
A relation is well-founded if it contains no innite descending chains. Example: "Less than" on natural numbers (<). 0 < 1 < 2 < 5 < 8 < 10 Example: "Proper subset" on sets (). {} {2} {1,2,5} {1,2,3,4,5}
12 / 24
Implementing Quicksort
Well-founded Relations
A relation is well-founded if it contains no innite descending chains. Example: "Less than" on natural numbers (<). 0 < 1 < 2 < 5 < 8 < 10 Example: "Proper subset" on sets (). {} {2} {1,2,5} {1,2,3,4,5} False example: "Less than or equal to" on natural numbers ( ).
12 / 24
Implementing Quicksort
Well-founded Relations
A relation is well-founded if it contains no innite descending chains. Example: "Less than" on natural numbers (<). 0 < 1 < 2 < 5 < 8 < 10 Example: "Proper subset" on sets (). {} {2} {1,2,5} {1,2,3,4,5} False example: "Less than or equal to" on natural numbers ( ). 42 42 42
12 / 24
Dening Relations
Introduction to Agda Implementing Quicksort Dening Relations Building a better recursion Back to Implementing Quicksort
13 / 24
Dening Relations
Relations in Agda
Characterizing relations: Rel : Set Set1 Rel A = A A Set
14 / 24
Dening Relations
Relations in Agda
Characterizing relations: Rel : Set Set1 Rel A = A A Set Dening a new relation (inductively dened type family): data _<_ (m : N) : N Set where <-base : m < suc m <-step : {n : N} m < n m < suc n
14 / 24
Dening Relations
Relations in Agda
Characterizing relations: Rel : Set Set1 Rel A = A A Set Dening a new relation (inductively dened type family): data _<_ (m : N) : N Set where <-base : m < suc m <-step : {n : N} m < n m < suc n Dening a negation: _ _ : Rel N a b = a<b
Eric Mertens (Galois Inc) Introducing Well-founded Recursion Tech Talk: June 15, 2010 14 / 24
Dening Relations
15 / 24
Dening Relations
15 / 24
Dening Relations
15 / 24
Dening Relations
15 / 24
Dening Relations
15 / 24
Dening Relations
15 / 24
Dening Relations
15 / 24
Introduction to Agda Implementing Quicksort Dening Relations Building a better recursion Back to Implementing Quicksort
16 / 24
Accessibility
We need a way to encode what it means for a relation to be well-founded.
17 / 24
Accessibility
We need a way to encode what it means for a relation to be well-founded. An element, x, of a set, A, is "accessible" with respect to a relation,<, i all of the elements, y, are less-than x are accessible.
module WF {A : Set} (_<_ : Rel A) where data Acc (x : A) : Set where acc : ( y y < x Acc y) Acc x
17 / 24
Accessibility
We need a way to encode what it means for a relation to be well-founded. An element, x, of a set, A, is "accessible" with respect to a relation,<, i all of the elements, y, are less-than x are accessible. A relation is well-founded i all elements in the set are accessible. module WF {A : Set} (_<_ : Rel A) where data Acc (x : A) : Set where acc : ( y y < x Acc y) Acc x Well-founded : Set Well-founded = x Acc x
17 / 24
We implement this with structural recursion. <-N-wf : Well-founded _<_ <-N-wf x = acc (aux x) where aux : x y y < x Acc _<_ y aux . (suc y) y <-base = <-N-wf y aux . (suc x) y (<-step {x} y<x) = aux x y y<x
18 / 24
We implement this with structural recursion. <-N-wf : Well-founded _<_ <-N-wf x = acc (aux x) where aux : x y y < x Acc _<_ y aux . (suc y) y <-base = <-N-wf y aux . (suc x) y (<-step {x} y<x) = aux x y y<x This is rather complicated; lets reuse it!
18 / 24
19 / 24
19 / 24
19 / 24
19 / 24
19 / 24
Shorter lists
Lets instantiate this module for our quicksort case. _<_ : Rel N length : List A N _ _ : Rel (List A) module <-on-length-Well-founded {A} where open Inverse-image-Well-founded {List A} _<_ length public wf : Well-founded _ _ wf = ii-wf <-N-wf
20 / 24
Introduction to Agda Implementing Quicksort Dening Relations Building a better recursion Back to Implementing Quicksort
21 / 24
22 / 24
List A
The subrelation of a well-founded relation is well-founded. The transitive closure of a well-founded relation is well-founded. The lexicographic product of a well-founded relation is well-founded.
24 / 24