author krauss Thu, 12 Jul 2007 12:20:39 +0200 changeset 23805 953eb3c5f793 parent 23804 5801141870b1 child 23806 d67aac3992c3
updated
--- a/doc-src/IsarAdvanced/Functions/Thy/Functions.thy	Thu Jul 12 11:43:17 2007 +0200
+++ b/doc-src/IsarAdvanced/Functions/Thy/Functions.thy	Thu Jul 12 12:20:39 2007 +0200
@@ -24,7 +24,7 @@
text {*
The syntax is rather self-explanatory: We introduce a function by
giving its name, its type and a set of defining recursive
-  equations. Note that the function is not primitive recursive.
+  equations.
*}

text {*
@@ -34,7 +34,6 @@
fundamental requirement to prevent inconsistencies\footnote{From the
\qt{definition} @{text "f(n) = f(n) + 1"} we could prove
@{text "0 = 1"} by subtracting @{text "f(n)"} on both sides.}.
-
Isabelle tries to prove termination automatically when a definition
is made. In \S\ref{termination}, we will look at cases where this
fails and see what to do then.
@@ -46,7 +45,9 @@
Like in functional programming, we can use pattern matching to
define functions. At the moment we will only consider \emph{constructor
patterns}, which only consist of datatype constructors and
-  (linear occurrences of) variables.
+  variables. Furthermore, patterns must be linear, i.e.\ all variables
+  on the left hand side of an equation must be distinct. In
+  \S\ref{genpats} we discuss more general pattern matching.

If patterns overlap, the order of the equations is taken into
account. The following function inserts a fixed element between any
@@ -70,7 +71,7 @@
text {* @{thm [display] sep.simps[no_vars]} *}

text {*
-  The equations from function definitions are automatically used in
+  \noindent The equations from function definitions are automatically used in
simplification:
*}

@@ -81,9 +82,30 @@

text {*

-  Isabelle provides customized induction rules for recursive functions.
-  See \cite[\S3.5.4]{isa-tutorial}. \fixme{Cases?}
+  Isabelle provides customized induction rules for recursive
+  functions. These rules follow the recursive structure of the
+  definition. Here is the rule @{text sep.induct} arising from the
+  above definition of @{const sep}:
+
+  @{thm [display] sep.induct}
+
+  We have a step case for list with at least two elements, and two
+  base cases for the zero- and the one-element list. Here is a simple
+  proof about @{const sep} and @{const map}
+*}

+lemma "map f (sep x ys) = sep (f x) (map f ys)"
+apply (induct x ys rule: sep.induct)
+
+txt {*
+  We get three cases, like in the definition.
+
+  @{subgoals [display]}
+*}
+
+apply auto
+done
+text {*

With the \cmd{fun} command, you can define about 80\% of the
functions that occur in practice. The rest of this tutorial explains
@@ -131,7 +153,7 @@

\begin{enumerate}
\item The \cmd{sequential} option enables the preprocessing of
-  pattern overlaps we already saw. Without this option, the equations
+  pattern overlaps which we already saw. Without this option, the equations
must already be disjoint and complete. The automatic completion only
works with constructor patterns.

@@ -152,10 +174,12 @@
section {* Termination *}

text {*\label{termination}
-  The @{text "lexicographic_order"} method can prove termination of a
+  The method @{text "lexicographic_order"} is the default method for
+  termination proofs. It can prove termination of a
certain class of functions by searching for a suitable lexicographic
combination of size measures. Of course, not all functions have such
-  a simple termination argument.
+  a simple termination argument. For them, we can specify the termination
+  relation manually.
*}

subsection {* The {\tt relation} method *}
@@ -171,23 +195,19 @@

text {*
\noindent The @{text "lexicographic_order"} method fails on this example, because none of the
-  arguments decreases in the recursive call.
-  % FIXME: simps and induct only appear after "termination"
-
-  The easiest way of doing termination proofs is to supply a wellfounded
-  relation on the argument type, and to show that the argument
-  decreases in every recursive call.
+  arguments decreases in the recursive call, with respect to the standard size ordering.
+  To prove termination manually, we must provide a custom wellfounded relation.

The termination argument for @{text "sum"} is based on the fact that
the \emph{difference} between @{text "i"} and @{text "N"} gets
smaller in every step, and that the recursion stops when @{text "i"}
-  is greater then @{text "n"}. Phrased differently, the expression
-  @{text "N + 1 - i"} decreases in every recursive call.
+  is greater than @{text "N"}. Phrased differently, the expression
+  @{text "N + 1 - i"} always decreases.

We can use this expression as a measure function suitable to prove termination.
*}

-termination sum
+termination
apply (relation "measure (\<lambda>(i,N). N + 1 - i)")

txt {*
@@ -267,19 +287,22 @@
\noindent Isabelle responds with the following error:

\begin{isabelle}
-*** Could not find lexicographic termination order:\newline
-*** \ \ \ \ 1\ \ 2  \newline
-*** a:  N   <= \newline
+*** Unfinished subgoals:\newline
+*** (a, 1, <):\newline
+*** \ 1.~@{text "\<And>x. x = 0"}\newline
+*** (a, 1, <=):\newline
+*** \ 1.~False\newline
+*** (a, 2, <):\newline
+*** \ 1.~False\newline
*** Calls:\newline
*** a) @{text "(a, x # xs) -->> (x + a, x # xs)"}\newline
*** Measures:\newline
*** 1) @{text "\<lambda>x. size (fst x)"}\newline
*** 2) @{text "\<lambda>x. size (snd x)"}\newline
-*** Unfinished subgoals:\newline
-*** @{text "\<And>a x xs."}\newline
-*** \quad @{text "(x. size (fst x)) (x + a, x # xs)"}\newline
-***  \quad @{text "\<le> (\<lambda>x. size (fst x)) (a, x # xs)"}\newline
-***  @{text "1. \<And>x. x = 0"}\newline
+*** Result matrix:\newline
+*** \ \ \ \ 1\ \ 2  \newline
+*** a:  ?   <= \newline
+*** Could not find lexicographic termination order.\newline
*** At command "fun".\newline
\end{isabelle}
*}
@@ -288,7 +311,7 @@
text {*

-  The the key to this error message is the matrix at the top. The rows
+  The the key to this error message is the matrix at the bottom. The rows
of that matrix correspond to the different recursive calls (In our
case, there is just one). The columns are the function's arguments
(expressed through different measure functions, which map the
@@ -297,11 +320,11 @@
The contents of the matrix summarize what is known about argument
descents: The second argument has a weak descent (@{text "<="}) at the
recursive call, and for the first argument nothing could be proved,
-  which is expressed by @{text N}. In general, there are the values
-  @{text "<"}, @{text "<="} and @{text "N"}.
+  which is expressed by @{text "?"}. In general, there are the values
+  @{text "<"}, @{text "<="} and @{text "?"}.

For the failed proof attempts, the unfinished subgoals are also
-  printed. Looking at these will often point us to a missing lemma.
+  printed. Looking at these will often point to a missing lemma.

%  As a more real example, here is quicksort:
*}
@@ -391,13 +414,12 @@
txt {*
@{subgoals[display,indent=0]}

-  \noindent These can be handeled by the descision procedure for
-  arithmethic.
+  \noindent These can be handled by Isabelle's arithmetic decision procedures.

*}

-apply presburger -- {* \fixme{arith} *}
-apply presburger
+apply arith
+apply arith
done

text {*
@@ -423,6 +445,7 @@
oops

section {* General pattern matching *}
+text{*\label{genpats} *}

subsection {* Avoiding automatic pattern splitting *}

@@ -437,7 +460,7 @@
equations involved, and this is not always desirable. The following
example shows the problem:

-  Suppose we are modelling incomplete knowledge about the world by a
+  Suppose we are modeling incomplete knowledge about the world by a
three-valued datatype, which has values @{term "T"}, @{term "F"}
and @{term "X"} for true, false and uncertain propositions, respectively.
*}
@@ -457,7 +480,7 @@

text {*
This definition is useful, because the equations can directly be used
-  as simplifcation rules rules. But the patterns overlap: For example,
+  as simplification rules rules. But the patterns overlap: For example,
the expression @{term "And T T"} is matched by both the first and
the second equation. By default, Isabelle makes the patterns disjoint by
splitting them up, producing instances:
@@ -538,33 +561,12 @@
subsection {* Non-constructor patterns *}

text {*
-  Most of Isabelle's basic types take the form of inductive data types
-  with constructors. However, this is not true for all of them. The
-  integers, for instance, are defined using the usual algebraic
-  quotient construction, thus they are not an \qt{official} datatype.
-
-  Of course, we might want to do pattern matching there, too. So
-
-
-
-*}
+  Most of Isabelle's basic types take the form of inductive datatypes,
+  and usually pattern matching works on the constructors of such types.
+  However, this need not be always the case, and the \cmd{function}
+  command handles other kind of patterns, too.

-function Abs :: "int \<Rightarrow> nat"
-where
-  "Abs (int n) = n"
-| "Abs (- int (Suc n)) = n"
-by (erule int_cases) auto
-termination by (relation "{}") simp
-
-text {*
-  This kind of matching is again justified by the proof of pattern
-  completeness and compatibility. Here, the existing lemma @{text
-  int_cases} is used:
-
-  \begin{center}@{thm int_cases}\hfill(@{text "int_cases"})\end{center}
-*}
-text {*
-  One well-known instance of non-constructor patterns are the
+  One well-known instance of non-constructor patterns are
so-called \emph{$n+k$-patterns}, which are a little controversial in
the functional programming world. Here is the initial fibonacci
example with $n+k$-patterns:
@@ -578,6 +580,8 @@

(*<*)ML "goals_limit := 1"(*>*)
txt {*
+  This kind of matching is again justified by the proof of pattern
+  completeness and compatibility.
The proof obligation for pattern completeness states that every natural number is
either @{term "0::nat"}, @{term "1::nat"} or @{term "n +
(2::nat)"}:
@@ -586,13 +590,14 @@

This is an arithmetic triviality, but unfortunately the
@{text arith} method cannot handle this specific form of an
-  elimination rule. We have to do a case split on @{text P} first,
-  which can be conveniently done using the @{text
-  classical} rule. Pattern compatibility and termination are automatic as usual.
+  elimination rule. However, we can use the method @{text
+  "elim_to_cases"} to do an ad-hoc conversion to a disjunction of
+  existentials, which can then be soved by the arithmetic decision procedure.
+  Pattern compatibility and termination are automatic as usual.
*}
(*<*)ML "goals_limit := 10"(*>*)
-
-apply (rule classical, simp, arith)
+apply elim_to_cases
+apply arith
apply auto
done
termination by lexicographic_order
@@ -607,7 +612,8 @@
where
"ev (2 * n) = True"
| "ev (2 * n + 1) = False"
-by (rule classical, simp) arith+
+apply elim_to_cases
+by arith+
termination by (relation "{}") simp

text {*
@@ -639,7 +645,7 @@
| "gcd 0 y = y"
| "x < y \<Longrightarrow> gcd (Suc x) (Suc y) = gcd (Suc x) (y - x)"
| "\<not> x < y \<Longrightarrow> gcd (Suc x) (Suc y) = gcd (x - y) (Suc y)"
-by (rule classical, auto, arith)
+by (elim_to_cases, auto, arith)
termination by lexicographic_order

text {*
@@ -654,7 +660,7 @@
subsection {* Pattern matching on strings *}

text {*
-  As strings (as lists of characters) are normal data types, pattern
+  As strings (as lists of characters) are normal datatypes, pattern
matching on them is possible, but somewhat problematic. Consider the
following definition:

@@ -665,9 +671,9 @@
@{text "| \"check s = False\""}
\begin{isamarkuptext}

-  An invocation of the above \cmd{fun} command does not
+  \noindent An invocation of the above \cmd{fun} command does not
terminate. What is the problem? Strings are lists of characters, and
-  characters are a data type with a lot of constructors. Splitting the
+  characters are a datatype with a lot of constructors. Splitting the
catch-all pattern thus leads to an explosion of cases, which cannot
be handled by Isabelle.

@@ -688,7 +694,6 @@
In HOL, all functions are total. A function @{term "f"} applied to
@{term "x"} always has the value @{term "f x"}, and there is no notion
of undefinedness.
-
This is why we have to do termination
proofs when defining functions: The proof justifies that the
function can be defined by wellfounded recursion.
@@ -705,7 +710,7 @@
(*<*)declare findzero.simps[simp del](*>*)

text {*
-  Clearly, any attempt of a termination proof must fail. And without
+  \noindent Clearly, any attempt of a termination proof must fail. And without
that, we do not get the usual rules @{text "findzero.simp"} and
@{text "findzero.induct"}. So what was the definition good for at all?
*}
@@ -723,16 +728,13 @@
pinduct}:
*}

-thm findzero.psimps
+text {*
+  \noindent\begin{minipage}{0.79\textwidth}@{thm[display,margin=85] findzero.psimps}\end{minipage}
+  \hfill(@{text "findzero.psimps"})
+  \vspace{1em}

-text {*
-  @{thm[display] findzero.psimps}
-*}
-
-thm findzero.pinduct
-
-text {*
-  @{thm[display] findzero.pinduct}
+  \noindent\begin{minipage}{0.79\textwidth}@{thm[display,margin=85] findzero.pinduct}\end{minipage}
+  \hfill(@{text "findzero.pinduct"})
*}

text {*
@@ -743,23 +745,23 @@
to some natural number, although we might not be able to find out
which one. The function is \emph{underdefined}.

-  But it is enough defined to prove something interesting about it. We
+  But it is defined enough to prove something interesting about it. We
can prove that if @{term "findzero f n"}
-  it terminates, it indeed returns a zero of @{term f}:
+  terminates, it indeed returns a zero of @{term f}:
*}

lemma findzero_zero: "findzero_dom (f, n) \<Longrightarrow> f (findzero f n) = 0"

-txt {* We apply induction as usual, but using the partial induction
+txt {* \noindent We apply induction as usual, but using the partial induction
rule: *}

apply (induct f n rule: findzero.pinduct)

-txt {* This gives the following subgoals:
+txt {* \noindent This gives the following subgoals:

@{subgoals[display,indent=0]}

-  The hypothesis in our lemma was used to satisfy the first premise in
+  \noindent The hypothesis in our lemma was used to satisfy the first premise in
the induction rule. However, we also get @{term
"findzero_dom (f, n)"} as a local assumption in the induction step. This
allows to unfold @{term "findzero f n"} using the @{text psimps}
@@ -804,8 +806,7 @@
with f n \<noteq> 0 show ?thesis by simp
next
assume "x \<in> {Suc n ..< findzero f n}"
-    with dom and f n \<noteq> 0 have "x \<in> {Suc n ..< findzero f (Suc n)}"
-      by simp
+    with dom and f n \<noteq> 0 have "x \<in> {Suc n ..< findzero f (Suc n)}" by simp
with IH and f n \<noteq> 0
show ?thesis by simp
qed
@@ -863,7 +864,7 @@
that @{text findzero} terminates if there is a zero which is greater
or equal to @{term n}. First we derive two useful rules which will
solve the base case and the step case of the induction. The
-  induction is then straightforward, except for the unusal induction
+  induction is then straightforward, except for the unusual induction
principle.

*}
@@ -911,8 +912,8 @@
assumes zero: "x >= n"
assumes [simp]: "f x = 0"
shows "findzero_dom (f, n)"
-  using zero
-  by (induct rule:inc_induct) (auto intro: findzero.domintros)
+using zero
+by (induct rule:inc_induct) (auto intro: findzero.domintros)

text {*
\noindent It is simple to combine the partial correctness result with the
@@ -927,7 +928,7 @@

text {*
Sometimes it is useful to know what the definition of the domain
-  predicate actually is. Actually, @{text findzero_dom} is just an
+  predicate looks like. Actually, @{text findzero_dom} is just an
abbreviation:

@{abbrev[display] findzero_dom}
@@ -948,22 +949,22 @@
recursive calls. In general, there is one introduction rule for each
recursive call.

-  The predicate @{term "acc findzero_rel"} is the accessible part of
+  The predicate @{term "accp findzero_rel"} is the accessible part of
that relation. An argument belongs to the accessible part, if it can
be reached in a finite number of steps (cf.~its definition in @{text
"Accessible_Part.thy"}).

Since the domain predicate is just an abbreviation, you can use
-  lemmas for @{const acc} and @{const findzero_rel} directly. Some
-  lemmas which are occasionally useful are @{text accI}, @{text
-  acc_downward}, and of course the introduction and elimination rules
+  lemmas for @{const accp} and @{const findzero_rel} directly. Some
+  lemmas which are occasionally useful are @{text accpI}, @{text
+  accp_downward}, and of course the introduction and elimination rules
for the recursion relation @{text "findzero.intros"} and @{text "findzero.cases"}.
*}

(*lemma findzero_nicer_domintros:
"f x = 0 \<Longrightarrow> findzero_dom (f, x)"
"findzero_dom (f, Suc x) \<Longrightarrow> findzero_dom (f, x)"
-by (rule accI, erule findzero_rel.cases, auto)+
+by (rule accpI, erule findzero_rel.cases, auto)+
*)

subsection {* A Useful Special Case: Tail recursion *}
@@ -1067,8 +1068,7 @@
the zero function. And in fact we have no problem proving this
property by induction.
*}
-oops
-
+(*<*)oops(*>*)
lemma nz_is_zero: "nz_dom n \<Longrightarrow> nz n = 0"
by (induct rule:nz.pinduct) auto

@@ -1119,7 +1119,7 @@

assume inner_trm: "f91_dom (n + 11)" -- "Outer call"
with f91_estimate have "n + 11 < f91 (n + 11) + 11" .
-  with \<not> 100 < n show "(f91 (n + 11), n) \<in> ?R" by simp
+  with \<not> 100 < n show "(f91 (n + 11), n) \<in> ?R" by simp
qed

text_raw {*
@@ -1137,7 +1137,7 @@
Higher-order recursion occurs when recursive calls
are passed as arguments to higher-order combinators such as @{term
map}, @{term filter} etc.
-  As an example, imagine a data type of n-ary trees:
+  As an example, imagine a datatype of n-ary trees:
*}

datatype 'a tree =
@@ -1184,14 +1184,14 @@
txt {*
Simplification returns the following subgoal:

-      @{subgoals[display,indent=0]}
+      @{text[display] "1. x \<in> set l \<Longrightarrow> size x < Suc (tree_list_size l)"}

We are lacking a property about the function @{const
tree_list_size}, which was generated automatically at the
definition of the @{text tree} type. We should go back and prove
it, by induction.
*}
-    oops
+    (*<*)oops(*>*)

lemma tree_list_size[simp]: "x \<in> set l \<Longrightarrow> size x < Suc (tree_list_size l)"
by (induct l) auto
@@ -1225,7 +1225,7 @@
Usually, one such congruence rule is
needed for each higher-order construct that is used when defining
new functions. In fact, even basic functions like @{const
-  If} and @{const Let} are handeled by this mechanism. The congruence
+  If} and @{const Let} are handled by this mechanism. The congruence
rule for @{const If} states that the @{text then} branch is only
relevant if the condition is true, and the @{text else} branch only if it
is false:
@@ -1235,20 +1235,82 @@
Congruence rules can be added to the
function package by giving them the @{term fundef_cong} attribute.

-  Isabelle comes with predefined congruence rules for most of the
-  definitions.
-  But if you define your own higher-order constructs, you will have to
+  The constructs that are predefined in Isabelle, usually
+  come with the respective congruence rules.
+  But if you define your own higher-order functions, you will have to
come up with the congruence rules yourself, if you want to use your
-  functions in recursive definitions. Since the structure of
+  functions in recursive definitions.
+*}
+
+subsection {* Congruence Rules and Evaluation Order *}
+
+text {*
+  Higher order logic differs from functional programming languages in
+  that it has no built-in notion of evaluation order. A program is
+  just a set of equations, and it is not specified how they must be
+  evaluated.
+
+  However for the purpose of function definition, we must talk about
+  evaluation order implicitly, when we reason about termination.
+  Congruence rules express that a certain evaluation order is
+  consistent with the logical definition.
+
+  Consider the following function.
+*}
+
+function f :: "nat \<Rightarrow> bool"
+where
+  "f n = (n = 0 \<or> f (n - 1))"
+(*<*)by pat_completeness auto(*>*)
+
+text {*
+  As given above, the definition fails. The default configuration
+  specifies no congruence rule for disjunction. We have to add a
+  congruence rule that specifies left-to-right evaluation order:
+
+  \vspace{1ex}
+  \noindent @{thm disj_cong}\hfill(@{text "disj_cong"})
+  \vspace{1ex}
+
+  Now the definition works without problems. Note how the termination
+  proof depends on the extra condition that we get from the congruence
+  rule.
+
+  However, as evaluation is not a hard-wired concept, we
+  could just turn everything around by declaring a different
+  congruence rule. Then we can make the reverse definition:
+*}
+
+lemma disj_cong2[fundef_cong]:
+  "(\<not> Q' \<Longrightarrow> P = P') \<Longrightarrow> (Q = Q') \<Longrightarrow> (P \<or> Q) = (P' \<or> Q')"
+  by blast
+
+fun f' :: "nat \<Rightarrow> bool"
+where
+  "f' n = (f' (n - 1) \<or> n = 0)"
+
+text {*
+  \noindent These examples show that, in general, there is no \qt{best} set of
+  congruence rules.
+
+  However, such tweaking should rarely be necessary in
+  practice, as most of the time, the default set of congruence rules
+  works well.
+*}
+
+(*
+text {*
+Since the structure of
congruence rules is a little unintuitive, here are some exercises:
*}
-(*<*)
+
fun mapeven :: "(nat \<Rightarrow> nat) \<Rightarrow> nat list \<Rightarrow> nat list"
where
"mapeven f [] = []"
| "mapeven f (x#xs) = (if x mod 2 = 0 then f x # mapeven f xs else x #
mapeven f xs)"
-(*>*)
+
+
text {*

\begin{exercise}
@@ -1267,5 +1329,5 @@
\fixme{}

*}
-
+*)
end
--- a/doc-src/IsarAdvanced/Functions/Thy/document/Functions.tex	Thu Jul 12 11:43:17 2007 +0200
+++ b/doc-src/IsarAdvanced/Functions/Thy/document/Functions.tex	Thu Jul 12 12:20:39 2007 +0200
@@ -37,7 +37,7 @@
\begin{isamarkuptext}%
The syntax is rather self-explanatory: We introduce a function by
giving its name, its type and a set of defining recursive
-  equations. Note that the function is not primitive recursive.%
+  equations.%
\end{isamarkuptext}%
\isamarkuptrue%
%
@@ -48,7 +48,6 @@
fundamental requirement to prevent inconsistencies\footnote{From the
\qt{definition} \isa{f{\isacharparenleft}n{\isacharparenright}\ {\isacharequal}\ f{\isacharparenleft}n{\isacharparenright}\ {\isacharplus}\ {\isadigit{1}}} we could prove
\isa{{\isadigit{0}}\ {\isacharequal}\ {\isadigit{1}}} by subtracting \isa{f{\isacharparenleft}n{\isacharparenright}} on both sides.}.
-
Isabelle tries to prove termination automatically when a definition
is made. In \S\ref{termination}, we will look at cases where this
fails and see what to do then.%
@@ -64,7 +63,9 @@
Like in functional programming, we can use pattern matching to
define functions. At the moment we will only consider \emph{constructor
patterns}, which only consist of datatype constructors and
-  (linear occurrences of) variables.
+  variables. Furthermore, patterns must be linear, i.e.\ all variables
+  on the left hand side of an equation must be distinct. In
+  \S\ref{genpats} we discuss more general pattern matching.

If patterns overlap, the order of the equations is taken into
account. The following function inserts a fixed element between any
@@ -95,7 +96,7 @@
\isamarkuptrue%
%
\begin{isamarkuptext}%
-The equations from function definitions are automatically used in
+\noindent The equations from function definitions are automatically used in
simplification:%
\end{isamarkuptext}%
\isamarkuptrue%
@@ -121,11 +122,56 @@
\isamarkuptrue%
%
\begin{isamarkuptext}%
-Isabelle provides customized induction rules for recursive functions.
-  See \cite[\S3.5.4]{isa-tutorial}. \fixme{Cases?}
+Isabelle provides customized induction rules for recursive
+  functions. These rules follow the recursive structure of the
+  definition. Here is the rule \isa{sep{\isachardot}induct} arising from the
+  above definition of \isa{sep}:

+  \begin{isabelle}%
+{\isasymlbrakk}{\isasymAnd}a\ x\ y\ xs{\isachardot}\ {\isacharquery}P\ a\ {\isacharparenleft}y\ {\isacharhash}\ xs{\isacharparenright}\ {\isasymLongrightarrow}\ {\isacharquery}P\ a\ {\isacharparenleft}x\ {\isacharhash}\ y\ {\isacharhash}\ xs{\isacharparenright}{\isacharsemicolon}\ {\isasymAnd}a{\isachardot}\ {\isacharquery}P\ a\ {\isacharbrackleft}{\isacharbrackright}{\isacharsemicolon}\ {\isasymAnd}a\ v{\isachardot}\ {\isacharquery}P\ a\ {\isacharbrackleft}v{\isacharbrackright}{\isasymrbrakk}\isanewline
+{\isasymLongrightarrow}\ {\isacharquery}P\ {\isacharquery}a{\isadigit{0}}{\isachardot}{\isadigit{0}}\ {\isacharquery}a{\isadigit{1}}{\isachardot}{\isadigit{0}}%
+\end{isabelle}
+
+  We have a step case for list with at least two elements, and two
+  base cases for the zero- and the one-element list. Here is a simple
+  proof about \isa{sep} and \isa{map}%
+\end{isamarkuptext}%
+\isamarkuptrue%
+\isacommand{lemma}\isamarkupfalse%
+\ {\isachardoublequoteopen}map\ f\ {\isacharparenleft}sep\ x\ ys{\isacharparenright}\ {\isacharequal}\ sep\ {\isacharparenleft}f\ x{\isacharparenright}\ {\isacharparenleft}map\ f\ ys{\isacharparenright}{\isachardoublequoteclose}\isanewline
+%
+\isadelimproof
+%
+\endisadelimproof
+%
+\isatagproof
+\isacommand{apply}\isamarkupfalse%
+\ {\isacharparenleft}induct\ x\ ys\ rule{\isacharcolon}\ sep{\isachardot}induct{\isacharparenright}%
+\begin{isamarkuptxt}%
+We get three cases, like in the definition.

-  With the \cmd{fun} command, you can define about 80\% of the
+  \begin{isabelle}%
+\ {\isadigit{1}}{\isachardot}\ {\isasymAnd}a\ x\ y\ xs{\isachardot}\isanewline
+\isaindent{\ {\isadigit{1}}{\isachardot}\ \ \ \ }map\ f\ {\isacharparenleft}sep\ a\ {\isacharparenleft}y\ {\isacharhash}\ xs{\isacharparenright}{\isacharparenright}\ {\isacharequal}\ sep\ {\isacharparenleft}f\ a{\isacharparenright}\ {\isacharparenleft}map\ f\ {\isacharparenleft}y\ {\isacharhash}\ xs{\isacharparenright}{\isacharparenright}\ {\isasymLongrightarrow}\isanewline
+\isaindent{\ {\isadigit{1}}{\isachardot}\ \ \ \ }map\ f\ {\isacharparenleft}sep\ a\ {\isacharparenleft}x\ {\isacharhash}\ y\ {\isacharhash}\ xs{\isacharparenright}{\isacharparenright}\ {\isacharequal}\ sep\ {\isacharparenleft}f\ a{\isacharparenright}\ {\isacharparenleft}map\ f\ {\isacharparenleft}x\ {\isacharhash}\ y\ {\isacharhash}\ xs{\isacharparenright}{\isacharparenright}\isanewline
+\ {\isadigit{2}}{\isachardot}\ {\isasymAnd}a{\isachardot}\ map\ f\ {\isacharparenleft}sep\ a\ {\isacharbrackleft}{\isacharbrackright}{\isacharparenright}\ {\isacharequal}\ sep\ {\isacharparenleft}f\ a{\isacharparenright}\ {\isacharparenleft}map\ f\ {\isacharbrackleft}{\isacharbrackright}{\isacharparenright}\isanewline
+\ {\isadigit{3}}{\isachardot}\ {\isasymAnd}a\ v{\isachardot}\ map\ f\ {\isacharparenleft}sep\ a\ {\isacharbrackleft}v{\isacharbrackright}{\isacharparenright}\ {\isacharequal}\ sep\ {\isacharparenleft}f\ a{\isacharparenright}\ {\isacharparenleft}map\ f\ {\isacharbrackleft}v{\isacharbrackright}{\isacharparenright}%
+\end{isabelle}%
+\end{isamarkuptxt}%
+\isamarkuptrue%
+\isacommand{apply}\isamarkupfalse%
+\ auto\ \isanewline
+\isacommand{done}\isamarkupfalse%
+%
+\endisatagproof
+{\isafoldproof}%
+%
+\isadelimproof
+%
+\endisadelimproof
+%
+\begin{isamarkuptext}%
+With the \cmd{fun} command, you can define about 80\% of the
functions that occur in practice. The rest of this tutorial explains
the remaining 20\%.%
\end{isamarkuptext}%
@@ -173,7 +219,7 @@

\begin{enumerate}
\item The \cmd{sequential} option enables the preprocessing of
-  pattern overlaps we already saw. Without this option, the equations
+  pattern overlaps which we already saw. Without this option, the equations
must already be disjoint and complete. The automatic completion only
works with constructor patterns.

@@ -197,10 +243,12 @@
%
\begin{isamarkuptext}%
\label{termination}
-  The \isa{lexicographic{\isacharunderscore}order} method can prove termination of a
+  The method \isa{lexicographic{\isacharunderscore}order} is the default method for
+  termination proofs. It can prove termination of a
certain class of functions by searching for a suitable lexicographic
combination of size measures. Of course, not all functions have such
-  a simple termination argument.%
+  a simple termination argument. For them, we can specify the termination
+  relation manually.%
\end{isamarkuptext}%
\isamarkuptrue%
%
@@ -234,24 +282,20 @@
%
\begin{isamarkuptext}%
\noindent The \isa{lexicographic{\isacharunderscore}order} method fails on this example, because none of the
-  arguments decreases in the recursive call.
-  % FIXME: simps and induct only appear after "termination"
-
-  The easiest way of doing termination proofs is to supply a wellfounded
-  relation on the argument type, and to show that the argument
-  decreases in every recursive call.
+  arguments decreases in the recursive call, with respect to the standard size ordering.
+  To prove termination manually, we must provide a custom wellfounded relation.

The termination argument for \isa{sum} is based on the fact that
the \emph{difference} between \isa{i} and \isa{N} gets
smaller in every step, and that the recursion stops when \isa{i}
-  is greater then \isa{n}. Phrased differently, the expression
-  \isa{N\ {\isacharplus}\ {\isadigit{1}}\ {\isacharminus}\ i} decreases in every recursive call.
+  is greater than \isa{N}. Phrased differently, the expression
+  \isa{N\ {\isacharplus}\ {\isadigit{1}}\ {\isacharminus}\ i} always decreases.

We can use this expression as a measure function suitable to prove termination.%
\end{isamarkuptext}%
\isamarkuptrue%
\isacommand{termination}\isamarkupfalse%
-\ sum\isanewline
+\isanewline
%
\isadelimproof
%
@@ -371,26 +415,29 @@
\noindent Isabelle responds with the following error:

\begin{isabelle}
-*** Could not find lexicographic termination order:\newline
-*** \ \ \ \ 1\ \ 2  \newline
-*** a:  N   <= \newline
+*** Unfinished subgoals:\newline
+*** (a, 1, <):\newline
+*** \ 1.~\isa{{\isasymAnd}x{\isachardot}\ x\ {\isacharequal}\ {\isadigit{0}}}\newline
+*** (a, 1, <=):\newline
+*** \ 1.~False\newline
+*** (a, 2, <):\newline
+*** \ 1.~False\newline
*** Calls:\newline
*** a) \isa{{\isacharparenleft}a{\isacharcomma}\ x\ {\isacharhash}\ xs{\isacharparenright}\ {\isacharminus}{\isacharminus}{\isachargreater}{\isachargreater}\ {\isacharparenleft}x\ {\isacharplus}\ a{\isacharcomma}\ x\ {\isacharhash}\ xs{\isacharparenright}}\newline
*** Measures:\newline
*** 1) \isa{{\isasymlambda}x{\isachardot}\ size\ {\isacharparenleft}fst\ x{\isacharparenright}}\newline
*** 2) \isa{{\isasymlambda}x{\isachardot}\ size\ {\isacharparenleft}snd\ x{\isacharparenright}}\newline
-*** Unfinished subgoals:\newline
-*** \isa{{\isasymAnd}a\ x\ xs{\isachardot}}\newline
-*** \quad \isa{{\isacharparenleft}x{\isachardot}\ size\ {\isacharparenleft}fst\ x{\isacharparenright}{\isacharparenright}\ {\isacharparenleft}x\ {\isacharplus}\ a{\isacharcomma}\ x\ {\isacharhash}\ xs{\isacharparenright}}\newline
-***  \quad \isa{{\isasymle}\ {\isacharparenleft}{\isasymlambda}x{\isachardot}\ size\ {\isacharparenleft}fst\ x{\isacharparenright}{\isacharparenright}\ {\isacharparenleft}a{\isacharcomma}\ x\ {\isacharhash}\ xs{\isacharparenright}}\newline
-***  \isa{{\isadigit{1}}{\isachardot}\ {\isasymAnd}x{\isachardot}\ x\ {\isacharequal}\ {\isadigit{0}}}\newline
+*** Result matrix:\newline
+*** \ \ \ \ 1\ \ 2  \newline
+*** a:  ?   <= \newline
+*** Could not find lexicographic termination order.\newline
*** At command "fun".\newline
\end{isabelle}%
\end{isamarkuptext}%
\isamarkuptrue%
%
\begin{isamarkuptext}%
-The the key to this error message is the matrix at the top. The rows
+The the key to this error message is the matrix at the bottom. The rows
of that matrix correspond to the different recursive calls (In our
case, there is just one). The columns are the function's arguments
(expressed through different measure functions, which map the
@@ -399,11 +446,11 @@
The contents of the matrix summarize what is known about argument
descents: The second argument has a weak descent (\isa{{\isacharless}{\isacharequal}}) at the
recursive call, and for the first argument nothing could be proved,
-  which is expressed by \isa{N}. In general, there are the values
-  \isa{{\isacharless}}, \isa{{\isacharless}{\isacharequal}} and \isa{N}.
+  which is expressed by \isa{{\isacharquery}}. In general, there are the values
+  \isa{{\isacharless}}, \isa{{\isacharless}{\isacharequal}} and \isa{{\isacharquery}}.

For the failed proof attempts, the unfinished subgoals are also
-  printed. Looking at these will often point us to a missing lemma.
+  printed. Looking at these will often point to a missing lemma.

%  As a more real example, here is quicksort:%
\end{isamarkuptext}%
@@ -523,17 +570,13 @@
\ {\isadigit{2}}{\isachardot}\ {\isasymAnd}n{\isachardot}\ even\ n\ {\isacharequal}\ {\isacharparenleft}n\ mod\ {\isadigit{2}}\ {\isacharequal}\ {\isadigit{0}}{\isacharparenright}\ {\isasymLongrightarrow}\ {\isacharparenleft}n\ mod\ {\isadigit{2}}\ {\isacharequal}\ {\isadigit{0}}{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}Suc\ n\ mod\ {\isadigit{2}}\ {\isacharequal}\ Suc\ {\isadigit{0}}{\isacharparenright}%
\end{isabelle}

-  \noindent These can be handeled by the descision procedure for
-  arithmethic.%
+  \noindent These can be handled by Isabelle's arithmetic decision procedures.%
\end{isamarkuptxt}%
\isamarkuptrue%
\isacommand{apply}\isamarkupfalse%
-\ presburger\ %
-\isamarkupcmt{\fixme{arith}%
-}
-\isanewline
+\ arith\isanewline
\isacommand{apply}\isamarkupfalse%
-\ presburger\isanewline
+\ arith\isanewline
\isacommand{done}\isamarkupfalse%
%
\endisatagproof
@@ -587,6 +630,11 @@
}
\isamarkuptrue%
%
+\begin{isamarkuptext}%
+\label{genpats}%
+\end{isamarkuptext}%
+\isamarkuptrue%
+%
\isamarkupsubsection{Avoiding automatic pattern splitting%
}
\isamarkuptrue%
@@ -601,7 +649,7 @@
equations involved, and this is not always desirable. The following
example shows the problem:

-  Suppose we are modelling incomplete knowledge about the world by a
+  Suppose we are modeling incomplete knowledge about the world by a
three-valued datatype, which has values \isa{T}, \isa{F}
and \isa{X} for true, false and uncertain propositions, respectively.%
\end{isamarkuptext}%
@@ -622,7 +670,7 @@
{\isacharbar}\ {\isachardoublequoteopen}And\ X\ X\ {\isacharequal}\ X{\isachardoublequoteclose}%
\begin{isamarkuptext}%
This definition is useful, because the equations can directly be used
-  as simplifcation rules rules. But the patterns overlap: For example,
+  as simplification rules rules. But the patterns overlap: For example,
the expression \isa{And\ T\ T} is matched by both the first and
the second equation. By default, Isabelle makes the patterns disjoint by
splitting them up, producing instances:%
@@ -733,60 +781,12 @@
\isamarkuptrue%
%
\begin{isamarkuptext}%
-Most of Isabelle's basic types take the form of inductive data types
-  with constructors. However, this is not true for all of them. The
-  integers, for instance, are defined using the usual algebraic
-  quotient construction, thus they are not an \qt{official} datatype.
+Most of Isabelle's basic types take the form of inductive datatypes,
+  and usually pattern matching works on the constructors of such types.
+  However, this need not be always the case, and the \cmd{function}
+  command handles other kind of patterns, too.

-  Of course, we might want to do pattern matching there, too. So%
-\end{isamarkuptext}%
-\isamarkuptrue%
-\isacommand{function}\isamarkupfalse%
-\ Abs\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequoteopen}int\ {\isasymRightarrow}\ nat{\isachardoublequoteclose}\isanewline
-\isakeyword{where}\isanewline
-\ \ {\isachardoublequoteopen}Abs\ {\isacharparenleft}int\ n{\isacharparenright}\ {\isacharequal}\ n{\isachardoublequoteclose}\isanewline
-{\isacharbar}\ {\isachardoublequoteopen}Abs\ {\isacharparenleft}{\isacharminus}\ int\ {\isacharparenleft}Suc\ n{\isacharparenright}{\isacharparenright}\ {\isacharequal}\ n{\isachardoublequoteclose}\isanewline
-%
-\isadelimproof
-%
-\endisadelimproof
-%
-\isatagproof
-\isacommand{by}\isamarkupfalse%
-\ {\isacharparenleft}erule\ int{\isacharunderscore}cases{\isacharparenright}\ auto%
-\endisatagproof
-{\isafoldproof}%
-%
-\isadelimproof
-\isanewline
-%
-\endisadelimproof
-\isacommand{termination}\isamarkupfalse%
-%
-\isadelimproof
-\ %
-\endisadelimproof
-%
-\isatagproof
-\isacommand{by}\isamarkupfalse%
-\ {\isacharparenleft}relation\ {\isachardoublequoteopen}{\isacharbraceleft}{\isacharbraceright}{\isachardoublequoteclose}{\isacharparenright}\ simp%
-\endisatagproof
-{\isafoldproof}%
-%
-\isadelimproof
-%
-\endisadelimproof
-%
-\begin{isamarkuptext}%
-This kind of matching is again justified by the proof of pattern
-  completeness and compatibility. Here, the existing lemma \isa{int{\isacharunderscore}cases} is used:
-
-  \begin{center}\isa{{\isasymlbrakk}{\isasymAnd}n{\isachardot}\ {\isacharquery}z\ {\isacharequal}\ int\ n\ {\isasymLongrightarrow}\ {\isacharquery}P{\isacharsemicolon}\ {\isasymAnd}n{\isachardot}\ {\isacharquery}z\ {\isacharequal}\ {\isacharminus}\ int\ {\isacharparenleft}Suc\ n{\isacharparenright}\ {\isasymLongrightarrow}\ {\isacharquery}P{\isasymrbrakk}\ {\isasymLongrightarrow}\ {\isacharquery}P}\hfill(\isa{int{\isacharunderscore}cases})\end{center}%
-\end{isamarkuptext}%
-\isamarkuptrue%
-%
-\begin{isamarkuptext}%
-One well-known instance of non-constructor patterns are the
+  One well-known instance of non-constructor patterns are
so-called \emph{$n+k$-patterns}, which are a little controversial in
the functional programming world. Here is the initial fibonacci
example with $n+k$-patterns:%
@@ -819,7 +819,9 @@
\isatagproof
%
\begin{isamarkuptxt}%
-The proof obligation for pattern completeness states that every natural number is
+This kind of matching is again justified by the proof of pattern
+  completeness and compatibility.
+  The proof obligation for pattern completeness states that every natural number is
either \isa{{\isadigit{0}}}, \isa{{\isadigit{1}}} or \isa{n\ {\isacharplus}\ {\isadigit{2}}}:

\begin{isabelle}%
@@ -828,8 +830,9 @@

This is an arithmetic triviality, but unfortunately the
\isa{arith} method cannot handle this specific form of an
-  elimination rule. We have to do a case split on \isa{P} first,
-  which can be conveniently done using the \isa{classical} rule. Pattern compatibility and termination are automatic as usual.%
+  elimination rule. However, we can use the method \isa{elim{\isacharunderscore}to{\isacharunderscore}cases} to do an ad-hoc conversion to a disjunction of
+  existentials, which can then be soved by the arithmetic decision procedure.
+  Pattern compatibility and termination are automatic as usual.%
\end{isamarkuptxt}%
\isamarkuptrue%
%
@@ -852,7 +855,6 @@
\isadelimML
%
\endisadelimML
-\isanewline
%
\isadelimproof
%
@@ -860,7 +862,9 @@
%
\isatagproof
\isacommand{apply}\isamarkupfalse%
-\ {\isacharparenleft}rule\ classical{\isacharcomma}\ simp{\isacharcomma}\ arith{\isacharparenright}\isanewline
+\ elim{\isacharunderscore}to{\isacharunderscore}cases\isanewline
+\isacommand{apply}\isamarkupfalse%
+\ arith\isanewline
\isacommand{apply}\isamarkupfalse%
\ auto\isanewline
\isacommand{done}\isamarkupfalse%
@@ -905,8 +909,10 @@
\endisadelimproof
%
\isatagproof
+\isacommand{apply}\isamarkupfalse%
+\ elim{\isacharunderscore}to{\isacharunderscore}cases\isanewline
\isacommand{by}\isamarkupfalse%
-\ {\isacharparenleft}rule\ classical{\isacharcomma}\ simp{\isacharparenright}\ arith{\isacharplus}%
+\ arith{\isacharplus}%
\endisatagproof
{\isafoldproof}%
%
@@ -969,7 +975,7 @@
%
\isatagproof
\isacommand{by}\isamarkupfalse%
-\ {\isacharparenleft}rule\ classical{\isacharcomma}\ auto{\isacharcomma}\ arith{\isacharparenright}%
+\ {\isacharparenleft}elim{\isacharunderscore}to{\isacharunderscore}cases{\isacharcomma}\ auto{\isacharcomma}\ arith{\isacharparenright}%
\endisatagproof
{\isafoldproof}%
%
@@ -1007,7 +1013,7 @@
\isamarkuptrue%
%
\begin{isamarkuptext}%
-As strings (as lists of characters) are normal data types, pattern
+As strings (as lists of characters) are normal datatypes, pattern
matching on them is possible, but somewhat problematic. Consider the
following definition:

@@ -1018,9 +1024,9 @@
\isa{{\isacharbar}\ {\isachardoublequote}check\ s\ {\isacharequal}\ False{\isachardoublequote}}
\begin{isamarkuptext}

-  An invocation of the above \cmd{fun} command does not
+  \noindent An invocation of the above \cmd{fun} command does not
terminate. What is the problem? Strings are lists of characters, and
-  characters are a data type with a lot of constructors. Splitting the
+  characters are a datatype with a lot of constructors. Splitting the
catch-all pattern thus leads to an explosion of cases, which cannot
be handled by Isabelle.

@@ -1056,7 +1062,6 @@
In HOL, all functions are total. A function \isa{f} applied to
\isa{x} always has the value \isa{f\ x}, and there is no notion
of undefinedness.
-
This is why we have to do termination
proofs when defining functions: The proof justifies that the
function can be defined by wellfounded recursion.
@@ -1086,7 +1091,7 @@
\endisadelimproof
%
\begin{isamarkuptext}%
-Clearly, any attempt of a termination proof must fail. And without
+\noindent Clearly, any attempt of a termination proof must fail. And without
that, we do not get the usual rules \isa{findzero{\isachardot}simp} and
\isa{findzero{\isachardot}induct}. So what was the definition good for at all?%
\end{isamarkuptext}%
@@ -1106,23 +1111,21 @@
by domain conditions and are called \isa{psimps} and \isa{pinduct}:%
\end{isamarkuptext}%
\isamarkuptrue%
-\isacommand{thm}\isamarkupfalse%
-\ findzero{\isachardot}psimps%
+%
\begin{isamarkuptext}%
-\begin{isabelle}%
+\noindent\begin{minipage}{0.79\textwidth}\begin{isabelle}%
findzero{\isacharunderscore}dom\ {\isacharparenleft}{\isacharquery}f{\isacharcomma}\ {\isacharquery}n{\isacharparenright}\ {\isasymLongrightarrow}\isanewline
findzero\ {\isacharquery}f\ {\isacharquery}n\ {\isacharequal}\ {\isacharparenleft}if\ {\isacharquery}f\ {\isacharquery}n\ {\isacharequal}\ {\isadigit{0}}\ then\ {\isacharquery}n\ else\ findzero\ {\isacharquery}f\ {\isacharparenleft}Suc\ {\isacharquery}n{\isacharparenright}{\isacharparenright}%
-\end{isabelle}%
-\end{isamarkuptext}%
-\isamarkuptrue%
-\isacommand{thm}\isamarkupfalse%
-\ findzero{\isachardot}pinduct%
-\begin{isamarkuptext}%
-\begin{isabelle}%
+\end{isabelle}\end{minipage}
+  \hfill(\isa{findzero{\isachardot}psimps})
+  \vspace{1em}
+
+  \noindent\begin{minipage}{0.79\textwidth}\begin{isabelle}%
{\isasymlbrakk}findzero{\isacharunderscore}dom\ {\isacharparenleft}{\isacharquery}a{\isadigit{0}}{\isachardot}{\isadigit{0}}{\isacharcomma}\ {\isacharquery}a{\isadigit{1}}{\isachardot}{\isadigit{0}}{\isacharparenright}{\isacharsemicolon}\isanewline
\isaindent{\ }{\isasymAnd}f\ n{\isachardot}\ {\isasymlbrakk}findzero{\isacharunderscore}dom\ {\isacharparenleft}f{\isacharcomma}\ n{\isacharparenright}{\isacharsemicolon}\ f\ n\ {\isasymnoteq}\ {\isadigit{0}}\ {\isasymLongrightarrow}\ {\isacharquery}P\ f\ {\isacharparenleft}Suc\ n{\isacharparenright}{\isasymrbrakk}\ {\isasymLongrightarrow}\ {\isacharquery}P\ f\ n{\isasymrbrakk}\isanewline
{\isasymLongrightarrow}\ {\isacharquery}P\ {\isacharquery}a{\isadigit{0}}{\isachardot}{\isadigit{0}}\ {\isacharquery}a{\isadigit{1}}{\isachardot}{\isadigit{0}}%
-\end{isabelle}%
+\end{isabelle}\end{minipage}
+  \hfill(\isa{findzero{\isachardot}pinduct})%
\end{isamarkuptext}%
\isamarkuptrue%
%
@@ -1133,9 +1136,9 @@
to some natural number, although we might not be able to find out
which one. The function is \emph{underdefined}.

-  But it is enough defined to prove something interesting about it. We
+  But it is defined enough to prove something interesting about it. We
can prove that if \isa{findzero\ f\ n}
-  it terminates, it indeed returns a zero of \isa{f}:%
+  terminates, it indeed returns a zero of \isa{f}:%
\end{isamarkuptext}%
\isamarkuptrue%
\isacommand{lemma}\isamarkupfalse%
@@ -1147,21 +1150,21 @@
\isatagproof
%
\begin{isamarkuptxt}%
-We apply induction as usual, but using the partial induction
+\noindent We apply induction as usual, but using the partial induction
rule:%
\end{isamarkuptxt}%
\isamarkuptrue%
\isacommand{apply}\isamarkupfalse%
\ {\isacharparenleft}induct\ f\ n\ rule{\isacharcolon}\ findzero{\isachardot}pinduct{\isacharparenright}%
\begin{isamarkuptxt}%
-This gives the following subgoals:
+\noindent This gives the following subgoals:

\begin{isabelle}%
\ {\isadigit{1}}{\isachardot}\ {\isasymAnd}f\ n{\isachardot}\ {\isasymlbrakk}findzero{\isacharunderscore}dom\ {\isacharparenleft}f{\isacharcomma}\ n{\isacharparenright}{\isacharsemicolon}\ f\ n\ {\isasymnoteq}\ {\isadigit{0}}\ {\isasymLongrightarrow}\ f\ {\isacharparenleft}findzero\ f\ {\isacharparenleft}Suc\ n{\isacharparenright}{\isacharparenright}\ {\isacharequal}\ {\isadigit{0}}{\isasymrbrakk}\isanewline
\isaindent{\ {\isadigit{1}}{\isachardot}\ {\isasymAnd}f\ n{\isachardot}\ }{\isasymLongrightarrow}\ f\ {\isacharparenleft}findzero\ f\ n{\isacharparenright}\ {\isacharequal}\ {\isadigit{0}}%
\end{isabelle}

-  The hypothesis in our lemma was used to satisfy the first premise in
+  \noindent The hypothesis in our lemma was used to satisfy the first premise in
the induction rule. However, we also get \isa{findzero{\isacharunderscore}dom\ {\isacharparenleft}f{\isacharcomma}\ n{\isacharparenright}} as a local assumption in the induction step. This
allows to unfold \isa{findzero\ f\ n} using the \isa{psimps}
rule, and the rest is trivial. Since the \isa{psimps} rules carry the
@@ -1246,8 +1249,7 @@
\ {\isachardoublequoteopen}x\ {\isasymin}\ {\isacharbraceleft}Suc\ n\ {\isachardot}{\isachardot}{\isacharless}\ findzero\ f\ n{\isacharbraceright}{\isachardoublequoteclose}\isanewline
\ \ \ \ \isacommand{with}\isamarkupfalse%
\ dom\ \isakeyword{and}\ {\isacharbackquoteopen}f\ n\ {\isasymnoteq}\ {\isadigit{0}}{\isacharbackquoteclose}\ \isacommand{have}\isamarkupfalse%
-\ {\isachardoublequoteopen}x\ {\isasymin}\ {\isacharbraceleft}Suc\ n\ {\isachardot}{\isachardot}{\isacharless}\ findzero\ f\ {\isacharparenleft}Suc\ n{\isacharparenright}{\isacharbraceright}{\isachardoublequoteclose}\isanewline
-\ \ \ \ \ \ \isacommand{by}\isamarkupfalse%
+\ {\isachardoublequoteopen}x\ {\isasymin}\ {\isacharbraceleft}Suc\ n\ {\isachardot}{\isachardot}{\isacharless}\ findzero\ f\ {\isacharparenleft}Suc\ n{\isacharparenright}{\isacharbraceright}{\isachardoublequoteclose}\ \isacommand{by}\isamarkupfalse%
\ simp\isanewline
\ \ \ \ \isacommand{with}\isamarkupfalse%
\ IH\ \isakeyword{and}\ {\isacharbackquoteopen}f\ n\ {\isasymnoteq}\ {\isadigit{0}}{\isacharbackquoteclose}\isanewline
@@ -1318,7 +1320,7 @@
that \isa{findzero} terminates if there is a zero which is greater
or equal to \isa{n}. First we derive two useful rules which will
solve the base case and the step case of the induction. The
-  induction is then straightforward, except for the unusal induction
+  induction is then straightforward, except for the unusual induction
principle.%
\end{isamarkuptext}%
\isamarkuptrue%
@@ -1396,13 +1398,13 @@
\ \ \isakeyword{shows}\ {\isachardoublequoteopen}findzero{\isacharunderscore}dom\ {\isacharparenleft}f{\isacharcomma}\ n{\isacharparenright}{\isachardoublequoteclose}\isanewline
%
\isadelimproof
-\ \ %
+%
\endisadelimproof
%
\isatagproof
\isacommand{using}\isamarkupfalse%
\ zero\isanewline
-\ \ \isacommand{by}\isamarkupfalse%
+\isacommand{by}\isamarkupfalse%
\ {\isacharparenleft}induct\ rule{\isacharcolon}inc{\isacharunderscore}induct{\isacharparenright}\ {\isacharparenleft}auto\ intro{\isacharcolon}\ findzero{\isachardot}domintros{\isacharparenright}%
\endisatagproof
{\isafoldproof}%
@@ -1440,11 +1442,11 @@
%
\begin{isamarkuptext}%
Sometimes it is useful to know what the definition of the domain
-  predicate actually is. Actually, \isa{findzero{\isacharunderscore}dom} is just an
+  predicate looks like. Actually, \isa{findzero{\isacharunderscore}dom} is just an
abbreviation:

\begin{isabelle}%
-findzero{\isacharunderscore}dom\ {\isasymequiv}\ acc\ findzero{\isacharunderscore}rel%
+findzero{\isacharunderscore}dom\ {\isasymequiv}\ accp\ findzero{\isacharunderscore}rel%
\end{isabelle}

The domain predicate is the \emph{accessible part} of a relation \isa{findzero{\isacharunderscore}rel}, which was also created internally by the function
@@ -1469,8 +1471,8 @@
be reached in a finite number of steps (cf.~its definition in \isa{Accessible{\isacharunderscore}Part{\isachardot}thy}).

Since the domain predicate is just an abbreviation, you can use
-  lemmas for \isa{acc} and \isa{findzero{\isacharunderscore}rel} directly. Some
-  lemmas which are occasionally useful are \isa{accI}, \isa{acc{\isacharunderscore}downward}, and of course the introduction and elimination rules
+  lemmas for \isa{accp} and \isa{findzero{\isacharunderscore}rel} directly. Some
+  lemmas which are occasionally useful are \isa{accpI}, \isa{accp{\isacharunderscore}downward}, and of course the introduction and elimination rules
for the recursion relation \isa{findzero{\isachardot}intros} and \isa{findzero{\isachardot}cases}.%
\end{isamarkuptext}%
\isamarkuptrue%
@@ -1608,16 +1610,13 @@
property by induction.%
\end{isamarkuptxt}%
\isamarkuptrue%
-\isacommand{oops}\isamarkupfalse%
%
\endisatagproof
{\isafoldproof}%
%
\isadelimproof
-\isanewline
%
\endisadelimproof
-\isanewline
\isacommand{lemma}\isamarkupfalse%
\ nz{\isacharunderscore}is{\isacharunderscore}zero{\isacharcolon}\ {\isachardoublequoteopen}nz{\isacharunderscore}dom\ n\ {\isasymLongrightarrow}\ nz\ n\ {\isacharequal}\ {\isadigit{0}}{\isachardoublequoteclose}\isanewline
%
@@ -1755,7 +1754,7 @@
\ \ \isacommand{with}\isamarkupfalse%
\ {\isacharbackquoteopen}{\isasymnot}\ {\isadigit{1}}{\isadigit{0}}{\isadigit{0}}\ {\isacharless}\ n{\isacharbackquoteclose}\ \isacommand{show}\isamarkupfalse%
\ {\isachardoublequoteopen}{\isacharparenleft}f{\isadigit{9}}{\isadigit{1}}\ {\isacharparenleft}n\ {\isacharplus}\ {\isadigit{1}}{\isadigit{1}}{\isacharparenright}{\isacharcomma}\ n{\isacharparenright}\ {\isasymin}\ {\isacharquery}R{\isachardoublequoteclose}\ \isacommand{by}\isamarkupfalse%
-\ simp\ \isanewline
+\ simp\isanewline
\isacommand{qed}\isamarkupfalse%
%
\endisatagproof
@@ -1778,7 +1777,7 @@
\begin{isamarkuptext}%
Higher-order recursion occurs when recursive calls
are passed as arguments to higher-order combinators such as \isa{map}, \isa{filter} etc.
-  As an example, imagine a data type of n-ary trees:%
+  As an example, imagine a datatype of n-ary trees:%
\end{isamarkuptext}%
\isamarkuptrue%
\isacommand{datatype}\isamarkupfalse%
@@ -1858,7 +1857,7 @@
Simplification returns the following subgoal:

\begin{isabelle}%
-\ {\isadigit{1}}{\isachardot}\ x{\isacharunderscore}{\isacharunderscore}\ {\isasymin}\ set\ l{\isacharunderscore}{\isacharunderscore}\ {\isasymLongrightarrow}\ size\ x{\isacharunderscore}{\isacharunderscore}\ {\isacharless}\ Suc\ {\isacharparenleft}tree{\isacharunderscore}list{\isacharunderscore}size\ l{\isacharunderscore}{\isacharunderscore}{\isacharparenright}%
+{\isadigit{1}}{\isachardot}\ x\ {\isasymin}\ set\ l\ {\isasymLongrightarrow}\ size\ x\ {\isacharless}\ Suc\ {\isacharparenleft}tree{\isacharunderscore}list{\isacharunderscore}size\ l{\isacharparenright}%
\end{isabelle}

We are lacking a property about the function \isa{tree{\isacharunderscore}list{\isacharunderscore}size}, which was generated automatically at the
@@ -1866,8 +1865,7 @@
it, by induction.%
\end{isamarkuptxt}%
\isamarkuptrue%
-\ \ \ \ \isacommand{oops}\isamarkupfalse%
-%
+\ \ \ \ %
\endisatagproof
{\isafoldproof}%
%
@@ -1875,7 +1873,6 @@
%
\endisadelimproof
\isanewline
-\isanewline
\ \ \isacommand{lemma}\isamarkupfalse%
\ tree{\isacharunderscore}list{\isacharunderscore}size{\isacharbrackleft}simp{\isacharbrackright}{\isacharcolon}\ {\isachardoublequoteopen}x\ {\isasymin}\ set\ l\ {\isasymLongrightarrow}\ size\ x\ {\isacharless}\ Suc\ {\isacharparenleft}tree{\isacharunderscore}list{\isacharunderscore}size\ l{\isacharparenright}{\isachardoublequoteclose}\isanewline
%
@@ -1936,7 +1933,7 @@

Usually, one such congruence rule is
needed for each higher-order construct that is used when defining
-  new functions. In fact, even basic functions like \isa{If} and \isa{Let} are handeled by this mechanism. The congruence
+  new functions. In fact, even basic functions like \isa{If} and \isa{Let} are handled by this mechanism. The congruence
rule for \isa{If} states that the \isa{then} branch is only
relevant if the condition is true, and the \isa{else} branch only if it
is false:
@@ -1949,34 +1946,97 @@
Congruence rules can be added to the
function package by giving them the \isa{fundef{\isacharunderscore}cong} attribute.

-  Isabelle comes with predefined congruence rules for most of the
-  definitions.
-  But if you define your own higher-order constructs, you will have to
+  The constructs that are predefined in Isabelle, usually
+  come with the respective congruence rules.
+  But if you define your own higher-order functions, you will have to
come up with the congruence rules yourself, if you want to use your
-  functions in recursive definitions. Since the structure of
-  congruence rules is a little unintuitive, here are some exercises:%
+  functions in recursive definitions.%
\end{isamarkuptext}%
\isamarkuptrue%
%
+\isamarkupsubsection{Congruence Rules and Evaluation Order%
+}
+\isamarkuptrue%
+%
\begin{isamarkuptext}%
-\begin{exercise}
-    Find a suitable congruence rule for the following function which
-  maps only over the even numbers in a list:
+Higher order logic differs from functional programming languages in
+  that it has no built-in notion of evaluation order. A program is
+  just a set of equations, and it is not specified how they must be
+  evaluated.
+
+  However for the purpose of function definition, we must talk about
+  evaluation order implicitly, when we reason about termination.
+  Congruence rules express that a certain evaluation order is
+  consistent with the logical definition.
+
+  Consider the following function.%
+\end{isamarkuptext}%
+\isamarkuptrue%
+\isacommand{function}\isamarkupfalse%
+\ f\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequoteopen}nat\ {\isasymRightarrow}\ bool{\isachardoublequoteclose}\isanewline
+\isakeyword{where}\isanewline
+\ \ {\isachardoublequoteopen}f\ n\ {\isacharequal}\ {\isacharparenleft}n\ {\isacharequal}\ {\isadigit{0}}\ {\isasymor}\ f\ {\isacharparenleft}n\ {\isacharminus}\ {\isadigit{1}}{\isacharparenright}{\isacharparenright}{\isachardoublequoteclose}%
+\isadelimproof
+%
+\endisadelimproof
+%
+\isatagproof
+%
+\endisatagproof
+{\isafoldproof}%
+%
+\isadelimproof
+%
+\endisadelimproof
+%
+\begin{isamarkuptext}%
+As given above, the definition fails. The default configuration
+  specifies no congruence rule for disjunction. We have to add a
+  congruence rule that specifies left-to-right evaluation order:
+
+  \vspace{1ex}
+  \noindent \isa{{\isasymlbrakk}{\isacharquery}P\ {\isacharequal}\ {\isacharquery}P{\isacharprime}{\isacharsemicolon}\ {\isasymnot}\ {\isacharquery}P{\isacharprime}\ {\isasymLongrightarrow}\ {\isacharquery}Q\ {\isacharequal}\ {\isacharquery}Q{\isacharprime}{\isasymrbrakk}\ {\isasymLongrightarrow}\ {\isacharparenleft}{\isacharquery}P\ {\isasymor}\ {\isacharquery}Q{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}{\isacharquery}P{\isacharprime}\ {\isasymor}\ {\isacharquery}Q{\isacharprime}{\isacharparenright}}\hfill(\isa{disj{\isacharunderscore}cong})
+  \vspace{1ex}

