src/HOL/Tools/Function/partial_function.ML
author blanchet
Wed, 08 Jun 2011 16:20:18 +0200
changeset 43293 a80cdc4b27a3
parent 43083 df41a5762c3d
child 45008 8b74cfea913a
permissions -rw-r--r--
made "query" type systes a bit more sound -- local facts, e.g. the negated conjecture, may make invalid the infinity check, e.g. if we are proving that there exists two values of an infinite type, we can use the negated conjecture that there is only one value to derive unsound proofs unless the type is properly encoded
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     1
(*  Title:      HOL/Tools/Function/partial_function.ML
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     2
    Author:     Alexander Krauss, TU Muenchen
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     3
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     4
Partial function definitions based on least fixed points in ccpos.
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     5
*)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     6
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     7
signature PARTIAL_FUNCTION =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     8
sig
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
     9
  val setup: theory -> theory
43080
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    10
  val init: string -> term -> term -> thm -> thm option -> declaration
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    11
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    12
  val add_partial_function: string -> (binding * typ option * mixfix) list ->
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    13
    Attrib.binding * term -> local_theory -> local_theory
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    14
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    15
  val add_partial_function_cmd: string -> (binding * string option * mixfix) list ->
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    16
    Attrib.binding * string -> local_theory -> local_theory
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    17
end;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    18
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    19
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    20
structure Partial_Function: PARTIAL_FUNCTION =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    21
struct
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    22
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    23
(*** Context Data ***)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    24
43080
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    25
datatype setup_data = Setup_Data of 
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    26
 {fixp: term,
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    27
  mono: term,
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    28
  fixp_eq: thm,
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    29
  fixp_induct: thm option};
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    30
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    31
structure Modes = Generic_Data
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    32
(
43080
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    33
  type T = setup_data Symtab.table;
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    34
  val empty = Symtab.empty;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    35
  val extend = I;
41472
f6ab14e61604 misc tuning and comments based on review of Theory_Data, Proof_Data, Generic_Data usage;
wenzelm
parents: 41117
diff changeset
    36
  fun merge data = Symtab.merge (K true) data;
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    37
)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    38
43080
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    39
fun init mode fixp mono fixp_eq fixp_induct phi =
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    40
  let
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    41
    val term = Morphism.term phi;
43080
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    42
    val thm = Morphism.thm phi;
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    43
    val data' = Setup_Data 
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    44
      {fixp=term fixp, mono=term mono, fixp_eq=thm fixp_eq,
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
    45
       fixp_induct=Option.map thm fixp_induct};
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    46
  in
