1 (* Title: HOL/Tools/Function/fundef_lib.ML |
1 (* Title: HOL/Tools/Function/fundef_lib.ML |
2 Author: Alexander Krauss, TU Muenchen |
2 Author: Alexander Krauss, TU Muenchen |
3 |
3 |
4 A package for general recursive function definitions. |
4 A package for general recursive function definitions. |
5 Some fairly general functions that should probably go somewhere else... |
5 Some fairly general functions that should probably go somewhere else... |
6 *) |
6 *) |
7 |
7 |
8 structure Function_Lib = |
8 structure Function_Lib = |
9 struct |
9 struct |
10 |
10 |
11 fun map_option f NONE = NONE |
11 fun map_option f NONE = NONE |
12 | map_option f (SOME x) = SOME (f x); |
12 | map_option f (SOME x) = SOME (f x); |
13 |
13 |
14 fun fold_option f NONE y = y |
14 fun fold_option f NONE y = y |
15 | fold_option f (SOME x) y = f x y; |
15 | fold_option f (SOME x) y = f x y; |
16 |
16 |
19 | plural sg pl _ = pl |
19 | plural sg pl _ = pl |
20 |
20 |
21 (* lambda-abstracts over an arbitrarily nested tuple |
21 (* lambda-abstracts over an arbitrarily nested tuple |
22 ==> hologic.ML? *) |
22 ==> hologic.ML? *) |
23 fun tupled_lambda vars t = |
23 fun tupled_lambda vars t = |
24 case vars of |
24 case vars of |
25 (Free v) => lambda (Free v) t |
25 (Free v) => lambda (Free v) t |
26 | (Var v) => lambda (Var v) t |
26 | (Var v) => lambda (Var v) t |
27 | (Const ("Pair", Type ("fun", [Ta, Type ("fun", [Tb, _])]))) $ us $ vs => |
27 | (Const ("Pair", Type ("fun", [Ta, Type ("fun", [Tb, _])]))) $ us $ vs => |
28 (HOLogic.split_const (Ta,Tb, fastype_of t)) $ (tupled_lambda us (tupled_lambda vs t)) |
28 (HOLogic.split_const (Ta,Tb, fastype_of t)) $ (tupled_lambda us (tupled_lambda vs t)) |
29 | _ => raise Match |
29 | _ => raise Match |
30 |
30 |
31 |
31 |
32 fun dest_all (Const ("all", _) $ Abs (a as (_,T,_))) = |
32 fun dest_all (Const ("all", _) $ Abs (a as (_,T,_))) = |
33 let |
33 let |
34 val (n, body) = Term.dest_abs a |
34 val (n, body) = Term.dest_abs a |
35 in |
35 in |
36 (Free (n, T), body) |
36 (Free (n, T), body) |
37 end |
37 end |
38 | dest_all _ = raise Match |
38 | dest_all _ = raise Match |
39 |
39 |
40 |
40 |
41 (* Removes all quantifiers from a term, replacing bound variables by frees. *) |
41 (* Removes all quantifiers from a term, replacing bound variables by frees. *) |
42 fun dest_all_all (t as (Const ("all",_) $ _)) = |
42 fun dest_all_all (t as (Const ("all",_) $ _)) = |
43 let |
43 let |
44 val (v,b) = dest_all t |
44 val (v,b) = dest_all t |
45 val (vs, b') = dest_all_all b |
45 val (vs, b') = dest_all_all b |
46 in |
46 in |
47 (v :: vs, b') |
47 (v :: vs, b') |
48 end |
48 end |
49 | dest_all_all t = ([],t) |
49 | dest_all_all t = ([],t) |
50 |
50 |
51 |
51 |
52 (* FIXME: similar to Variable.focus *) |
52 (* FIXME: similar to Variable.focus *) |
53 fun dest_all_all_ctx ctx (Const ("all", _) $ Abs (n,T,b)) = |
53 fun dest_all_all_ctx ctx (Const ("all", _) $ Abs (n,T,b)) = |
54 let |
54 let |
55 val [(n', _)] = Variable.variant_frees ctx [] [(n,T)] |
55 val [(n', _)] = Variable.variant_frees ctx [] [(n,T)] |
56 val (_, ctx') = ProofContext.add_fixes [(Binding.name n', SOME T, NoSyn)] ctx |
56 val (_, ctx') = ProofContext.add_fixes [(Binding.name n', SOME T, NoSyn)] ctx |
57 |
57 |
58 val (n'', body) = Term.dest_abs (n', T, b) |
58 val (n'', body) = Term.dest_abs (n', T, b) |
59 val _ = (n' = n'') orelse error "dest_all_ctx" |
59 val _ = (n' = n'') orelse error "dest_all_ctx" |
60 (* Note: We assume that n' does not occur in the body. Otherwise it would be fixed. *) |
60 (* Note: We assume that n' does not occur in the body. Otherwise it would be fixed. *) |
61 |
61 |
62 val (ctx'', vs, bd) = dest_all_all_ctx ctx' body |
62 val (ctx'', vs, bd) = dest_all_all_ctx ctx' body |
63 in |
63 in |
64 (ctx'', (n', T) :: vs, bd) |
64 (ctx'', (n', T) :: vs, bd) |
65 end |
65 end |
66 | dest_all_all_ctx ctx t = |
66 | dest_all_all_ctx ctx t = |
67 (ctx, [], t) |
67 (ctx, [], t) |
68 |
68 |
69 |
69 |
70 fun map3 _ [] [] [] = [] |
70 fun map3 _ [] [] [] = [] |
71 | map3 f (x :: xs) (y :: ys) (z :: zs) = f x y z :: map3 f xs ys zs |
71 | map3 f (x :: xs) (y :: ys) (z :: zs) = f x y z :: map3 f xs ys zs |
72 | map3 _ _ _ _ = raise Library.UnequalLengths; |
72 | map3 _ _ _ _ = raise Library.UnequalLengths; |
84 | map7 _ _ _ _ _ _ _ _ = raise Library.UnequalLengths; |
84 | map7 _ _ _ _ _ _ _ _ = raise Library.UnequalLengths; |
85 |
85 |
86 |
86 |
87 |
87 |
88 (* forms all "unordered pairs": [1, 2, 3] ==> [(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)] *) |
88 (* forms all "unordered pairs": [1, 2, 3] ==> [(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)] *) |
89 (* ==> library *) |
|
90 fun unordered_pairs [] = [] |
89 fun unordered_pairs [] = [] |
91 | unordered_pairs (x::xs) = map (pair x) (x::xs) @ unordered_pairs xs |
90 | unordered_pairs (x::xs) = map (pair x) (x::xs) @ unordered_pairs xs |
92 |
91 |
93 |
92 |
94 (* Replaces Frees by name. Works with loose Bounds. *) |
93 (* Replaces Frees by name. Works with loose Bounds. *) |
95 fun replace_frees assoc = |
94 fun replace_frees assoc = |
96 map_aterms (fn c as Free (n, _) => the_default c (AList.lookup (op =) assoc n) |
95 map_aterms (fn c as Free (n, _) => the_default c (AList.lookup (op =) assoc n) |
97 | t => t) |
96 | t => t) |
98 |
97 |
99 |
98 |
100 fun rename_bound n (Q $ Abs(_, T, b)) = (Q $ Abs(n, T, b)) |
99 fun rename_bound n (Q $ Abs (_, T, b)) = (Q $ Abs (n, T, b)) |
101 | rename_bound n _ = raise Match |
100 | rename_bound n _ = raise Match |
102 |
101 |
103 fun mk_forall_rename (n, v) = |
102 fun mk_forall_rename (n, v) = |
104 rename_bound n o Logic.all v |
103 rename_bound n o Logic.all v |
105 |
104 |
106 fun forall_intr_rename (n, cv) thm = |
105 fun forall_intr_rename (n, cv) thm = |
107 let |
106 let |
108 val allthm = forall_intr cv thm |
107 val allthm = forall_intr cv thm |
109 val (_ $ abs) = prop_of allthm |
108 val (_ $ abs) = prop_of allthm |
110 in |
109 in |
111 Thm.rename_boundvars abs (Abs (n, dummyT, Term.dummy_pattern dummyT)) allthm |
110 Thm.rename_boundvars abs (Abs (n, dummyT, Term.dummy_pattern dummyT)) allthm |
112 end |
111 end |
113 |
112 |
114 |
113 |
115 (* Returns the frees in a term in canonical order, excluding the fixes from the context *) |
114 (* Returns the frees in a term in canonical order, excluding the fixes from the context *) |
116 fun frees_in_term ctxt t = |
115 fun frees_in_term ctxt t = |
117 Term.add_frees t [] |
116 Term.add_frees t [] |
118 |> filter_out (Variable.is_fixed ctxt o fst) |
117 |> filter_out (Variable.is_fixed ctxt o fst) |
119 |> rev |
118 |> rev |
120 |
119 |
121 |
120 |
122 datatype proof_attempt = Solved of thm | Stuck of thm | Fail |
121 datatype proof_attempt = Solved of thm | Stuck of thm | Fail |
123 |
122 |
124 fun try_proof cgoal tac = |
123 fun try_proof cgoal tac = |
125 case SINGLE tac (Goal.init cgoal) of |
124 case SINGLE tac (Goal.init cgoal) of |
126 NONE => Fail |
125 NONE => Fail |
127 | SOME st => |
126 | SOME st => |
128 if Thm.no_prems st |
127 if Thm.no_prems st |
129 then Solved (Goal.finish (Syntax.init_pretty_global (Thm.theory_of_cterm cgoal)) st) |
128 then Solved (Goal.finish (Syntax.init_pretty_global (Thm.theory_of_cterm cgoal)) st) |
130 else Stuck st |
129 else Stuck st |
131 |
130 |
132 |
131 |
133 fun dest_binop_list cn (t as (Const (n, _) $ a $ b)) = |
132 fun dest_binop_list cn (t as (Const (n, _) $ a $ b)) = |
134 if cn = n then dest_binop_list cn a @ dest_binop_list cn b else [ t ] |
133 if cn = n then dest_binop_list cn a @ dest_binop_list cn b else [ t ] |
135 | dest_binop_list _ t = [ t ] |
134 | dest_binop_list _ t = [ t ] |
136 |
135 |
137 |
136 |
138 (* separate two parts in a +-expression: |
137 (* separate two parts in a +-expression: |
139 "a + b + c + d + e" --> "(a + b + d) + (c + e)" |
138 "a + b + c + d + e" --> "(a + b + d) + (c + e)" |