-  \begin{isabelle}%
-mapeven\ {\isacharquery}f\ {\isacharbrackleft}{\isacharbrackright}\ {\isacharequal}\ {\isacharbrackleft}{\isacharbrackright}\isasep\isanewline%
-mapeven\ {\isacharquery}f\ {\isacharparenleft}{\isacharquery}x\ {\isacharhash}\ {\isacharquery}xs{\isacharparenright}\ {\isacharequal}\isanewline
-{\isacharparenleft}if\ {\isacharquery}x\ mod\ {\isadigit{2}}\ {\isacharequal}\ {\isadigit{0}}\ then\ {\isacharquery}f\ {\isacharquery}x\ {\isacharhash}\ mapeven\ {\isacharquery}f\ {\isacharquery}xs\ else\ {\isacharquery}x\ {\isacharhash}\ mapeven\ {\isacharquery}f\ {\isacharquery}xs{\isacharparenright}%
-\end{isabelle}
-  \end{exercise}
-
-  \begin{exercise}
-  Try what happens if the congruence rule for \isa{If} is
-  disabled by declaring \isa{if{\isacharunderscore}cong{\isacharbrackleft}fundef{\isacharunderscore}cong\ del{\isacharbrackright}}?
-  \end{exercise}
+  Now the definition works without problems. Note how the termination
+  proof depends on the extra condition that we get from the congruence
+  rule.

