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
|