42949
618adb3584e5 separate initializations for different modes of partial_function -- generation of induction rules will be non-uniform
krauss
parents: 42495
diff changeset
    47
    Modes.map (Symtab.update (mode, data'))
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    48
  end
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    49
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    50
val known_modes = Symtab.keys o Modes.get o Context.Proof;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    51
val lookup_mode = Symtab.lookup o Modes.get o Context.Proof;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    52
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    53
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    54
structure Mono_Rules = Named_Thms
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    55
(
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    56
  val name = "partial_function_mono";
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    57
  val description = "monotonicity rules for partial function definitions";
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    58
);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    59
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    60
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    61
(*** Automated monotonicity proofs ***)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    62
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    63
fun strip_cases ctac = ctac #> Seq.map snd;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    64
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    65
(*rewrite conclusion with k-th assumtion*)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    66
fun rewrite_with_asm_tac ctxt k =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    67
  Subgoal.FOCUS (fn {context=ctxt', prems, ...} =>
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    68
    Local_Defs.unfold_tac ctxt' [nth prems k]) ctxt;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    69
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    70
fun dest_case thy t =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    71
  case strip_comb t of
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    72
    (Const (case_comb, _), args) =>
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    73
      (case Datatype.info_of_case thy case_comb of
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    74
         NONE => NONE
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    75
       | SOME {case_rewrites, ...} =>
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    76
           let
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    77
             val lhs = prop_of (hd case_rewrites)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    78
               |> HOLogic.dest_Trueprop |> HOLogic.dest_eq |> fst;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    79
             val arity = length (snd (strip_comb lhs));
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    80
             val conv = funpow (length args - arity) Conv.fun_conv
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    81
               (Conv.rewrs_conv (map mk_meta_eq case_rewrites));
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    82
           in
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    83
             SOME (nth args (arity - 1), conv)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    84
           end)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    85
  | _ => NONE;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    86
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    87
(*split on case expressions*)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    88
val split_cases_tac = Subgoal.FOCUS_PARAMS (fn {context=ctxt, ...} =>
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    89
  SUBGOAL (fn (t, i) => case t of
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    90
    _ $ (_ $ Abs (_, _, body)) =>
42361
23f352990944 modernized structure Proof_Context;
wenzelm
parents: 42083
diff changeset
    91
      (case dest_case (Proof_Context.theory_of ctxt) body of
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    92
         NONE => no_tac
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    93
       | SOME (arg, conv) =>
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    94
           let open Conv in
42083
e1209fc7ecdc added Term.is_open and Term.is_dependent convenience, to cover common situations of loose bounds;
wenzelm
parents: 41472
diff changeset
    95
              if Term.is_open arg then no_tac
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    96
              else ((DETERM o strip_cases o Induct.cases_tac ctxt false [[SOME arg]] NONE [])
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    97
                THEN_ALL_NEW (rewrite_with_asm_tac ctxt 0)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    98
                THEN_ALL_NEW etac @{thm thin_rl}
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
    99
                THEN_ALL_NEW (CONVERSION
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   100
                  (params_conv ~1 (fn ctxt' =>
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   101
                    arg_conv (arg_conv (abs_conv (K conv) ctxt'))) ctxt))) i
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   102
           end)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   103
  | _ => no_tac) 1);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   104
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   105
(*monotonicity proof: apply rules + split case expressions*)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   106
fun mono_tac ctxt =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   107
  K (Local_Defs.unfold_tac ctxt [@{thm curry_def}])
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   108
  THEN' (TRY o REPEAT_ALL_NEW
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   109
   (resolve_tac (Mono_Rules.get ctxt)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   110
     ORELSE' split_cases_tac ctxt));
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   111
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   112
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   113
(*** Auxiliary functions ***)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   114
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   115
(*positional instantiation with computed type substitution.
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   116
  internal version of  attribute "[of s t u]".*)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   117
fun cterm_instantiate' cts thm =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   118
  let
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   119
    val thy = Thm.theory_of_thm thm;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   120
    val vs = rev (Term.add_vars (prop_of thm) [])
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   121
      |> map (Thm.cterm_of thy o Var);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   122
  in
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   123
    cterm_instantiate (zip_options vs cts) thm
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   124
  end;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   125
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   126
(*Returns t $ u, but instantiates the type of t to make the
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   127
application type correct*)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   128
fun apply_inst ctxt t u =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   129
  let
42361
23f352990944 modernized structure Proof_Context;
wenzelm
parents: 42083
diff changeset
   130
    val thy = Proof_Context.theory_of ctxt;
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   131
    val T = domain_type (fastype_of t);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   132
    val T' = fastype_of u;
42388
a44b0fdaa6c2 standardized aliases of operations on tsig;
wenzelm
parents: 42361
diff changeset
   133
    val subst = Sign.typ_match thy (T, T') Vartab.empty
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   134
      handle Type.TYPE_MATCH => raise TYPE ("apply_inst", [T, T'], [t, u])
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   135
  in
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   136
    map_types (Envir.norm_type subst) t $ u
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   137
  end;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   138
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   139
fun head_conv cv ct =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   140
  if can Thm.dest_comb ct then Conv.fun_conv (head_conv cv) ct else cv ct;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   141
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   142
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   143
(*** currying transformation ***)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   144
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   145
fun curry_const (A, B, C) =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   146
  Const (@{const_name Product_Type.curry},
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   147
    [HOLogic.mk_prodT (A, B) --> C, A, B] ---> C);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   148
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   149
fun mk_curry f =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   150
  case fastype_of f of
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   151
    Type ("fun", [Type (_, [S, T]), U]) =>
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   152
      curry_const (S, T, U) $ f
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   153
  | T => raise TYPE ("mk_curry", [T], [f]);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   154
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   155
(* iterated versions. Nonstandard left-nested tuples arise naturally
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   156
from "split o split o split"*)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   157
fun curry_n arity = funpow (arity - 1) mk_curry;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   158
fun uncurry_n arity = funpow (arity - 1) HOLogic.mk_split;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   159
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   160
val curry_uncurry_ss = HOL_basic_ss addsimps
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   161
  [@{thm Product_Type.curry_split}, @{thm Product_Type.split_curry}]
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   162
43083
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   163
val split_conv_ss = HOL_basic_ss addsimps
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   164
  [@{thm Product_Type.split_conv}];
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   165
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   166
fun mk_curried_induct args ctxt ccurry cuncurry rule =
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   167
  let
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   168
    val cert = Thm.cterm_of (Proof_Context.theory_of ctxt)
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   169
    val ([P], ctxt') = Variable.variant_fixes ["P"] ctxt
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   170
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   171
    val split_paired_all_conv =
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   172
      Conv.every_conv (replicate (length args - 1) (Conv.rewr_conv @{thm split_paired_all}))
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   173
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   174
    val split_params_conv = 
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   175
      Conv.params_conv ~1 (fn ctxt' =>
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   176
        Conv.implies_conv split_paired_all_conv Conv.all_conv)
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   177
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   178
    val inst_rule =
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   179
      cterm_instantiate' [SOME cuncurry, NONE, SOME ccurry] rule
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   180
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   181
    val plain_resultT = 
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   182
      Thm.prop_of inst_rule |> Logic.strip_imp_concl |> HOLogic.dest_Trueprop
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   183
      |> Term.head_of |> Term.dest_Var |> snd |> range_type |> domain_type
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   184
    val PT = map (snd o dest_Free) args ---> plain_resultT --> HOLogic.boolT
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   185
    val x_inst = cert (foldl1 HOLogic.mk_prod args)
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   186
    val P_inst = cert (uncurry_n (length args) (Free (P, PT)))
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   187
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   188
    val inst_rule' = inst_rule
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   189
      |> Tactic.rule_by_tactic ctxt
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   190
        (Simplifier.simp_tac curry_uncurry_ss 4
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   191
         THEN Simplifier.simp_tac curry_uncurry_ss 3
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   192
         THEN CONVERSION (split_params_conv ctxt
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   193
           then_conv (Conv.forall_conv (K split_paired_all_conv) ctxt)) 3)
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   194
      |> Drule.instantiate' [] [NONE, NONE, SOME P_inst, SOME x_inst]
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   195
      |> Simplifier.full_simplify split_conv_ss
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   196
      |> singleton (Variable.export ctxt' ctxt)
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   197
  in
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   198
    inst_rule'
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   199
  end;
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   200
    
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   201
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   202
(*** partial_function definition ***)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   203
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   204
fun gen_add_partial_function prep mode fixes_raw eqn_raw lthy =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   205
  let
43080
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
   206
    val setup_data = the (lookup_mode lthy mode)
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   207
      handle Option.Option => error (cat_lines ["Unknown mode " ^ quote mode ^ ".",
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   208
        "Known modes are " ^ commas_quote (known_modes lthy) ^ "."]);
43080
73a1d6a7ef1d also manage induction rule;
krauss
parents: 42949
diff changeset
   209
    val Setup_Data {fixp, mono, fixp_eq, fixp_induct} = setup_data;
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   210
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   211
    val ((fixes, [(eq_abinding, eqn)]), _) = prep fixes_raw [eqn_raw] lthy;
43083
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   212
    val ((_, plain_eqn), args_ctxt) = Variable.focus eqn lthy;
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   213
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   214
    val ((f_binding, fT), mixfix) = the_single fixes;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   215
    val fname = Binding.name_of f_binding;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   216
42361
23f352990944 modernized structure Proof_Context;
wenzelm
parents: 42083
diff changeset
   217
    val cert = cterm_of (Proof_Context.theory_of lthy);
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   218
    val (lhs, rhs) = HOLogic.dest_eq (HOLogic.dest_Trueprop plain_eqn);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   219
    val (head, args) = strip_comb lhs;
43083
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   220
    val argnames = map (fst o dest_Free) args;
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   221
    val F = fold_rev lambda (head :: args) rhs;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   222
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   223
    val arity = length args;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   224
    val (aTs, bTs) = chop arity (binder_types fT);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   225
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   226
    val tupleT = foldl1 HOLogic.mk_prodT aTs;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   227
    val fT_uc = tupleT :: bTs ---> body_type fT;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   228
    val f_uc = Var ((fname, 0), fT_uc);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   229
    val x_uc = Var (("x", 0), tupleT);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   230
    val uncurry = lambda head (uncurry_n arity head);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   231
    val curry = lambda f_uc (curry_n arity f_uc);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   232
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   233
    val F_uc =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   234
      lambda f_uc (uncurry_n arity (F $ curry_n arity f_uc));
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   235
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   236
    val mono_goal = apply_inst lthy mono (lambda f_uc (F_uc $ f_uc $ x_uc))
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   237
      |> HOLogic.mk_Trueprop
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   238
      |> Logic.all x_uc;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   239
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   240
    val mono_thm = Goal.prove_internal [] (cert mono_goal)
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   241
        (K (mono_tac lthy 1))
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   242
      |> Thm.forall_elim (cert x_uc);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   243
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   244
    val f_def_rhs = curry_n arity (apply_inst lthy fixp F_uc);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   245
    val f_def_binding = Binding.conceal (Binding.name (Thm.def_name fname));
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   246
    val ((f, (_, f_def)), lthy') = Local_Theory.define
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   247
      ((f_binding, mixfix), ((f_def_binding, []), f_def_rhs)) lthy;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   248
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   249
    val eqn = HOLogic.mk_eq (list_comb (f, args),
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   250
        Term.betapplys (F, f :: args))
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   251
      |> HOLogic.mk_Trueprop;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   252
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   253
    val unfold =
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   254
      (cterm_instantiate' (map (SOME o cert) [uncurry, F, curry]) fixp_eq
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   255
        OF [mono_thm, f_def])
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   256
      |> Tactic.rule_by_tactic lthy (Simplifier.simp_tac curry_uncurry_ss 1);
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   257
43083
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   258
    val mk_raw_induct =
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   259
      mk_curried_induct args args_ctxt (cert curry) (cert uncurry)
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   260
      #> singleton (Variable.export args_ctxt lthy)
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   261
      #> (fn thm => Drule.instantiate' [] [SOME (cert F)] thm OF [mono_thm, f_def])
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   262
      #> Drule.rename_bvars' (map SOME (fname :: argnames @ argnames))
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   263
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   264
    val raw_induct = Option.map mk_raw_induct fixp_induct
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   265
    val rec_rule = let open Conv in
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   266
      Goal.prove lthy' (map (fst o dest_Free) args) [] eqn (fn _ =>
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   267
        CONVERSION ((arg_conv o arg1_conv o head_conv o rewr_conv) (mk_meta_eq unfold)) 1
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   268
        THEN rtac @{thm refl} 1) end;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   269
  in
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   270
    lthy'
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   271
    |> Local_Theory.note (eq_abinding, [rec_rule])
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   272
    |-> (fn (_, rec') =>
40180
c3ef007115a0 fixed confusion introduced in 008dc2d2c395
krauss
parents: 40172
diff changeset
   273
      Spec_Rules.add Spec_Rules.Equational ([f], rec')
c3ef007115a0 fixed confusion introduced in 008dc2d2c395
krauss
parents: 40172
diff changeset
   274
      #> Local_Theory.note ((Binding.qualify true fname (Binding.name "simps"), []), rec') #> snd)
43083
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   275
    |> (case raw_induct of NONE => I | SOME thm =>
df41a5762c3d generate raw induction rule as instance of generic rule with careful treatment of currying
krauss
parents: 43080
diff changeset
   276
         Local_Theory.note ((Binding.qualify true fname (Binding.name "raw_induct"), []), [thm]) #> snd)
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   277
  end;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   278
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   279
val add_partial_function = gen_add_partial_function Specification.check_spec;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   280
val add_partial_function_cmd = gen_add_partial_function Specification.read_spec;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   281
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   282
val mode = Parse.$$$ "(" |-- Parse.xname --| Parse.$$$ ")";
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   283
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   284
val _ = Outer_Syntax.local_theory
40186
fe4a58419d46 partial_function is a declaration command
haftmann
parents: 40180
diff changeset
   285
  "partial_function" "define partial function" Keyword.thy_decl
40107
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   286
  ((mode -- (Parse.fixes -- (Parse.where_ |-- Parse_Spec.spec)))
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   287
     >> (fn (mode, (fixes, spec)) => add_partial_function_cmd mode fixes spec));
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   288
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   289
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   290
val setup = Mono_Rules.setup;
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   291
374f3ef9f940 first version of partial_function package
krauss
parents:
diff changeset
   292
end