-  Note that in some cases there is no \qt{best} congruence rule.
-  \fixme{}%
+  However, as evaluation is not a hard-wired concept, we
+  could just turn everything around by declaring a different
+  congruence rule. Then we can make the reverse definition:%
+\end{isamarkuptext}%
+\isamarkuptrue%
+\isacommand{lemma}\isamarkupfalse%
+\ disj{\isacharunderscore}cong{\isadigit{2}}{\isacharbrackleft}fundef{\isacharunderscore}cong{\isacharbrackright}{\isacharcolon}\ \isanewline
+\ \ {\isachardoublequoteopen}{\isacharparenleft}{\isasymnot}\ Q{\isacharprime}\ {\isasymLongrightarrow}\ P\ {\isacharequal}\ P{\isacharprime}{\isacharparenright}\ {\isasymLongrightarrow}\ {\isacharparenleft}Q\ {\isacharequal}\ Q{\isacharprime}{\isacharparenright}\ {\isasymLongrightarrow}\ {\isacharparenleft}P\ {\isasymor}\ Q{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}P{\isacharprime}\ {\isasymor}\ Q{\isacharprime}{\isacharparenright}{\isachardoublequoteclose}\isanewline
+%
+\isadelimproof
+\ \ %
+\endisadelimproof
+%
+\isatagproof
+\isacommand{by}\isamarkupfalse%
+\ blast%
+\endisatagproof
+{\isafoldproof}%
+%
+\isadelimproof
+\isanewline
+%
+\endisadelimproof
+\isanewline
+\isacommand{fun}\isamarkupfalse%
+\ f{\isacharprime}\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequoteopen}nat\ {\isasymRightarrow}\ bool{\isachardoublequoteclose}\isanewline
+\isakeyword{where}\isanewline
+\ \ {\isachardoublequoteopen}f{\isacharprime}\ n\ {\isacharequal}\ {\isacharparenleft}f{\isacharprime}\ {\isacharparenleft}n\ {\isacharminus}\ {\isadigit{1}}{\isacharparenright}\ {\isasymor}\ n\ {\isacharequal}\ {\isadigit{0}}{\isacharparenright}{\isachardoublequoteclose}%
+\begin{isamarkuptext}%
+\noindent These examples show that, in general, there is no \qt{best} set of
+  congruence rules.
+
+  However, such tweaking should rarely be necessary in
+  practice, as most of the time, the default set of congruence rules
+  works well.%
\end{isamarkuptext}%
\isamarkuptrue%
%
--- a/doc-src/IsarAdvanced/Functions/Thy/document/session.tex	Thu Jul 12 11:43:17 2007 +0200
+++ b/doc-src/IsarAdvanced/Functions/Thy/document/session.tex	Thu Jul 12 12:20:39 2007 +0200
@@ -1,7 +1,5 @@
\input{Functions.tex}

