src/HOL/Tools/function_package/fundef_lib.ML
author haftmann
Sat, 15 Sep 2007 19:27:35 +0200
changeset 24584 01e83ffa6c54
parent 23819 2040846d1bbe
child 27330 1af2598b5f7d
permissions -rw-r--r--
fixed title
haftmann@24584
     1
(*  Title:      HOL/Tools/function_package/fundef_lib.ML
krauss@19564
     2
    ID:         $Id$
krauss@19564
     3
    Author:     Alexander Krauss, TU Muenchen
krauss@19564
     4
krauss@19564
     5
A package for general recursive function definitions. 
krauss@19564
     6
Some fairly general functions that should probably go somewhere else... 
krauss@19564
     7
*)
krauss@19564
     8
krauss@21051
     9
structure FundefLib = struct
krauss@21051
    10
krauss@22166
    11
fun map_option f NONE = NONE 
krauss@22166
    12
  | map_option f (SOME x) = SOME (f x);
krauss@22166
    13
krauss@22166
    14
fun fold_option f NONE y = y
krauss@22166
    15
  | fold_option f (SOME x) y = f x y;
krauss@22166
    16
krauss@22166
    17
fun fold_map_option f NONE y = (NONE, y)
krauss@22166
    18
  | fold_map_option f (SOME x) y = apfst SOME (f x y);
krauss@22166
    19
wenzelm@23216
    20
(* Ex: "The variable" ^ plural " is" "s are" vs *)
wenzelm@23216
    21
fun plural sg pl [x] = sg
wenzelm@23216
    22
  | plural sg pl _ = pl
krauss@20523
    23
krauss@22166
    24
(* ==> logic.ML? *)
krauss@21188
    25
fun mk_forall v t = all (fastype_of v) $ lambda v t
krauss@19564
    26
krauss@22166
    27
(* lambda-abstracts over an arbitrarily nested tuple
krauss@22166
    28
  ==> hologic.ML? *)
krauss@19564
    29
fun tupled_lambda vars t =
krauss@19564
    30
    case vars of
krauss@21237
    31
      (Free v) => lambda (Free v) t
krauss@21188
    32
    | (Var v) => lambda (Var v) t
krauss@21188
    33
    | (Const ("Pair", Type ("fun", [Ta, Type ("fun", [Tb, _])]))) $ us $ vs =>  
krauss@21237
    34
      (HOLogic.split_const (Ta,Tb, fastype_of t)) $ (tupled_lambda us (tupled_lambda vs t))
krauss@21188
    35
    | _ => raise Match
krauss@21188
    36
                 
krauss@21188
    37
                 
krauss@19564
    38
fun dest_all (Const ("all", _) $ Abs (a as (_,T,_))) =
krauss@19564
    39
    let
krauss@21237
    40
      val (n, body) = Term.dest_abs a
krauss@19564
    41
    in
krauss@21237
    42
      (Free (n, T), body)
krauss@19564
    43
    end
krauss@19564
    44
  | dest_all _ = raise Match
krauss@21188
    45
                         
krauss@19564
    46
krauss@19564
    47
(* Removes all quantifiers from a term, replacing bound variables by frees. *)
krauss@19564
    48
fun dest_all_all (t as (Const ("all",_) $ _)) = 
krauss@19564
    49
    let
krauss@21319
    50
      val (v,b) = dest_all t
