src/HOL/ex/Recdefs.thy
author blanchet
Fri, 27 May 2011 10:30:08 +0200
changeset 43016 42330f25142c
parent 37595 9591362629e3
child 44013 5cfc1c36ae97
permissions -rw-r--r--
renamed "try" "try_methods"
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6481
dbf2d9b3d6c8 recdef requires theory Recdef;
wenzelm
parents: 6455
diff changeset
     1
(*  Title:      HOL/ex/Recdefs.thy
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
     2
    Author:     Konrad Slind and Lawrence C Paulson
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
     3
    Copyright   1996  University of Cambridge
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
     4
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
     5
Examples of recdef definitions.  Most, but not all, are handled automatically.
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
     6
*)
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
     7
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
     8
header {* Examples of recdef definitions *}
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
     9
16417
9bc16273c2d4 migrated theory headers to new format
haftmann
parents: 14953
diff changeset
    10
theory Recdefs imports Main begin
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    11
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    12
consts fact :: "nat => nat"
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    13
recdef fact  less_than
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    14
  "fact x = (if x = 0 then 1 else x * fact (x - 1))"
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    15
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    16
consts Fact :: "nat => nat"
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    17
recdef Fact  less_than
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    18
  "Fact 0 = 1"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    19
  "Fact (Suc x) = Fact x * Suc x"
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    20
14953
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    21
consts fib :: "int => int"
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    22
recdef fib  "measure nat"
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    23
  eqn:  "fib n = (if n < 1 then 0
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    24
                  else if n=1 then 1
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    25
                  else fib(n - 2) + fib(n - 1))";
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    26
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    27
lemma "fib 7 = 13"
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    28
by simp
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    29
27decf8d40ff new fib example
paulson
parents: 14244
diff changeset
    30
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    31
consts map2 :: "('a => 'b => 'c) * 'a list * 'b list => 'c list"
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    32
recdef map2  "measure(\<lambda>(f, l1, l2). size l1)"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    33
  "map2 (f, [], [])  = []"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    34
  "map2 (f, h # t, []) = []"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    35
  "map2 (f, h1 # t1, h2 # t2) = f h1 h2 # map2 (f, t1, t2)"
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    36
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    37
consts finiteRchain :: "('a => 'a => bool) * 'a list => bool"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    38
recdef finiteRchain  "measure (\<lambda>(R, l). size l)"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    39
  "finiteRchain(R,  []) = True"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    40
  "finiteRchain(R, [x]) = True"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    41
  "finiteRchain(R, x # y # rst) = (R x y \<and> finiteRchain (R, y # rst))"
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    42
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    43
text {* Not handled automatically: too complicated. *}
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    44
consts variant :: "nat * nat list => nat"
14244
f58598341d30 InductiveInvariant_examples illustrates advanced recursive function definitions
paulson
parents: 12023
diff changeset
    45
recdef (permissive) variant "measure (\<lambda>(n,ns). size (filter (\<lambda>y. n \<le> y) ns))"
37595
9591362629e3 dropped ancient infix mem; refined code generation operations in List.thy
haftmann
parents: 37456
diff changeset
    46
  "variant (x, L) = (if x \<in> set L then variant (Suc x, L) else x)"
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    47
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    48
consts gcd :: "nat * nat => nat"
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    49
recdef gcd  "measure (\<lambda>(x, y). x + y)"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    50
  "gcd (0, y) = y"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    51
  "gcd (Suc x, 0) = Suc x"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    52
  "gcd (Suc x, Suc y) =
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    53
    (if y \<le> x then gcd (x - y, Suc y) else gcd (Suc x, y - x))"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    54
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    55
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    56
text {*
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    57
  \medskip The silly @{term g} function: example of nested recursion.
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    58
  Not handled automatically.  In fact, @{term g} is the zero constant
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    59
  function.
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    60
 *}
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    61
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    62
consts g :: "nat => nat"
11626
0dbfb578bf75 recdef (permissive);
wenzelm
parents: 11024
diff changeset
    63