-\input{Predefined_Congs.tex}
-
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "root"
--- a/doc-src/IsarAdvanced/Functions/functions.tex	Thu Jul 12 11:43:17 2007 +0200
+++ b/doc-src/IsarAdvanced/Functions/functions.tex	Thu Jul 12 12:20:39 2007 +0200
@@ -67,6 +67,7 @@

\begin{document}

+\date{\ \\}
\maketitle

\begin{abstract}
@@ -74,7 +75,7 @@
which provides general recursive function definitions for Isabelle/HOL.
We start with very simple examples and then gradually move on to more
advanced topics such as manual termination proofs, nested recursion,
-	partiality and congruence rules.
+	partiality, tail recursion and congruence rules.
\end{abstract}

%\thispagestyle{empty}\clearpage
@@ -84,7 +85,7 @@

\input{intro.tex}
\input{Thy/document/Functions.tex}
-\input{conclusion.tex}
+%\input{conclusion.tex}

\begingroup
%\tocentry{\bibname}
--- a/doc-src/IsarAdvanced/Functions/intro.tex	Thu Jul 12 11:43:17 2007 +0200
+++ b/doc-src/IsarAdvanced/Functions/intro.tex	Thu Jul 12 12:20:39 2007 +0200
@@ -1,16 +1,37 @@
\section{Introduction}