krauss@21319
    51
      val (vs, b') = dest_all_all b
krauss@19564
    52
    in
krauss@21319
    53
      (v :: vs, b')
krauss@19564
    54
    end
krauss@19564
    55
  | dest_all_all t = ([],t)
krauss@21319
    56
                     
krauss@19564
    57
krauss@21319
    58
(* FIXME: similar to Variable.focus *)
krauss@19922
    59
fun dest_all_all_ctx ctx (Const ("all", _) $ Abs (a as (n,T,b))) =
krauss@19922
    60
    let
wenzelm@20154
    61
      val [(n', _)] = Variable.variant_frees ctx [] [(n,T)]
krauss@19922
    62
      val (_, ctx') = ProofContext.add_fixes_i [(n', SOME T, NoSyn)] ctx
krauss@19922
    63
krauss@19922
    64
      val (n'', body) = Term.dest_abs (n', T, b) 
wenzelm@21858
    65
      val _ = (n' = n'') orelse error "dest_all_ctx"
wenzelm@21858
    66
      (* Note: We assume that n' does not occur in the body. Otherwise it would be fixed. *)
krauss@19922
    67
krauss@19922
    68
      val (ctx'', vs, bd) = dest_all_all_ctx ctx' body
krauss@19922
    69
    in
krauss@21237
    70
      (ctx'', (n', T) :: vs, bd)
krauss@19922
    71
    end
krauss@19922
    72
  | dest_all_all_ctx ctx t = 
krauss@19922
    73
    (ctx, [], t)
krauss@19922
    74
krauss@19922
    75
krauss@19564
    76
fun map3 _ [] [] [] = []
krauss@19564
    77
  | map3 f (x :: xs) (y :: ys) (z :: zs) = f x y z :: map3 f xs ys zs
wenzelm@19841
    78
  | map3 _ _ _ _ = raise Library.UnequalLengths;
krauss@19564
    79
krauss@20523
    80
fun map4 _ [] [] [] [] = []
krauss@20523
    81
  | map4 f (x :: xs) (y :: ys) (z :: zs) (u :: us) = f x y z u :: map4 f xs ys zs us
krauss@20523
    82
  | map4 _ _ _ _ _ = raise Library.UnequalLengths;
krauss@20523
    83
krauss@19922
    84
fun map6 _ [] [] [] [] [] [] = []
krauss@19922
    85
  | map6 f (x :: xs) (y :: ys) (z :: zs) (u :: us) (v :: vs) (w :: ws) = f x y z u v w :: map6 f xs ys zs us vs ws
krauss@19922
    86
  | map6 _ _ _ _ _ _ _ = raise Library.UnequalLengths;
krauss@19922
    87
krauss@20523
    88
fun map7 _ [] [] [] [] [] [] [] = []
krauss@20523
    89
  | map7 f (x :: xs) (y :: ys) (z :: zs) (u :: us) (v :: vs) (w :: ws) (b :: bs) = f x y z u v w b :: map7 f xs ys zs us vs ws bs
krauss@20523
    90
  | map7 _ _ _ _ _ _ _ _ = raise Library.UnequalLengths;
krauss@20523
    91
krauss@19564
    92
krauss@19564
    93
krauss@19564
    94
(* forms all "unordered pairs": [1, 2, 3] ==> [(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)] *)
krauss@22166
    95
(* ==> library *)
krauss@19922
    96
fun unordered_pairs [] = []
krauss@19922
    97
  | unordered_pairs (x::xs) = map (pair x) (x::xs) @ unordered_pairs xs
krauss@19564
    98
krauss@19770
    99
wenzelm@23260
   100
(* FIXME cf. Term.exists_subterm *)
krauss@21319
   101
fun forall_aterms P (t $ u) = forall_aterms P t andalso forall_aterms P u
krauss@21319
   102
  | forall_aterms P (Abs (_, _, t)) = forall_aterms P t
krauss@21319
   103
  | forall_aterms P a = P a
krauss@21319
   104
wenzelm@23260
   105
(* FIXME cf. Term.exists_subterm *)
krauss@21319
   106
fun exists_aterm P = not o forall_aterms (not o P)
krauss@21319
   107
krauss@21319
   108
krauss@21319
   109
krauss@22166
   110
(* Replaces Frees by name. Probably quicker than Pattern.rewrite_terms, and works with loose Bounds. *)
krauss@22166
   111
fun replace_frees assoc =
krauss@22166
   112
    map_aterms (fn c as Free (n, _) => the_default c (AList.lookup (op =) assoc n)
krauss@22166
   113
                 | t => t)
krauss@22166
   114
krauss@20523
   115
krauss@20523
   116
fun rename_bound n (Q $ Abs(_, T, b)) = (Q $ Abs(n, T, b))
krauss@20523
   117
  | rename_bound n _ = raise Match
krauss@20523
   118
krauss@20523
   119
fun mk_forall_rename (n, v) =
krauss@20523
   120
    rename_bound n o mk_forall v 
krauss@20523
   121
krauss@21319
   122
val dummy_term = Free ("", dummyT)
krauss@21319
   123
krauss@20523
   124
fun forall_intr_rename (n, cv) thm =
krauss@20523
   125
    let
krauss@20523
   126
      val allthm = forall_intr cv thm
krauss@22166
   127
      val (_ $ abs) = prop_of allthm
krauss@20523
   128
    in
krauss@21319
   129
      Thm.rename_boundvars abs (Abs (n, dummyT, dummy_term)) allthm
krauss@20523
   130
    end
krauss@20523
   131
krauss@20523
   132
krauss@20523
   133
(* Returns the frees in a term in canonical order, excluding the fixes from the context *)
krauss@20523
   134
fun frees_in_term ctxt t =
krauss@21319
   135
    Term.add_frees t []
krauss@21319
   136
    |> filter_out (Variable.is_fixed ctxt o fst)
krauss@21319
   137
    |> rev
krauss@20851
   138
krauss@21051
   139
wenzelm@21858
   140
end