recdef (permissive) g  less_than
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    64
  "g 0 = 0"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    65
  "g (Suc x) = g (g x)"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    66
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    67
lemma g_terminates: "g x < Suc x"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    68
  apply (induct x rule: g.induct)
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    69
   apply (auto simp add: g.simps)
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    70
  done
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    71
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    72
lemma g_zero: "g x = 0"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    73
  apply (induct x rule: g.induct)
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    74
   apply (simp_all add: g.simps g_terminates)
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    75
  done
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    76
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    77
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    78
consts Div :: "nat * nat => nat * nat"
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    79
recdef Div  "measure fst"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    80
  "Div (0, x) = (0, 0)"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    81
  "Div (Suc x, y) =
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    82
    (let (q, r) = Div (x, y)
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    83
    in if y \<le> Suc r then (Suc q, 0) else (q, Suc r))"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    84
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    85
text {*
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    86
  \medskip Not handled automatically.  Should be the predecessor
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    87
  function, but there is an unnecessary "looping" recursive call in
12023
wenzelm
parents: 11701
diff changeset
    88
  @{text "k 1"}.
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    89
*}
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
    90
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    91
consts k :: "nat => nat"
11701
3d51fbf81c17 sane numerals (stage 1): added generic 1, removed 1' and 2 on nat,
wenzelm
parents: 11626
diff changeset
    92
11626
0dbfb578bf75 recdef (permissive);
wenzelm
parents: 11024
diff changeset
    93
recdef (permissive) k  less_than
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    94
  "k 0 = 0"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    95
  "k (Suc n) =
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    96
   (let x = k 1
11701
3d51fbf81c17 sane numerals (stage 1): added generic 1, removed 1' and 2 on nat,
wenzelm
parents: 11626
diff changeset
    97
    in if False then k (Suc 1) else n)"
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    98
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
    99
consts part :: "('a => bool) * 'a list * 'a list * 'a list => 'a list * 'a list"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   100
recdef part  "measure (\<lambda>(P, l, l1, l2). size l)"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   101
  "part (P, [], l1, l2) = (l1, l2)"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   102
  "part (P, h # rst, l1, l2) =
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   103
    (if P h then part (P, rst, h # l1, l2)
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   104
    else part (P, rst, l1, h # l2))"
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
   105
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   106
consts fqsort :: "('a => 'a => bool) * 'a list => 'a list"
11626
0dbfb578bf75 recdef (permissive);
wenzelm
parents: 11024
diff changeset
   107
recdef (permissive) fqsort  "measure (size o snd)"
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   108
  "fqsort (ord, []) = []"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   109
  "fqsort (ord, x # rst) =
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   110
  (let (less, more) = part ((\<lambda>y. ord y x), rst, ([], []))
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   111
  in fqsort (ord, less) @ [x] @ fqsort (ord, more))"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   112
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   113
text {*
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   114
  \medskip Silly example which demonstrates the occasional need for
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   115
  additional congruence rules (here: @{thm [source] map_cong}).  If
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   116
  the congruence rule is removed, an unprovable termination condition
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   117
  is generated!  Termination not proved automatically.  TFL requires
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   118
  @{term [source] "\<lambda>x. mapf x"} instead of @{term [source] mapf}.
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   119
*}
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
   120
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   121
consts mapf :: "nat => nat list"
37456
0a1cc2675958 tuned set_replicate lemmas
nipkow
parents: 16417
diff changeset
   122
recdef mapf  "measure (\<lambda>m. m)"
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   123
  "mapf 0 = []"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   124
  "mapf (Suc n) = concat (map (\<lambda>x. mapf x) (replicate n n))"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   125
  (hints cong: map_cong)
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
   126
37456
0a1cc2675958 tuned set_replicate lemmas
nipkow
parents: 16417
diff changeset
   127
(* This used to be an example where recdef_tc etc is needed,
0a1cc2675958 tuned set_replicate lemmas
nipkow
parents: 16417
diff changeset
   128
   but now termination is proved outright
11024
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   129
recdef_tc mapf_tc: mapf
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   130
  apply (rule allI)
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   131
  apply (case_tac "n = 0")
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   132
   apply simp_all
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   133
  done
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   134
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   135
text {* Removing the termination condition from the generated thms: *}
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   136
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   137
lemma "mapf (Suc n) = concat (map mapf (replicate n n))"
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   138
  apply (simp add: mapf.simps mapf_tc)
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   139
  done
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   140
23bf8d787b04 converted to new-style theories;
wenzelm
parents: 8522
diff changeset
   141
lemmas mapf_induct = mapf.induct [OF mapf_tc]
37456
0a1cc2675958 tuned set_replicate lemmas
nipkow
parents: 16417
diff changeset
   142
*)
5124
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
   143
1ce3cccfacdb stepping stones: Recdef, Main;
wenzelm
parents:
diff changeset
   144
end