src/HOL/ex/Fundefs.thy
changeset 61343 5b5656a63bd6
parent 58889 5b7a9633cfa8
child 61933 cf58b5b794b2
equal deleted inserted replaced
61342:b98cd131e2b5 61343:5b5656a63bd6
     1 (*  Title:      HOL/ex/Fundefs.thy
     1 (*  Title:      HOL/ex/Fundefs.thy
     2     Author:     Alexander Krauss, TU Muenchen
     2     Author:     Alexander Krauss, TU Muenchen
     3 *)
     3 *)
     4 
     4 
     5 section {* Examples of function definitions *}
     5 section \<open>Examples of function definitions\<close>
     6 
     6 
     7 theory Fundefs 
     7 theory Fundefs 
     8 imports Main "~~/src/HOL/Library/Monad_Syntax"
     8 imports Main "~~/src/HOL/Library/Monad_Syntax"
     9 begin
     9 begin
    10 
    10 
    11 subsection {* Very basic *}
    11 subsection \<open>Very basic\<close>
    12 
    12 
    13 fun fib :: "nat \<Rightarrow> nat"
    13 fun fib :: "nat \<Rightarrow> nat"
    14 where
    14 where
    15   "fib 0 = 1"
    15   "fib 0 = 1"
    16 | "fib (Suc 0) = 1"
    16 | "fib (Suc 0) = 1"
    17 | "fib (Suc (Suc n)) = fib n + fib (Suc n)"
    17 | "fib (Suc (Suc n)) = fib n + fib (Suc n)"
    18 
    18 
    19 text {* partial simp and induction rules: *}
    19 text \<open>partial simp and induction rules:\<close>
    20 thm fib.psimps
    20 thm fib.psimps
    21 thm fib.pinduct
    21 thm fib.pinduct
    22 
    22 
    23 text {* There is also a cases rule to distinguish cases along the definition *}
    23 text \<open>There is also a cases rule to distinguish cases along the definition\<close>
    24 thm fib.cases
    24 thm fib.cases
    25 
    25 
    26 
    26 
    27 text {* total simp and induction rules: *}
    27 text \<open>total simp and induction rules:\<close>
    28 thm fib.simps
    28 thm fib.simps
    29 thm fib.induct
    29 thm fib.induct
    30 
    30 
    31 text {* elimination rules *}
    31 text \<open>elimination rules\<close>
    32 thm fib.elims
    32 thm fib.elims
    33 
    33 
    34 subsection {* Currying *}
    34 subsection \<open>Currying\<close>
    35 
    35 
    36 fun add
    36 fun add
    37 where
    37 where
    38   "add 0 y = y"
    38   "add 0 y = y"
    39 | "add (Suc x) y = Suc (add x y)"
    39 | "add (Suc x) y = Suc (add x y)"
    40 
    40 
    41 thm add.simps
    41 thm add.simps
    42 thm add.induct -- {* Note the curried induction predicate *}
    42 thm add.induct -- \<open>Note the curried induction predicate\<close>
    43 
    43 
    44 
    44 
    45 subsection {* Nested recursion *}
    45 subsection \<open>Nested recursion\<close>
    46 
    46 
    47 function nz 
    47 function nz 
    48 where
    48 where
    49   "nz 0 = 0"
    49   "nz 0 = 0"
    50 | "nz (Suc x) = nz (nz x)"
    50 | "nz (Suc x) = nz (nz x)"
    51 by pat_completeness auto
    51 by pat_completeness auto
    52 
    52 
    53 lemma nz_is_zero: -- {* A lemma we need to prove termination *}
    53 lemma nz_is_zero: -- \<open>A lemma we need to prove termination\<close>
    54   assumes trm: "nz_dom x"
    54   assumes trm: "nz_dom x"
    55   shows "nz x = 0"
    55   shows "nz x = 0"
    56 using trm
    56 using trm
    57 by induct (auto simp: nz.psimps)
    57 by induct (auto simp: nz.psimps)
    58 
    58 
    60   by (relation "less_than") (auto simp:nz_is_zero)
    60   by (relation "less_than") (auto simp:nz_is_zero)
    61 
    61 
    62 thm nz.simps
    62 thm nz.simps
    63 thm nz.induct
    63 thm nz.induct
    64 
    64 
    65 text {* Here comes McCarthy's 91-function *}
    65 text \<open>Here comes McCarthy's 91-function\<close>
    66 
    66 
    67 
    67 
    68 function f91 :: "nat => nat"
    68 function f91 :: "nat => nat"
    69 where
    69 where
    70   "f91 n = (if 100 < n then n - 10 else f91 (f91 (n + 11)))"
    70   "f91 n = (if 100 < n then n - 10 else f91 (f91 (n + 11)))"
    84   fix n::nat assume "~ 100 < n" (* Inner call *)
    84   fix n::nat assume "~ 100 < n" (* Inner call *)
    85   thus "(n + 11, n) : ?R" by simp
    85   thus "(n + 11, n) : ?R" by simp
    86 
    86 
    87   assume inner_trm: "f91_dom (n + 11)" (* Outer call *)
    87   assume inner_trm: "f91_dom (n + 11)" (* Outer call *)
    88   with f91_estimate have "n + 11 < f91 (n + 11) + 11" .
    88   with f91_estimate have "n + 11 < f91 (n + 11) + 11" .
    89   with `~ 100 < n` show "(f91 (n + 11), n) : ?R" by simp 
    89   with \<open>~ 100 < n\<close> show "(f91 (n + 11), n) : ?R" by simp 
    90 qed
    90 qed
    91 
    91 
    92 text{* Now trivial (even though it does not belong here): *}
    92 text\<open>Now trivial (even though it does not belong here):\<close>
    93 lemma "f91 n = (if 100 < n then n - 10 else 91)"
    93 lemma "f91 n = (if 100 < n then n - 10 else 91)"
    94 by (induct n rule:f91.induct) auto
    94 by (induct n rule:f91.induct) auto
    95 
    95 
    96 
    96 
    97 subsection {* More general patterns *}
    97 subsection \<open>More general patterns\<close>
    98 
    98 
    99 subsubsection {* Overlapping patterns *}
    99 subsubsection \<open>Overlapping patterns\<close>
   100 
   100 
   101 text {* Currently, patterns must always be compatible with each other, since
   101 text \<open>Currently, patterns must always be compatible with each other, since
   102 no automatic splitting takes place. But the following definition of
   102 no automatic splitting takes place. But the following definition of
   103 gcd is ok, although patterns overlap: *}
   103 gcd is ok, although patterns overlap:\<close>
   104 
   104 
   105 fun gcd2 :: "nat \<Rightarrow> nat \<Rightarrow> nat"
   105 fun gcd2 :: "nat \<Rightarrow> nat \<Rightarrow> nat"
   106 where
   106 where
   107   "gcd2 x 0 = x"
   107   "gcd2 x 0 = x"
   108 | "gcd2 0 y = y"
   108 | "gcd2 0 y = y"
   110                                     else gcd2 (x - y) (Suc y))"
   110                                     else gcd2 (x - y) (Suc y))"
   111 
   111 
   112 thm gcd2.simps
   112 thm gcd2.simps
   113 thm gcd2.induct
   113 thm gcd2.induct
   114 
   114 
   115 subsubsection {* Guards *}
   115 subsubsection \<open>Guards\<close>
   116 
   116 
   117 text {* We can reformulate the above example using guarded patterns *}
   117 text \<open>We can reformulate the above example using guarded patterns\<close>
   118 
   118 
   119 function gcd3 :: "nat \<Rightarrow> nat \<Rightarrow> nat"
   119 function gcd3 :: "nat \<Rightarrow> nat \<Rightarrow> nat"
   120 where
   120 where
   121   "gcd3 x 0 = x"
   121   "gcd3 x 0 = x"
   122 | "gcd3 0 y = y"
   122 | "gcd3 0 y = y"
   129 
   129 
   130 thm gcd3.simps
   130 thm gcd3.simps
   131 thm gcd3.induct
   131 thm gcd3.induct
   132 
   132 
   133 
   133 
   134 text {* General patterns allow even strange definitions: *}
   134 text \<open>General patterns allow even strange definitions:\<close>
   135 
   135 
   136 function ev :: "nat \<Rightarrow> bool"
   136 function ev :: "nat \<Rightarrow> bool"
   137 where
   137 where
   138   "ev (2 * n) = True"
   138   "ev (2 * n) = True"
   139 | "ev (2 * n + 1) = False"
   139 | "ev (2 * n + 1) = False"
   140 proof -  -- {* completeness is more difficult here \dots *}
   140 proof -  -- \<open>completeness is more difficult here \dots\<close>
   141   fix P :: bool
   141   fix P :: bool
   142     and x :: nat
   142     and x :: nat
   143   assume c1: "\<And>n. x = 2 * n \<Longrightarrow> P"
   143   assume c1: "\<And>n. x = 2 * n \<Longrightarrow> P"
   144     and c2: "\<And>n. x = 2 * n + 1 \<Longrightarrow> P"
   144     and c2: "\<And>n. x = 2 * n + 1 \<Longrightarrow> P"
   145   have divmod: "x = 2 * (x div 2) + (x mod 2)" by auto
   145   have divmod: "x = 2 * (x div 2) + (x mod 2)" by auto
   152     assume "x mod 2 \<noteq> 0"
   152     assume "x mod 2 \<noteq> 0"
   153     hence "x mod 2 = 1" by simp
   153     hence "x mod 2 = 1" by simp
   154     with divmod have "x = 2 * (x div 2) + 1" by simp
   154     with divmod have "x = 2 * (x div 2) + 1" by simp
   155     with c2 show "P" .
   155     with c2 show "P" .
   156   qed
   156   qed
   157 qed presburger+ -- {* solve compatibility with presburger *} 
   157 qed presburger+ -- \<open>solve compatibility with presburger\<close> 
   158 termination by lexicographic_order
   158 termination by lexicographic_order
   159 
   159 
   160 thm ev.simps
   160 thm ev.simps
   161 thm ev.induct
   161 thm ev.induct
   162 thm ev.cases
   162 thm ev.cases
   163 
   163 
   164 
   164 
   165 subsection {* Mutual Recursion *}
   165 subsection \<open>Mutual Recursion\<close>
   166 
   166 
   167 fun evn od :: "nat \<Rightarrow> bool"
   167 fun evn od :: "nat \<Rightarrow> bool"
   168 where
   168 where
   169   "evn 0 = True"
   169   "evn 0 = True"
   170 | "od 0 = False"
   170 | "od 0 = False"
   178 thm evn_od.termination
   178 thm evn_od.termination
   179 
   179 
   180 thm evn.elims
   180 thm evn.elims
   181 thm od.elims
   181 thm od.elims
   182 
   182 
   183 subsection {* Definitions in local contexts *}
   183 subsection \<open>Definitions in local contexts\<close>
   184 
   184 
   185 locale my_monoid = 
   185 locale my_monoid = 
   186 fixes opr :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
   186 fixes opr :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
   187   and un :: "'a"
   187   and un :: "'a"
   188 assumes assoc: "opr (opr x y) z = opr x (opr y z)"
   188 assumes assoc: "opr (opr x y) z = opr x (opr y z)"
   211 end
   211 end
   212 
   212 
   213 thm my_monoid.foldL.simps
   213 thm my_monoid.foldL.simps
   214 thm my_monoid.foldR_foldL
   214 thm my_monoid.foldR_foldL
   215 
   215 
   216 subsection {* @{text fun_cases} *}
   216 subsection \<open>@{text fun_cases}\<close>
   217 
   217 
   218 subsubsection {* Predecessor *}
   218 subsubsection \<open>Predecessor\<close>
   219 
   219 
   220 fun pred :: "nat \<Rightarrow> nat" where
   220 fun pred :: "nat \<Rightarrow> nat" where
   221 "pred 0 = 0" |
   221 "pred 0 = 0" |
   222 "pred (Suc n) = n"
   222 "pred (Suc n) = n"
   223 
   223 
   225 
   225 
   226 lemma assumes "pred x = y"
   226 lemma assumes "pred x = y"
   227 obtains "x = 0" "y = 0" | "n" where "x = Suc n" "y = n"
   227 obtains "x = 0" "y = 0" | "n" where "x = Suc n" "y = n"
   228 by (fact pred.elims[OF assms])
   228 by (fact pred.elims[OF assms])
   229 
   229 
   230 text {* If the predecessor of a number is 0, that number must be 0 or 1. *}
   230 text \<open>If the predecessor of a number is 0, that number must be 0 or 1.\<close>
   231 
   231 
   232 fun_cases pred0E[elim]: "pred n = 0"
   232 fun_cases pred0E[elim]: "pred n = 0"
   233 
   233 
   234 lemma "pred n = 0 \<Longrightarrow> n = 0 \<or> n = Suc 0"
   234 lemma "pred n = 0 \<Longrightarrow> n = 0 \<or> n = Suc 0"
   235 by (erule pred0E) metis+
   235 by (erule pred0E) metis+
   236 
   236 
   237 
   237 
   238 text {* Other expressions on the right-hand side also work, but whether the
   238 text \<open>Other expressions on the right-hand side also work, but whether the
   239         generated rule is useful depends on how well the simplifier can
   239         generated rule is useful depends on how well the simplifier can
   240         simplify it. This example works well: *}
   240         simplify it. This example works well:\<close>
   241 
   241 
   242 fun_cases pred42E[elim]: "pred n = 42"
   242 fun_cases pred42E[elim]: "pred n = 42"
   243 
   243 
   244 lemma "pred n = 42 \<Longrightarrow> n = 43"
   244 lemma "pred n = 42 \<Longrightarrow> n = 43"
   245 by (erule pred42E)
   245 by (erule pred42E)
   246 
   246 
   247 subsubsection {* List to option *}
   247 subsubsection \<open>List to option\<close>
   248 
   248 
   249 fun list_to_option :: "'a list \<Rightarrow> 'a option" where
   249 fun list_to_option :: "'a list \<Rightarrow> 'a option" where
   250 "list_to_option [x] = Some x" |
   250 "list_to_option [x] = Some x" |
   251 "list_to_option _ = None"
   251 "list_to_option _ = None"
   252 
   252 
   254       and list_to_option_SomeE: "list_to_option xs = Some x"
   254       and list_to_option_SomeE: "list_to_option xs = Some x"
   255 
   255 
   256 lemma "list_to_option xs = Some y \<Longrightarrow> xs = [y]"
   256 lemma "list_to_option xs = Some y \<Longrightarrow> xs = [y]"
   257 by (erule list_to_option_SomeE)
   257 by (erule list_to_option_SomeE)
   258 
   258 
   259 subsubsection {* Boolean Functions *}
   259 subsubsection \<open>Boolean Functions\<close>
   260 
   260 
   261 fun xor :: "bool \<Rightarrow> bool \<Rightarrow> bool" where
   261 fun xor :: "bool \<Rightarrow> bool \<Rightarrow> bool" where
   262 "xor False False = False" |
   262 "xor False False = False" |
   263 "xor True True = False" |
   263 "xor True True = False" |
   264 "xor _ _ = True"
   264 "xor _ _ = True"
   265 
   265 
   266 thm xor.elims
   266 thm xor.elims
   267 
   267 
   268 text {* @{text fun_cases} does not only recognise function equations, but also works with
   268 text \<open>@{text fun_cases} does not only recognise function equations, but also works with
   269    functions that return a boolean, e.g.: *}
   269    functions that return a boolean, e.g.:\<close>
   270 
   270 
   271 fun_cases xor_TrueE: "xor a b" and xor_FalseE: "\<not>xor a b"
   271 fun_cases xor_TrueE: "xor a b" and xor_FalseE: "\<not>xor a b"
   272 print_theorems
   272 print_theorems
   273 
   273 
   274 subsubsection {* Many parameters *}
   274 subsubsection \<open>Many parameters\<close>
   275 
   275 
   276 fun sum4 :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat" where
   276 fun sum4 :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat" where
   277 "sum4 a b c d = a + b + c + d"
   277 "sum4 a b c d = a + b + c + d"
   278 
   278 
   279 fun_cases sum40E: "sum4 a b c d = 0"
   279 fun_cases sum40E: "sum4 a b c d = 0"
   280 
   280 
   281 lemma "sum4 a b c d = 0 \<Longrightarrow> a = 0"
   281 lemma "sum4 a b c d = 0 \<Longrightarrow> a = 0"
   282 by (erule sum40E)
   282 by (erule sum40E)
   283 
   283 
   284 
   284 
   285 subsection {* Partial Function Definitions *}
   285 subsection \<open>Partial Function Definitions\<close>
   286 
   286 
   287 text {* Partial functions in the option monad: *}
   287 text \<open>Partial functions in the option monad:\<close>
   288 
   288 
   289 partial_function (option)
   289 partial_function (option)
   290   collatz :: "nat \<Rightarrow> nat list option"
   290   collatz :: "nat \<Rightarrow> nat list option"
   291 where
   291 where
   292   "collatz n =
   292   "collatz n =
   297 
   297 
   298 declare collatz.simps[code]
   298 declare collatz.simps[code]
   299 value "collatz 23"
   299 value "collatz 23"
   300 
   300 
   301 
   301 
   302 text {* Tail-recursive functions: *}
   302 text \<open>Tail-recursive functions:\<close>
   303 
   303 
   304 partial_function (tailrec) fixpoint :: "('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a"
   304 partial_function (tailrec) fixpoint :: "('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a"
   305 where
   305 where
   306   "fixpoint f x = (if f x = x then x else fixpoint f (f x))"
   306   "fixpoint f x = (if f x = x then x else fixpoint f (f x))"
   307 
   307 
   308 
   308 
   309 subsection {* Regression tests *}
   309 subsection \<open>Regression tests\<close>
   310 
   310 
   311 text {* The following examples mainly serve as tests for the 
   311 text \<open>The following examples mainly serve as tests for the 
   312   function package *}
   312   function package\<close>
   313 
   313 
   314 fun listlen :: "'a list \<Rightarrow> nat"
   314 fun listlen :: "'a list \<Rightarrow> nat"
   315 where
   315 where
   316   "listlen [] = 0"
   316   "listlen [] = 0"
   317 | "listlen (x#xs) = Suc (listlen xs)"
   317 | "listlen (x#xs) = Suc (listlen xs)"