Download presentation
Presentation is loading. Please wait.
Published byEzra Hudson Modified over 9 years ago
1
Induction & Recursion Discrete Mathematics and Its Applications Baojian Hua bjhua@ustc.edu.cn
2
Our Goal How to write data types (math.) via inductive definitions? How to turn inductive definitions into data structures? How to write algorithms operated on these data structures? How to argue the correctness of the algorithms?
3
Dead-simple Example: nat // Data types: 1. A zero, or 2. a number follow another nat. // Rewrite into inductive definition form: nat -> Zero -> Succ nat // Q: how to turn this into data structures?
4
Tagged Union in C // Rewrite into inductive definition form: nat -> Zero -> Succ nat typedef natStruct *nat; struct natStruct { enum natKind {Zero, Succ} kind; union { nat n; } u; }; u kind
5
Interface #ifndef NAT_H #define NAT_H typedef natStruct *nat; struct natStruct { enum natKind {Zero, Succ} kind; union { nat n; } u; };
6
Interface Continued nat newNatZero (); nat newNatSucc (nat n); nat natAdd (nat n1, nat n2); int natToInt (nat n); #endif
7
Generate nat nat newNatZero () { nat t = (nat)malloc (sizeof (*t)); t->kind = Zero; return t; } nat newNatSucc (nat n) { nat t = (nat)malloc (sizeof (*t)); t->kind = Succ; t->u.n = n; return t; } u kind nat -> Zero -> Succ nat
8
Example: 3 3: Succ(Succ(Succ(Zero))); three = newNatSucc( newNatSucc( newNatZero()))); u kind u u u three
9
Example: 3 3: Succ(Succ(Succ(Zero))); three = newNatSucc( newNatSucc( newNatZero()))); u Zero u Succ u u three
10
Addition n1 ⊕ n2 = { n2, if n1==Zero; { Succ (m ⊕ n2), if n1==Succ(m). nat natAdd (nat n1, nat n2) { switch (n1->kind) { case Zero: return n2; case Succ: return newNatSucc (natAdd (n1->u.n, n2)); default: error (…); } return NULL; } u kind
11
toInt toInt(n) = { 0, if n==Zero; { 1+toInt(m), if n1==Succ(m). int natToInt (nat n) { switch (n->kind) { case Zero: return 0; case Succ: return 1+(natToInt(n->u.n)); default: error (…); } return -1; } u kind
12
Linked List // Data types: 1. An empty list, or 2. a node, followed by another list. // Rewrite into inductive definition form: list -> Empty -> Cons T, list // Q: how to turn this into data structures?
13
Tagged Union in C // Rewrite into inductive definition form: list -> Empty -> Cons (T, list) typedef listStruct *list; struct listStruct { enum listKind {Empty, Cons} kind; union { struct { void *data; list next; } node; } u; }; u kind
14
Interface #ifndef LIST_H #define LIST_H typedef listStruct *list; struct listStruct { enum listKind {Empty, Cons} kind; union { struct { void *data; list next; } node; } u; };
15
Interface Continued list newListEmpty (); list newListCons (void *data, list next); int length (list l); list insertHead (list l, void *data); list insertTail (list l, void *data); #endif
16
Generate a List list newListEmpty () { list t = (list)malloc (sizeof (*t)); t->kind = Empty; return t; } list newListCons (void *data, list l) { list t = (list)malloc (sizeof (*t)); t->kind = Cons; t->u.node.data = data; t->u.node.next = l; return t; } u kind list -> Empty -> Cons (T, list)
17
Length length(l) = { 0, if l==Empty; { 1+length(m), if l==Cons (T, m) int length (list l) { switch (l->kind) { case Empty: return 0; case Cons: return 1 + length(l->u.node.next); default: error (…); } return -1; } u kind
18
Insert at Head f(d, l) = Cons (d, l) list insertHead (void *d, list l) { return newListCons (d, l); } u kind
19
Insert at Tail f(d, l) = { Cons (d, l), if l==Empty; { Cons (x, f(d, m)), if l==Cons(x, m). list insertTail (void *d, list l) { switch (l->kind) { case Empty: return newListCons (d, l); case Cons: return newListCons (l->u.node.data, insertTail (d, l->u.node.next)); default: error (…); } return NULL; } u kind How can you argue this is correct?
20
How does it Work? u Empty 3 Cons 6 4 list insert 9 at tail u Empty 9 Cons 3 6 newList 4 Cons
21
Persistent Data Structures Data structures never change once created you may want to compare the list here with the ones we discussed in Lab #1 Good for many purpose reason the correctness of the code local debugging important in emerging fields such as concurrent programming or multi-core
22
Functional Programming Stemming from mathematics Church and Turing, etc. Programming (and the resulting code) just behaves like writing mathematical functions persistent data structures h recursive functions An important programming idioms I personally love it more than procedural, OO, generic, etc. Stepping into industry Such as F# from M … S …
23
Summary Inductive Def ’ == Persistent DS Deduction == Recursion Math Proof == Program Correctness
24
Local Class Hierarchy abstract class List {} class ListEmpty extends List {} class ListCons extends List { X data; List next; ListCons (X data, List next) {…} }
25
Ugly Cast class Match { public int size (List l) { if (l instanceof ListEmpty ) return 0; else if (l instanceof ListCons ) …; else …; } // Or the visitor pattern
26
In C++ template class List { public: virtual void foo()=0; }; template class ListEmpty: public List { public: void foo (){}; };
27
In C++ template class ListCons: public List { public: X data; List next; ListCons(X adata, List anext) :data(adata), next(anext) {}; void foo () {}; }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.