src/HOL/Tools/Lifting/lifting_term.ML
author wenzelm
Tue, 03 Apr 2012 20:37:52 +0200
changeset 47319 8aa23a259ab2
parent 47308 9caab698dbe4
child 47350 ec46b60aa582
permissions -rw-r--r--
prefer static dependencies;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47308
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     1
(*  Title:      HOL/Tools/Lifting/lifting_term.ML
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     2
    Author:     Ondrej Kuncar
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     3
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     4
Proves Quotient theorem.
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     5
*)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     6
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     7
signature LIFTING_TERM =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     8
sig
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
     9
  val prove_quot_theorem: Proof.context -> typ * typ -> thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    10
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    11
  val absrep_fun: Proof.context -> typ * typ -> term
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    12
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    13
  (* Allows Nitpick to represent quotient types as single elements from raw type *)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    14
  (* val absrep_const_chk: Proof.context -> flag -> string -> term *)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    15
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    16
  val equiv_relation: Proof.context -> typ * typ -> term
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    17
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    18
  val quot_thm_rel: thm -> term
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    19
  val quot_thm_abs: thm -> term
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    20
  val quot_thm_rep: thm -> term
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    21
  val quot_thm_rty_qty: thm -> typ * typ
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    22
end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    23
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    24
structure Lifting_Term: LIFTING_TERM =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    25
struct
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    26
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    27
exception LIFT_MATCH of string
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    28
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    29
(* matches a type pattern with a type *)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    30
fun match ctxt err ty_pat ty =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    31
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    32
    val thy = Proof_Context.theory_of ctxt
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    33
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    34
    Sign.typ_match thy (ty_pat, ty) Vartab.empty
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    35
      handle Type.TYPE_MATCH => err ctxt ty_pat ty
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    36
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    37
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    38
fun equiv_match_err ctxt ty_pat ty =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    39
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    40
    val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    41
    val ty_str = Syntax.string_of_typ ctxt ty
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    42
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    43
    raise LIFT_MATCH (space_implode " "
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    44
      ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    45
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    46
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    47
(* generation of the Quotient theorem  *)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    48
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    49
exception QUOT_THM of string
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    50
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    51
fun get_quot_thm ctxt s =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    52
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    53
    val thy = Proof_Context.theory_of ctxt
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    54
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    55
    (case Lifting_Info.lookup_quotients ctxt s of
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    56
      SOME qdata => Thm.transfer thy (#quot_thm qdata)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    57
    | NONE => raise QUOT_THM ("No quotient type " ^ quote s ^ " found."))
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    58
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    59
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    60
fun get_rel_quot_thm ctxt s =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    61
   let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    62
    val thy = Proof_Context.theory_of ctxt
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    63
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    64
    (case Lifting_Info.lookup_quotmaps ctxt s of
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    65
      SOME map_data => Thm.transfer thy (#quot_thm map_data)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    66
    | NONE => raise QUOT_THM ("get_relmap (no relation map function found for type " ^ s ^ ")"))
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    67
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    68
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    69
fun is_id_quot thm = (prop_of thm = prop_of @{thm identity_quotient})
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    70
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    71
infix 0 MRSL
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    72
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    73
fun ants MRSL thm = fold (fn rl => fn thm => rl RS thm) ants thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    74
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    75
exception NOT_IMPL of string
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    76
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    77
fun quot_thm_rel quot_thm = 
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    78
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    79
    val (Const (@{const_name Quotient}, _) $ rel $ _ $ _ $ _) = 
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    80
      (HOLogic.dest_Trueprop o prop_of) quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    81
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    82
    rel
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    83
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    84
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    85
fun quot_thm_abs quot_thm =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    86
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    87
    val (Const (@{const_name Quotient}, _) $ _ $ abs $ _ $ _) = 
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    88
      (HOLogic.dest_Trueprop o prop_of) quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    89
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    90
    abs
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    91
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    92
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    93
fun quot_thm_rep quot_thm =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    94
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    95
    val (Const (@{const_name Quotient}, _) $ _ $ _ $ rep $ _) = 
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    96
      (HOLogic.dest_Trueprop o prop_of) quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    97
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    98
    rep
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
    99
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   100
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   101
fun quot_thm_rty_qty quot_thm =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   102
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   103
    val abs = quot_thm_abs quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   104
    val abs_type = fastype_of abs  
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   105
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   106
    (domain_type abs_type, range_type abs_type)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   107
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   108
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   109
fun prove_quot_theorem ctxt (rty, qty) =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   110
  case (rty, qty) of
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   111
    (Type (s, tys), Type (s', tys')) =>
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   112
      if s = s'
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   113
      then
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   114
        let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   115
          val args = map (prove_quot_theorem ctxt) (tys ~~ tys')
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   116
        in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   117
          if forall is_id_quot args
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   118
          then
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   119
            @{thm identity_quotient}
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   120
          else
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   121
            args MRSL (get_rel_quot_thm ctxt s)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   122
        end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   123
      else
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   124
        let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   125
          val quot_thm = get_quot_thm ctxt s'
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   126
          val (Type (_, rtys), qty_pat) = quot_thm_rty_qty quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   127
          val qtyenv = match ctxt equiv_match_err qty_pat qty
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   128
          val rtys' = map (Envir.subst_type qtyenv) rtys
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   129
          val args = map (prove_quot_theorem ctxt) (tys ~~ rtys')
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   130
        in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   131
          if forall is_id_quot args
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   132
          then
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   133
            quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   134
          else
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   135
            let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   136
              val rel_quot_thm = args MRSL (get_rel_quot_thm ctxt s)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   137
            in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   138
              [rel_quot_thm, quot_thm] MRSL @{thm Quotient_compose}
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   139
           end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   140
        end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   141
  | _ => @{thm identity_quotient}
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   142
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   143
fun force_qty_type thy qty quot_thm =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   144
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   145
    val abs_schematic = quot_thm_abs quot_thm 
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   146
    val qty_schematic = (range_type o fastype_of) abs_schematic  
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   147
    val match_env = Sign.typ_match thy (qty_schematic, qty) Vartab.empty
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   148
    fun prep_ty thy (x, (S, ty)) =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   149
      (ctyp_of thy (TVar (x, S)), ctyp_of thy ty)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   150
    val ty_inst = Vartab.fold (cons o (prep_ty thy)) match_env []
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   151
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   152
    Thm.instantiate (ty_inst, []) quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   153
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   154
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   155
fun absrep_fun ctxt (rty, qty) = 
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   156
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   157
    val thy = Proof_Context.theory_of ctxt
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   158
    val quot_thm = prove_quot_theorem ctxt (rty, qty)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   159
    val forced_quot_thm = force_qty_type thy qty quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   160
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   161
    quot_thm_abs forced_quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   162
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   163
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   164
fun equiv_relation ctxt (rty, qty) =
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   165
  let
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   166
    val thy = Proof_Context.theory_of ctxt
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   167
    val quot_thm = prove_quot_theorem ctxt (rty, qty)
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   168
    val forced_quot_thm = force_qty_type thy qty quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   169
  in
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   170
    quot_thm_rel forced_quot_thm
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   171
  end
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   172
9caab698dbe4 new package Lifting - initial commit
kuncar
parents:
diff changeset
   173
end;