-In the upcomung release of Isabelle 2007, new facilities for recursive
-function definitions \cite{krauss2006} will be available.
+In the upcoming release of Isabelle 2007, new facilities for recursive
+function definitions \cite{krauss2006} will be available, providing
+better support for general recursive definitions than previous
+packages did.  But despite all tool support, function definitions can
+sometimes be a difficult thing.

This tutorial is an example-guided introduction to the practical use
-of the package. We assume that you have mastered the basic concepts of
-Isabelle/HOL and are able to write basic specifications and
-proofs. To start out with Isabelle in general, you should read the
-tutorial \cite{isa-tutorial}.
+of the package and related tools. It should help you get started with
+defining functions quickly. For the more difficult definitions we will
+discuss what problems can arise, and how they can be solved.
+
+We assume that you have mastered the basics of Isabelle/HOL
+and are able to write basic specifications and proofs. To start out
+with Isabelle in general, consult the Isabelle/HOL tutorial
+\cite{isa-tutorial}.
+
+

-% Definitional extension
+\paragraph{Structure of this tutorial.}
+Section 2 introduces the syntax and basic operation of the \cmd{fun}
+command, which provides full automation with reasonable default
+behavior.  The impatient reader might want to stop after that
+section, and consult the remaining sections only when needed.
+Section 3 introduces the more verbose \cmd{function} command which
+gives fine-grained control to the user. This form should be used
+whenever the short form fails.
+After that we discuss different issues that are more specialized:
+termination, mutual and nested recursion, partiality, pattern matching
+and others.

+
+\paragraph{Some background.}
Following the LCF tradition, the package is realized as a definitional
extension: Recursive definitions are internally transformed into a
non-recursive form, such that the function can be defined using
@@ -18,7 +39,7 @@
derived from the primitive definition.  This is a complex task, but it
is fully automated and mostly transparent to the user. Definitional
extensions are valuable because they are conservative by construction:
-The new concept of general wellfounded recursion is completely reduced
+The \qt{new} concept of general wellfounded recursion is completely reduced
to existing principles.