src/Doc/Tutorial/Fun/fun0.thy
changeset 67406 23307fd33906
parent 62392 747d36865c2c
child 69505 cc2d676d5395
equal deleted inserted replaced
67405:e9ab4ad7bd15 67406:23307fd33906
     1 (*<*)
     1 (*<*)
     2 theory fun0 imports Main begin
     2 theory fun0 imports Main begin
     3 (*>*)
     3 (*>*)
     4 
     4 
     5 text{*
     5 text\<open>
     6 \subsection{Definition}
     6 \subsection{Definition}
     7 \label{sec:fun-examples}
     7 \label{sec:fun-examples}
     8 
     8 
     9 Here is a simple example, the \rmindex{Fibonacci function}:
     9 Here is a simple example, the \rmindex{Fibonacci function}:
    10 *}
    10 \<close>
    11 
    11 
    12 fun fib :: "nat \<Rightarrow> nat" where
    12 fun fib :: "nat \<Rightarrow> nat" where
    13 "fib 0 = 0" |
    13 "fib 0 = 0" |
    14 "fib (Suc 0) = 1" |
    14 "fib (Suc 0) = 1" |
    15 "fib (Suc(Suc x)) = fib x + fib (Suc x)"
    15 "fib (Suc(Suc x)) = fib x + fib (Suc x)"
    16 
    16 
    17 text{*\noindent
    17 text\<open>\noindent
    18 This resembles ordinary functional programming languages. Note the obligatory
    18 This resembles ordinary functional programming languages. Note the obligatory
    19 \isacommand{where} and \isa{|}. Command \isacommand{fun} declares and
    19 \isacommand{where} and \isa{|}. Command \isacommand{fun} declares and
    20 defines the function in one go. Isabelle establishes termination automatically
    20 defines the function in one go. Isabelle establishes termination automatically
    21 because @{const fib}'s argument decreases in every recursive call.
    21 because @{const fib}'s argument decreases in every recursive call.
    22 
    22 
    23 Slightly more interesting is the insertion of a fixed element
    23 Slightly more interesting is the insertion of a fixed element
    24 between any two elements of a list:
    24 between any two elements of a list:
    25 *}
    25 \<close>
    26 
    26 
    27 fun sep :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    27 fun sep :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    28 "sep a []     = []" |
    28 "sep a []     = []" |
    29 "sep a [x]    = [x]" |
    29 "sep a [x]    = [x]" |
    30 "sep a (x#y#zs) = x # a # sep a (y#zs)"
    30 "sep a (x#y#zs) = x # a # sep a (y#zs)"
    31 
    31 
    32 text{*\noindent
    32 text\<open>\noindent
    33 This time the length of the list decreases with the
    33 This time the length of the list decreases with the
    34 recursive call; the first argument is irrelevant for termination.
    34 recursive call; the first argument is irrelevant for termination.
    35 
    35 
    36 Pattern matching\index{pattern matching!and \isacommand{fun}}
    36 Pattern matching\index{pattern matching!and \isacommand{fun}}
    37 need not be exhaustive and may employ wildcards:
    37 need not be exhaustive and may employ wildcards:
    38 *}
    38 \<close>
    39 
    39 
    40 fun last :: "'a list \<Rightarrow> 'a" where
    40 fun last :: "'a list \<Rightarrow> 'a" where
    41 "last [x]      = x" |
    41 "last [x]      = x" |
    42 "last (_#y#zs) = last (y#zs)"
    42 "last (_#y#zs) = last (y#zs)"
    43 
    43 
    44 text{*
    44 text\<open>
    45 Overlapping patterns are disambiguated by taking the order of equations into
    45 Overlapping patterns are disambiguated by taking the order of equations into
    46 account, just as in functional programming:
    46 account, just as in functional programming:
    47 *}
    47 \<close>
    48 
    48 
    49 fun sep1 :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    49 fun sep1 :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
    50 "sep1 a (x#y#zs) = x # a # sep1 a (y#zs)" |
    50 "sep1 a (x#y#zs) = x # a # sep1 a (y#zs)" |
    51 "sep1 _ xs       = xs"
    51 "sep1 _ xs       = xs"
    52 
    52 
    53 text{*\noindent
    53 text\<open>\noindent
    54 To guarantee that the second equation can only be applied if the first
    54 To guarantee that the second equation can only be applied if the first
    55 one does not match, Isabelle internally replaces the second equation
    55 one does not match, Isabelle internally replaces the second equation
    56 by the two possibilities that are left: @{prop"sep1 a [] = []"} and
    56 by the two possibilities that are left: @{prop"sep1 a [] = []"} and
    57 @{prop"sep1 a [x] = [x]"}.  Thus the functions @{const sep} and
    57 @{prop"sep1 a [x] = [x]"}.  Thus the functions @{const sep} and
    58 @{const sep1} are identical.
    58 @{const sep1} are identical.
    59 
    59 
    60 Because of its pattern matching syntax, \isacommand{fun} is also useful
    60 Because of its pattern matching syntax, \isacommand{fun} is also useful
    61 for the definition of non-recursive functions:
    61 for the definition of non-recursive functions:
    62 *}
    62 \<close>
    63 
    63 
    64 fun swap12 :: "'a list \<Rightarrow> 'a list" where
    64 fun swap12 :: "'a list \<Rightarrow> 'a list" where
    65 "swap12 (x#y#zs) = y#x#zs" |
    65 "swap12 (x#y#zs) = y#x#zs" |
    66 "swap12 zs       = zs"
    66 "swap12 zs       = zs"
    67 
    67 
    68 text{*
    68 text\<open>
    69 After a function~$f$ has been defined via \isacommand{fun},
    69 After a function~$f$ has been defined via \isacommand{fun},
    70 its defining equations (or variants derived from them) are available
    70 its defining equations (or variants derived from them) are available
    71 under the name $f$@{text".simps"} as theorems.
    71 under the name $f$@{text".simps"} as theorems.
    72 For example, look (via \isacommand{thm}) at
    72 For example, look (via \isacommand{thm}) at
    73 @{thm[source]sep.simps} and @{thm[source]sep1.simps} to see that they define
    73 @{thm[source]sep.simps} and @{thm[source]sep1.simps} to see that they define
    85 recursive call.
    85 recursive call.
    86 
    86 
    87 More generally, \isacommand{fun} allows any \emph{lexicographic
    87 More generally, \isacommand{fun} allows any \emph{lexicographic
    88 combination} of size measures in case there are multiple
    88 combination} of size measures in case there are multiple
    89 arguments. For example, the following version of \rmindex{Ackermann's
    89 arguments. For example, the following version of \rmindex{Ackermann's
    90 function} is accepted: *}
    90 function} is accepted:\<close>
    91 
    91 
    92 fun ack2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
    92 fun ack2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
    93 "ack2 n 0 = Suc n" |
    93 "ack2 n 0 = Suc n" |
    94 "ack2 0 (Suc m) = ack2 (Suc 0) m" |
    94 "ack2 0 (Suc m) = ack2 (Suc 0) m" |
    95 "ack2 (Suc n) (Suc m) = ack2 (ack2 n (Suc m)) m"
    95 "ack2 (Suc n) (Suc m) = ack2 (ack2 n (Suc m)) m"
    96 
    96 
    97 text{* The order of arguments has no influence on whether
    97 text\<open>The order of arguments has no influence on whether
    98 \isacommand{fun} can prove termination of a function. For more details
    98 \isacommand{fun} can prove termination of a function. For more details
    99 see elsewhere~@{cite bulwahnKN07}.
    99 see elsewhere~@{cite bulwahnKN07}.
   100 
   100 
   101 \subsection{Simplification}
   101 \subsection{Simplification}
   102 \label{sec:fun-simplification}
   102 \label{sec:fun-simplification}
   106 In most cases this works fine, but there is a subtle
   106 In most cases this works fine, but there is a subtle
   107 problem that must be mentioned: simplification may not
   107 problem that must be mentioned: simplification may not
   108 terminate because of automatic splitting of @{text "if"}.
   108 terminate because of automatic splitting of @{text "if"}.
   109 \index{*if expressions!splitting of}
   109 \index{*if expressions!splitting of}
   110 Let us look at an example:
   110 Let us look at an example:
   111 *}
   111 \<close>
   112 
   112 
   113 fun gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
   113 fun gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
   114 "gcd m n = (if n=0 then m else gcd n (m mod n))"
   114 "gcd m n = (if n=0 then m else gcd n (m mod n))"
   115 
   115 
   116 text{*\noindent
   116 text\<open>\noindent
   117 The second argument decreases with each recursive call.
   117 The second argument decreases with each recursive call.
   118 The termination condition
   118 The termination condition
   119 @{prop[display]"n ~= (0::nat) ==> m mod n < n"}
   119 @{prop[display]"n ~= (0::nat) ==> m mod n < n"}
   120 is proved automatically because it is already present as a lemma in
   120 is proved automatically because it is already present as a lemma in
   121 HOL\@.  Thus the recursion equation becomes a simplification
   121 HOL\@.  Thus the recursion equation becomes a simplification
   143 @{text "if"} is involved.
   143 @{text "if"} is involved.
   144 
   144 
   145 If possible, the definition should be given by pattern matching on the left
   145 If possible, the definition should be given by pattern matching on the left
   146 rather than @{text "if"} on the right. In the case of @{term gcd} the
   146 rather than @{text "if"} on the right. In the case of @{term gcd} the
   147 following alternative definition suggests itself:
   147 following alternative definition suggests itself:
   148 *}
   148 \<close>
   149 
   149 
   150 fun gcd1 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
   150 fun gcd1 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
   151 "gcd1 m 0 = m" |
   151 "gcd1 m 0 = m" |
   152 "gcd1 m n = gcd1 n (m mod n)"
   152 "gcd1 m n = gcd1 n (m mod n)"
   153 
   153 
   154 text{*\noindent
   154 text\<open>\noindent
   155 The order of equations is important: it hides the side condition
   155 The order of equations is important: it hides the side condition
   156 @{prop"n ~= (0::nat)"}.  Unfortunately, not all conditionals can be
   156 @{prop"n ~= (0::nat)"}.  Unfortunately, not all conditionals can be
   157 expressed by pattern matching.
   157 expressed by pattern matching.
   158 
   158 
   159 A simple alternative is to replace @{text "if"} by @{text case}, 
   159 A simple alternative is to replace @{text "if"} by @{text case}, 
   160 which is also available for @{typ bool} and is not split automatically:
   160 which is also available for @{typ bool} and is not split automatically:
   161 *}
   161 \<close>
   162 
   162 
   163 fun gcd2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
   163 fun gcd2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
   164 "gcd2 m n = (case n=0 of True \<Rightarrow> m | False \<Rightarrow> gcd2 n (m mod n))"
   164 "gcd2 m n = (case n=0 of True \<Rightarrow> m | False \<Rightarrow> gcd2 n (m mod n))"
   165 
   165 
   166 text{*\noindent
   166 text\<open>\noindent
   167 This is probably the neatest solution next to pattern matching, and it is
   167 This is probably the neatest solution next to pattern matching, and it is
   168 always available.
   168 always available.
   169 
   169 
   170 A final alternative is to replace the offending simplification rules by
   170 A final alternative is to replace the offending simplification rules by
   171 derived conditional ones. For @{term gcd} it means we have to prove
   171 derived conditional ones. For @{term gcd} it means we have to prove
   172 these lemmas:
   172 these lemmas:
   173 *}
   173 \<close>
   174 
   174 
   175 lemma [simp]: "gcd m 0 = m"
   175 lemma [simp]: "gcd m 0 = m"
   176 apply(simp)
   176 apply(simp)
   177 done
   177 done
   178 
   178 
   179 lemma [simp]: "n \<noteq> 0 \<Longrightarrow> gcd m n = gcd n (m mod n)"
   179 lemma [simp]: "n \<noteq> 0 \<Longrightarrow> gcd m n = gcd n (m mod n)"
   180 apply(simp)
   180 apply(simp)
   181 done
   181 done
   182 
   182 
   183 text{*\noindent
   183 text\<open>\noindent
   184 Simplification terminates for these proofs because the condition of the @{text
   184 Simplification terminates for these proofs because the condition of the @{text
   185 "if"} simplifies to @{term True} or @{term False}.
   185 "if"} simplifies to @{term True} or @{term False}.
   186 Now we can disable the original simplification rule:
   186 Now we can disable the original simplification rule:
   187 *}
   187 \<close>
   188 
   188 
   189 declare gcd.simps [simp del]
   189 declare gcd.simps [simp del]
   190 
   190 
   191 text{*
   191 text\<open>
   192 \index{induction!recursion|(}
   192 \index{induction!recursion|(}
   193 \index{recursion induction|(}
   193 \index{recursion induction|(}
   194 
   194 
   195 \subsection{Induction}
   195 \subsection{Induction}
   196 \label{sec:fun-induction}
   196 \label{sec:fun-induction}
   205 \textbf{recursion induction}. Roughly speaking, it
   205 \textbf{recursion induction}. Roughly speaking, it
   206 requires you to prove for each \isacommand{fun} equation that the property
   206 requires you to prove for each \isacommand{fun} equation that the property
   207 you are trying to establish holds for the left-hand side provided it holds
   207 you are trying to establish holds for the left-hand side provided it holds
   208 for all recursive calls on the right-hand side. Here is a simple example
   208 for all recursive calls on the right-hand side. Here is a simple example
   209 involving the predefined @{term"map"} functional on lists:
   209 involving the predefined @{term"map"} functional on lists:
   210 *}
   210 \<close>
   211 
   211 
   212 lemma "map f (sep x xs) = sep (f x) (map f xs)"
   212 lemma "map f (sep x xs) = sep (f x) (map f xs)"
   213 
   213 
   214 txt{*\noindent
   214 txt\<open>\noindent
   215 Note that @{term"map f xs"}
   215 Note that @{term"map f xs"}
   216 is the result of applying @{term"f"} to all elements of @{term"xs"}. We prove
   216 is the result of applying @{term"f"} to all elements of @{term"xs"}. We prove
   217 this lemma by recursion induction over @{term"sep"}:
   217 this lemma by recursion induction over @{term"sep"}:
   218 *}
   218 \<close>
   219 
   219 
   220 apply(induct_tac x xs rule: sep.induct)
   220 apply(induct_tac x xs rule: sep.induct)
   221 
   221 
   222 txt{*\noindent
   222 txt\<open>\noindent
   223 The resulting proof state has three subgoals corresponding to the three
   223 The resulting proof state has three subgoals corresponding to the three
   224 clauses for @{term"sep"}:
   224 clauses for @{term"sep"}:
   225 @{subgoals[display,indent=0]}
   225 @{subgoals[display,indent=0]}
   226 The rest is pure simplification:
   226 The rest is pure simplification:
   227 *}
   227 \<close>
   228 
   228 
   229 apply simp_all
   229 apply simp_all
   230 done
   230 done
   231 
   231 
   232 text{*\noindent The proof goes smoothly because the induction rule
   232 text\<open>\noindent The proof goes smoothly because the induction rule
   233 follows the recursion of @{const sep}.  Try proving the above lemma by
   233 follows the recursion of @{const sep}.  Try proving the above lemma by
   234 structural induction, and you find that you need an additional case
   234 structural induction, and you find that you need an additional case
   235 distinction.
   235 distinction.
   236 
   236 
   237 In general, the format of invoking recursion induction is
   237 In general, the format of invoking recursion induction is
   253 empty list, the singleton list, and the list with at least two elements.
   253 empty list, the singleton list, and the list with at least two elements.
   254 The final case has an induction hypothesis:  you may assume that @{term"P"}
   254 The final case has an induction hypothesis:  you may assume that @{term"P"}
   255 holds for the tail of that list.
   255 holds for the tail of that list.
   256 \index{induction!recursion|)}
   256 \index{induction!recursion|)}
   257 \index{recursion induction|)}
   257 \index{recursion induction|)}
   258 *}
   258 \<close>
   259 (*<*)
   259 (*<*)
   260 end
   260 end
   261 (*>*)
   261 (*>*)