86 @{const Suc} in the case of @{typ nat} and @{const "op #"} in the case |
86 @{const Suc} in the case of @{typ nat} and @{const "op #"} in the case |
87 of lists. A recursive function is accepted if \isacommand{fun} can |
87 of lists. A recursive function is accepted if \isacommand{fun} can |
88 show that the size of one fixed argument becomes smaller with each |
88 show that the size of one fixed argument becomes smaller with each |
89 recursive call. |
89 recursive call. |
90 |
90 |
91 More generally, @{text fun} allows any \emph{lexicographic |
91 More generally, \isacommand{fun} allows any \emph{lexicographic |
92 combination} of size measures in case there are multiple |
92 combination} of size measures in case there are multiple |
93 arguments. For example the following version of \rmindex{Ackermann's |
93 arguments. For example, the following version of \rmindex{Ackermann's |
94 function} is accepted: *} |
94 function} is accepted: *} |
95 |
95 |
96 fun ack2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where |
96 fun ack2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where |
97 "ack2 n 0 = Suc n" | |
97 "ack2 n 0 = Suc n" | |
98 "ack2 0 (Suc m) = ack2 (Suc 0) m" | |
98 "ack2 0 (Suc m) = ack2 (Suc 0) m" | |
112 terminate because of automatic splitting of @{text "if"}. |
112 terminate because of automatic splitting of @{text "if"}. |
113 \index{*if expressions!splitting of} |
113 \index{*if expressions!splitting of} |
114 Let us look at an example: |
114 Let us look at an example: |
115 *} |
115 *} |
116 |
116 |
117 fun gcd :: "nat \<times> nat \<Rightarrow> nat" where |
117 fun gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat" where |
118 "gcd(m,n) = (if n=0 then m else gcd(n, m mod n))" |
118 "gcd m n = (if n=0 then m else gcd n (m mod n))" |
119 |
119 |
120 text{*\noindent |
120 text{*\noindent |
121 The second argument decreases with each recursive call. |
121 The second argument decreases with each recursive call. |
122 The termination condition |
122 The termination condition |
123 @{prop[display]"n ~= (0::nat) ==> m mod n < n"} |
123 @{prop[display]"n ~= (0::nat) ==> m mod n < n"} |
128 languages and our simplifier don't do that. Unfortunately the simplifier does |
128 languages and our simplifier don't do that. Unfortunately the simplifier does |
129 something else that leads to the same problem: it splits |
129 something else that leads to the same problem: it splits |
130 each @{text "if"}-expression unless its |
130 each @{text "if"}-expression unless its |
131 condition simplifies to @{term True} or @{term False}. For |
131 condition simplifies to @{term True} or @{term False}. For |
132 example, simplification reduces |
132 example, simplification reduces |
133 @{prop[display]"gcd(m,n) = k"} |
133 @{prop[display]"gcd m n = k"} |
134 in one step to |
134 in one step to |
135 @{prop[display]"(if n=0 then m else gcd(n, m mod n)) = k"} |
135 @{prop[display]"(if n=0 then m else gcd n (m mod n)) = k"} |
136 where the condition cannot be reduced further, and splitting leads to |
136 where the condition cannot be reduced further, and splitting leads to |
137 @{prop[display]"(n=0 --> m=k) & (n ~= 0 --> gcd(n, m mod n)=k)"} |
137 @{prop[display]"(n=0 --> m=k) & (n ~= 0 --> gcd n (m mod n)=k)"} |
138 Since the recursive call @{term"gcd(n, m mod n)"} is no longer protected by |
138 Since the recursive call @{term"gcd n (m mod n)"} is no longer protected by |
139 an @{text "if"}, it is unfolded again, which leads to an infinite chain of |
139 an @{text "if"}, it is unfolded again, which leads to an infinite chain of |
140 simplification steps. Fortunately, this problem can be avoided in many |
140 simplification steps. Fortunately, this problem can be avoided in many |
141 different ways. |
141 different ways. |
142 |
142 |
143 The most radical solution is to disable the offending theorem |
143 The most radical solution is to disable the offending theorem |
174 A final alternative is to replace the offending simplification rules by |
174 A final alternative is to replace the offending simplification rules by |
175 derived conditional ones. For @{term gcd} it means we have to prove |
175 derived conditional ones. For @{term gcd} it means we have to prove |
176 these lemmas: |
176 these lemmas: |
177 *} |
177 *} |
178 |
178 |
179 lemma [simp]: "gcd(m,0) = m" |
179 lemma [simp]: "gcd m 0 = m" |
180 apply(simp) |
180 apply(simp) |
181 done |
181 done |
182 |
182 |
183 lemma [simp]: "n \<noteq> 0 \<Longrightarrow> gcd(m,n) = gcd(n, m mod n)" |
183 lemma [simp]: "n \<noteq> 0 \<Longrightarrow> gcd m n = gcd n (m mod n)" |
184 apply(simp) |
184 apply(simp) |
185 done |
185 done |
186 |
186 |
187 text{*\noindent |
187 text{*\noindent |
188 Simplification terminates for these proofs because the condition of the @{text |
188 Simplification terminates for these proofs because the condition of the @{text |