needs "../formal_lp/arith/nat.hl";;
open Arith_nat;;
open Arith_misc;;
let t_const = `T` and
f_const = `F`;;
let MY_PROVE_HYP hyp th = EQ_MP (DEDUCT_ANTISYM_RULE hyp th) hyp;;
let MY_RULE = UNDISCH_ALL o PURE_REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL;;
let MY_RULE_NUM = UNDISCH_ALL o NUMERALS_TO_NUM o PURE_REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL;;
(******************************)
(* HD conversions *)
(* Takes a term `[a;...]` and returns the theorem |- HD [a;...] = a *)
let eval_hd list_tm =
let ltm, t_tm = dest_comb list_tm in
let h_tm = rand ltm in
let list_ty = type_of t_tm and
ty = type_of h_tm in
let h_var = mk_var("h", ty) and
t_var = mk_var("t", list_ty) in
(INST[h_tm, h_var; t_tm, t_var] o INST_TYPE[ty, aty]) HD_A_CONS;;
(* Takes a term `HD [a;...]` and returns the theorem |- HD [a;...] = a *)
let hd_conv hd_tm =
if (fst o dest_const o rator) hd_tm <> "HD" then failwith "hd_conv"
else eval_hd (rand hd_tm);;
(*
let tm = `HD [1;2;3;4]`;;
hd_conv tm;;
(* 0.072 *)
test 1000 (REWRITE_CONV[HD]) tm;;
(* 0.016 *)
test 1000 hd_conv tm;;
let tm = `[1;2;3;4]`;;
eval_hd tm;;
test 1000 eval_hd tm;;
*)
(*********************************)
(* EL conversion *)
let EL_0' = (MY_RULE_NUM o prove)(`EL 0 (CONS (h:A) t) = h`, REWRITE_TAC[EL; HD]);;
let EL_n' = (MY_RULE_NUM o prove)(`0 < n /\ PRE n = m ==> EL n (CONS (h:A) t) = EL m t`,
STRIP_TAC THEN SUBGOAL_THEN `n = SUC m` ASSUME_TAC THENL
[ REPEAT (POP_ASSUM MP_TAC) THEN ARITH_TAC; ALL_TAC ] THEN ASM_REWRITE_TAC[EL; TL]);;
let zero_const = `_0` and
pre_const = `PRE`;;
let m_var_num = `m:num` and
n_var_num = `n:num`;;
(* Takes a raw numeral term and a list term and returns the theorem |- EL n [...] = x *)
let eval_el n_tm list_tm =
let list_ty = type_of list_tm in
let ty = (hd o snd o dest_type) list_ty in
let inst_t = INST_TYPE[ty, aty] in
let el_0, el_n = inst_t EL_0', inst_t EL_n' in
let h_var, t_var = mk_var("h", ty), mk_var("t", list_ty) in
let rec el_conv_raw = fun n_tm list_tm ->
let h_tm, t_tm = dest_cons list_tm in
let inst0 = INST[h_tm, h_var; t_tm, t_var] in
if n_tm = zero_const then
inst0 el_0
else
let n_gt0 = (EQT_ELIM o raw_gt0_hash_conv) n_tm in
let pre_n = raw_pre_hash_conv (mk_comb (pre_const, n_tm)) in
let m_tm = (rand o concl) pre_n in
let th0 = (MY_PROVE_HYP pre_n o MY_PROVE_HYP n_gt0 o
INST[n_tm, n_var_num; m_tm, m_var_num] o inst0) el_n in
let th1 = el_conv_raw m_tm t_tm in
TRANS th0 th1 in
el_conv_raw n_tm list_tm;;
(* Takes a term `EL n [...]` and returns the theorem |- EL n [...] = x *)
(* Note: n must be a raw numeral term Dx (Dy ... _0) *)
let el_conv el_tm =
let ltm, list_tm = dest_comb el_tm in
let el, n_tm = dest_comb ltm in
if (fst o dest_const) el <> "EL" then failwith "el_conv"
else eval_el n_tm list_tm;;
(*
let n0_tm = `_0` and
n_tm = `D3 _0` and
list_tm = `[1; 2; 3; 4; 5]`;;
eval_el n0_tm list_tm;;
(* 0.24 *)
test 10000 (eval_el n0_tm) list_tm;;
eval_el n_tm list_tm;;
(* 1.22 *)
test 10000 (eval_el n_tm) list_tm;;
let tm = mk_icomb (mk_comb (`EL`, n_tm), list_tm);;
el_conv tm;;
*)
(*******************************)
(* FST, SND conversions *)
let FST' = ISPECL[`x:A`; `y:B`] FST;;
let SND' = ISPECL[`x:A`; `y:B`] SND;;
let fst_conv tm =
let x_tm, y_tm = dest_pair (rand tm) in
let x_ty, y_ty = type_of x_tm, type_of y_tm in
let x_var, y_var = mk_var("x", x_ty), mk_var("y", y_ty) in
(INST[x_tm, x_var; y_tm, y_var] o INST_TYPE[x_ty, aty; y_ty, bty]) FST';;
let snd_conv tm =
let x_tm, y_tm = dest_pair (rand tm) in
let x_ty, y_ty = type_of x_tm, type_of y_tm in
let x_var, y_var = mk_var("x", x_ty), mk_var("y", y_ty) in
(INST[x_tm, x_var; y_tm, y_var] o INST_TYPE[x_ty, aty; y_ty, bty]) SND';;
(*
let tm = `FST (1,2)`;;
fst_conv tm;;
(* 0.688 *)
test 10000 (REWRITE_CONV[]) tm;;
(* 0.100 *)
test 10000 fst_conv tm;;
*)
(******************************)
(* LENGTH conversions *)
let LENGTH_0' = (MY_RULE_NUM o prove) (`LENGTH ([]:(A)list) = 0`, REWRITE_TAC[LENGTH]) and
LENGTH_CONS' = prove(`LENGTH (CONS (h:A) t) = SUC (LENGTH t)`, REWRITE_TAC[LENGTH]);;
let suc_const = `SUC`;;
(* Takes a term `[...]` and returns the theorem |- LENGTH [...] = n *)
let eval_length list_tm =
let list_ty = type_of list_tm in
let ty = (hd o snd o dest_type) list_ty in
let inst_t = INST_TYPE[ty, aty] in
let length_empty, length_cons = inst_t LENGTH_0', inst_t LENGTH_CONS' in
let h_var, t_var = mk_var("h", ty), mk_var("t", list_ty) in
let rec length_conv_raw = fun list_tm ->
if (is_comb list_tm) then
let ltm, t_tm = dest_comb list_tm in
let h_tm = rand ltm in
let th0 = INST[h_tm, h_var; t_tm, t_var] length_cons in
let th1' = length_conv_raw t_tm in
let th1 = AP_TERM suc_const th1' in
let th2 = raw_suc_conv_hash (rand(concl th1)) in
TRANS (TRANS th0 th1) th2
else
length_empty in
length_conv_raw list_tm;;
(* Takes a term `LENGTH [...]` and returns the theorem |- LENGTH [...] = n *)
let length_conv length_tm =
if (fst o dest_const o rator) length_tm <> "LENGTH" then failwith "length_conv"
else eval_length (rand length_tm);;
(*
let tm = `LENGTH [&1;&4;&4;&6;&7 * &8]`;;
length_conv tm;;
test 1000 (REWRITE_CONV[LENGTH; ARITH_SUC]) tm;; (* 0.792 *)
test 1000 length_conv tm;; (* 0.076 *)
*)
(***************)
(* eval_zip *)
let ZIP_0' = prove(`
ZIP ([]:(A)list) ([]:(B)list) = []`,
REWRITE_TAC[
ZIP]) and
ZIP_CONS' = prove(`
ZIP (CONS (h1:A)
t1) (CONS (h2:B) t2) = CONS (h1, h2) (
ZIP t1 t2)`,
REWRITE_TAC[
ZIP]);;
let eval_zip list1_tm list2_tm =
let list1_ty = type_of list1_tm and
list2_ty = type_of list2_tm in
let ty1 = (hd o snd o dest_type) list1_ty and
ty2 = (hd o snd o dest_type) list2_ty in
let inst_t = INST_TYPE[ty1, aty; ty2, bty] in
let zip0, zip_cons = inst_t ZIP_0', inst_t ZIP_CONS' in
let h1_var, t1_var = mk_var("h1", ty1), mk_var("t1", list1_ty) and
h2_var, t2_var = mk_var("h2", ty2), mk_var("t2", list2_ty) in
let rec zip_conv_rec = fun list1_tm list2_tm ->
if (is_comb list1_tm) then
let ltm1, t1_tm = dest_comb list1_tm and
ltm2, t2_tm = dest_comb list2_tm in
let h1_tm, h2_tm = rand ltm1, rand ltm2 in
let th0 = INST[h1_tm, h1_var; t1_tm, t1_var; h2_tm, h2_var; t2_tm, t2_var] zip_cons in
let cons_tm = (rator o rand o concl) th0 in
let th1' = zip_conv_rec t1_tm t2_tm in
let th1 = AP_TERM cons_tm th1' in
TRANS th0 th1
else
zip0 in
zip_conv_rec list1_tm list2_tm;;
(******************)
(* ALL conversion *)
(******************)
let ALL_0' = prove(`
ALL P ([]:(A)list) <=> T`,
REWRITE_TAC[
ALL]) and
ALL_CONS_T' = (MY_RULE o prove)(`(P h <=> T) /\ (
ALL P t <=> T) ==> (
ALL P (CONS (h:A) t) <=> T)`,
REWRITE_TAC[
ALL]) and
ALL_CONS_F2' = (MY_RULE o prove)(`(
ALL P t <=> F) ==> (
ALL P (CONS (h:A) t) <=> F)`,
SIMP_TAC[
ALL]) and
ALL_CONS_F1' = (MY_RULE o prove)(`(P h <=> F) ==> (
ALL P (CONS (h:A) t) <=> F)`,
SIMP_TAC[
ALL]);;
(* Note: p_conv should return theorems of the form |- P a b <=> T *)
let all_conv_univ p_conv tm =
let ltm, list_tm = dest_comb tm in
let p_tm = rand ltm in
let list_ty = type_of list_tm and
p_ty = type_of p_tm in
let ty = (hd o snd o dest_type) list_ty in
let inst_t = INST_TYPE[ty, aty] in
let all_0, all_t, all_f1, all_f2 = inst_t ALL_0', inst_t ALL_CONS_T',
inst_t ALL_CONS_F1', inst_t ALL_CONS_F2' in
let h_var, t_var = mk_var("h", ty), mk_var("t", list_ty) and
p_var = mk_var("P", p_ty) in
let rec all_conv_rec = fun list_tm ->
if is_comb list_tm then
let ltm, t_tm = dest_comb list_tm in
let h_tm = rand ltm in
let p_th = p_conv (mk_comb (p_tm, h_tm)) in
let inst = INST[h_tm, h_var; t_tm, t_var; p_tm, p_var] in
if (rand o concl) p_th = t_const then
let all_th = all_conv_rec t_tm in
if (rand o concl) all_th = t_const then
(MY_PROVE_HYP all_th o MY_PROVE_HYP p_th o inst) all_t
else
(MY_PROVE_HYP all_th o inst) all_f2
else
(MY_PROVE_HYP p_th o inst) all_f1
else
INST[p_tm, p_var] all_0 in
all_conv_rec list_tm;;
(*
let tm = `ALL ((<) 0) [1;3;4;2;4]`;;
all_conv_univ NUM_LT_CONV tm;;
let test_conv = REWRITE_CONV[ALL] THENC ONCE_DEPTH_CONV NUM_LT_CONV;;
test_conv tm;;
(* 0.504 *)
test 1000 (all_conv_univ NUM_LT_CONV) tm;;
(* 1.056 *)
test 1000 test_conv test_tm;;
*)
(*******************)
(* ALL2 conversion *)
(*******************)
let ALL2_0' = prove(`
ALL2 P ([]:(A)list) ([]:(B)list) <=> T`,
REWRITE_TAC[
ALL2]) and
ALL2_CONS_T' = (MY_RULE o prove)(`(P h1 h2 <=> T) /\ (
ALL2 P
t1 t2 <=> T) ==>
(
ALL2 P (CONS (h1:A)
t1) (CONS (h2:B) t2) <=> T)`,
REWRITE_TAC[
ALL2]) and
ALL2_CONS_F2' = (MY_RULE o prove)(`(
ALL2 P
t1 t2 <=> F) ==>
(
ALL2 P (CONS (h1:A)
t1) (CONS (h2:B) t2) <=> F)`,
SIMP_TAC[
ALL2]) and
ALL2_CONS_F1' = (MY_RULE o prove)(`(P h1 h2 <=> F) ==>
(
ALL2 P (CONS (h1:A)
t1) (CONS (h2:B) t2) <=> F)`,
SIMP_TAC[
ALL2]);;
(* Note: p_conv should return theorems of the form |- P a b <=> T *)
let all2_conv_univ p_conv tm =
let ltm, list2_tm = dest_comb tm in
let ltm2, list1_tm = dest_comb ltm in
let p_tm = rand ltm2 in
let list1_ty = type_of list1_tm and
list2_ty = type_of list2_tm and
p_ty = type_of p_tm in
let ty1 = (hd o snd o dest_type) list1_ty and
ty2 = (hd o snd o dest_type) list2_ty in
let inst_t = INST_TYPE[ty1, aty; ty2, bty] in
let all2_0, all2_t, all2_f1, all2_f2 = inst_t ALL2_0', inst_t ALL2_CONS_T',
inst_t ALL2_CONS_F1', inst_t ALL2_CONS_F2' in
let h1_var, t1_var = mk_var("h1", ty1), mk_var("t1", list1_ty) and
h2_var, t2_var = mk_var("h2", ty2), mk_var("t2", list2_ty) and
p_var = mk_var("P", p_ty) in
let rec all2_conv_rec = fun list1_tm list2_tm ->
if is_comb list1_tm then
let ltm1, t1_tm = dest_comb list1_tm and
ltm2, t2_tm = dest_comb list2_tm in
let h1_tm, h2_tm = rand ltm1, rand ltm2 in
let p_th = p_conv (mk_binop p_tm h1_tm h2_tm) in
let inst = INST[h1_tm, h1_var; t1_tm, t1_var; h2_tm, h2_var; t2_tm, t2_var; p_tm, p_var] in
if (rand o concl) p_th = t_const then
let all2_th = all2_conv_rec t1_tm t2_tm in
if (rand o concl) all2_th = t_const then
(MY_PROVE_HYP all2_th o MY_PROVE_HYP p_th o inst) all2_t
else
(MY_PROVE_HYP all2_th o inst) all2_f2
else
(MY_PROVE_HYP p_th o inst) all2_f1
else
if is_comb list2_tm then failwith ("all2_conv_univ: l1 = []; l2 = "^string_of_term list2_tm) else
INST[p_tm, p_var] all2_0 in
all2_conv_rec list1_tm list2_tm;;
(*
let tm = `ALL2 (<) [1;3;4;2;4] [3;343;454;454;5]`;;
all2_conv_univ NUM_LT_CONV tm;;
let test_conv = REWRITE_CONV[ALL2] THENC ONCE_DEPTH_CONV NUM_LT_CONV;;
test_conv tm;;
(* 0.744 *)
test 1000 (all2_conv_univ NUM_LT_CONV) tm;;
(* 2.280 *)
test 1000 test_conv test_tm;;
*)
(******************************)
(* MEM conversions *)
let MEM_A_EMPTY = prove(`
MEM (x:A) [] <=> F`,
REWRITE_TAC[
MEM]) and
MEM_A_HD = MY_RULE (prove(`(x = h <=> T) ==> (
MEM (x:A) (CONS h t) <=> T)`,SIMP_TAC[
MEM])) and
MEM_A_TL = MY_RULE (prove(`(x = h <=> F) ==> (
MEM (x:A) (CONS h t) <=>
MEM x t)`, SIMP_TAC[
MEM]));;
let rec eval_mem_univ eq_conv x_tm list_tm =
let ty = type_of x_tm in
let inst_t = INST_TYPE[ty, aty] in
let mem_empty, mem_hd, mem_tl = inst_t MEM_A_EMPTY, inst_t MEM_A_HD, inst_t MEM_A_TL in
let x_var, h_var = mk_var("x", ty), mk_var("h", ty) and
t_var = mk_var("t", mk_type("list", [ty])) in
let rec mem_conv_raw list_tm =
if (is_comb list_tm) then
let h_tm', t_tm = dest_comb list_tm in
let h_tm = rand h_tm' in
let eq_th = eq_conv (mk_eq(x_tm, h_tm)) in
if (rand(concl eq_th) = t_const) then
let th0' = INST[x_tm, x_var; h_tm, h_var; t_tm, t_var] mem_hd in
MY_PROVE_HYP eq_th th0'
else
let th0' = INST[x_tm, x_var; h_tm, h_var; t_tm, t_var] mem_tl in
let th0 = MY_PROVE_HYP eq_th th0' in
let th1 = mem_conv_raw t_tm in
TRANS th0 th1
else
INST[x_tm, x_var] mem_empty in
mem_conv_raw list_tm;;
let mem_conv_univ eq_conv mem_tm =
let ltm, list_tm = dest_comb mem_tm in
let c_tm, x_tm = dest_comb ltm in
if (fst o dest_const) c_tm <> "MEM" then failwith "mem_conv_univ" else
eval_mem_univ eq_conv x_tm list_tm;;
(*
let tm = `MEM 11 [1;2;3;4;5;6;4;5;6;7;3;4;4;6;8;9;10]`;;
mem_conv_univ (PURE_REWRITE_CONV[ARITH_EQ]) tm;;
test 100 (mem_conv_univ (REWRITE_CONV[ARITH_EQ])) tm;; (* 0.176 *)
test 100 (REWRITE_CONV[MEM; ARITH_EQ]) tm;; (* 0.352 *)
*)
(**********************************)
(* FILTER conversions *)
let filter_conv_univ p_conv tm =
let ltm, list_tm = dest_comb tm in
let p_tm = rand ltm in
let p_ty = type_of p_tm in
let ty = (hd o snd o dest_type) p_ty in
let inst_t = INST_TYPE[ty, aty] in
let filter_empty, filter_hd, filter_tl =
inst_t FILTER_A_EMPTY, inst_t FILTER_A_HD, inst_t FILTER_A_TL in
let p_var = mk_var("P", p_ty) in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", mk_type("list",[ty])) in
let rec filter_conv_raw = fun list_tm ->
if (is_comb list_tm) then
let ltm, t_tm = dest_comb list_tm in
let h_tm = rand ltm in
let p_th = p_conv (mk_comb(p_tm, h_tm)) in
if (rand(concl p_th) = t_const) then
let th0' = INST[p_tm, p_var; h_tm, h_var; t_tm, t_var] filter_hd in
let th0 = MY_PROVE_HYP p_th th0' in
let ltm = rator(rand(concl th0)) in
let th1 = filter_conv_raw t_tm in
TRANS th0 (AP_TERM ltm th1)
else
let th0' = INST[p_tm, p_var; h_tm, h_var; t_tm, t_var] filter_tl in
let th0 = MY_PROVE_HYP p_th th0' in
let th1 = filter_conv_raw t_tm in
TRANS th0 th1
else
INST[p_tm, p_var] filter_empty in
filter_conv_raw list_tm;;
(*
let tm = `FILTER (\n. n = 2 \/ n = 3) [1;2;3;4;2;3;1]`;;
REWRITE_CONV[FILTER; ARITH_EQ] tm;;
filter_conv_univ (REWRITE_CONV[ARITH_EQ]) tm;;
test 100 (REWRITE_CONV[FILTER; ARITH_EQ]) tm;; (* 7.596 *)
test 100 (filter_conv_univ (REWRITE_CONV[ARITH_EQ])) tm;; (* 0.236 *)
*)
(***************************)
(* MAP conversions *)
let map_conv_univ f_conv tm =
let ltm, list_tm = dest_comb tm in
let ftm = rand ltm in
let ftm_ty = type_of ftm in
let f_var = mk_var("f", ftm_ty) in
let [a_type; b_type] = snd(dest_type ftm_ty) in
let h_var = mk_var("h", a_type) in
let t_var = mk_var("t", mk_type("list", [a_type])) in
let inst_t = INST[ftm, f_var] o INST_TYPE[a_type, aty; b_type, bty] in
let map_empty, map_cons =
inst_t MAP_AB_EMPTY, inst_t MAP_AB_CONS in
let rec map_conv_raw list_tm =
if (is_comb list_tm) then
let h_tm', t_tm = dest_comb list_tm in
let h_tm = rand h_tm' in
let th0 = INST[h_tm, h_var; t_tm, t_var] map_cons in
let ltm, rtm = dest_comb (rand(concl th0)) in
let cons_tm, f_h_tm = dest_comb ltm in
let f_h_th = f_conv f_h_tm in
let map_t_th = map_conv_raw t_tm in
TRANS th0 (MK_COMB (AP_TERM cons_tm f_h_th, map_t_th))
else
map_empty in
map_conv_raw list_tm;;
(*
let tm = `MAP (\x. x + 1) [1;2;3;4;5;6;7;8;9;10;11]`;;
REWRITE_CONV[MAP] tm;;
map_conv_univ BETA_CONV tm;;
map_conv_univ (BETA_CONV THENC NUM_ADD_CONV) tm;;
test 100 (REWRITE_CONV[MAP]) tm;; (* 0.464 *)
test 100 (map_conv_univ BETA_CONV) tm;; (* 0.04 *)
test 100 (map_conv_univ (BETA_CONV THENC NUM_ADD_CONV)) tm;; (* 0.096 *)
*)
(*****************************************)
(* ALL rules *)
let ALL_A_HD = UNDISCH_ALL(prove(`ALL (P:A->bool) (CONS h t) ==> P h`, SIMP_TAC[ALL])) and
ALL_A_TL = UNDISCH_ALL(prove(`ALL (P:A->bool) (CONS h t) ==> ALL P t`, SIMP_TAC[ALL]));;
(* Given a theorem `ALL P list` returns the list of theorems (P x1),...,(P xn) *)
let get_all th =
let ltm, list_tm = dest_comb (concl th) in
let p_tm = rand ltm in
let list_ty = type_of list_tm in
let p_ty = type_of p_tm in
let ty = (hd o snd o dest_type) list_ty in
let p_var = mk_var("P", p_ty) in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", list_ty) in
let inst_t = INST[p_tm, p_var] o INST_TYPE[ty, aty] in
let all_hd, all_tl = inst_t ALL_A_HD, inst_t ALL_A_TL in
let rec get_all_raw all_th list_tm =
if (is_comb list_tm) then
let h_tm', t_tm = dest_comb list_tm in
let h_tm = rand h_tm' in
let inst_t = INST[h_tm, h_var; t_tm, t_var] in
let th_tl = MY_PROVE_HYP all_th (inst_t all_tl) in
let th_hd = MY_PROVE_HYP all_th (inst_t all_hd) in
th_hd :: get_all_raw th_tl t_tm
else
[] in
get_all_raw th list_tm;;
(* Given a theorem `ALL P list`, returns (P x_i1),..., (P x_in)
where i1,...,in are given indices.
The list of indices should be sorted *)
let select_all th indices =
let ltm, list_tm = dest_comb (concl th) in
let p_tm = rand ltm in
let list_ty = type_of list_tm in
let p_ty = type_of p_tm in
let ty = (hd o snd o dest_type) list_ty in
let p_var = mk_var("P", p_ty) in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", list_ty) in
let inst_t = INST[p_tm, p_var] o INST_TYPE[ty, aty] in
let all_hd, all_tl = inst_t ALL_A_HD, inst_t ALL_A_TL in
let rec get_all_raw all_th list_tm indices n =
match indices with
[] -> []
| i::is ->
let h_tm', t_tm = dest_comb list_tm in
let h_tm = rand h_tm' in
let inst_t = INST[h_tm, h_var; t_tm, t_var] in
let th_tl = MY_PROVE_HYP all_th (inst_t all_tl) in
if (i - n = 0) then
let th_hd = MY_PROVE_HYP all_th (inst_t all_hd) in
th_hd :: get_all_raw th_tl t_tm is (n + 1)
else
get_all_raw th_tl t_tm (i::is) (n + 1) in
get_all_raw th list_tm indices 0;;
(*
let tm = `ALL (\x. x > 3) [4; 5; 8; 10; 5; 4]`;;
let th = (EQT_ELIM o REWRITE_CONV[ALL; ARITH]) tm;;
get_all th;;
select_all th [2;3;4];;
(* 0.192 *)
test 100 (CONJUNCTS o REWRITE_RULE[ALL]) th;;
(* 0.016 *)
test 100 (get_all) th;;
(* 0.012 *)
test 100 (select_all th) [2;3;4];;
*)
(*****************************************)
(* set_of_list conversions *)
let set_of_list_conv tm =
let list_tm = rand tm in
let list_ty = type_of list_tm in
let ty = (hd o snd o dest_type) list_ty in
let h_var = mk_var("h", ty) in
let t_var = mk_var("t", list_ty) in
let inst_t = INST_TYPE[ty, aty] in
let set_of_list_h, set_of_list_cons = inst_t SET_OF_LIST_A_H, inst_t SET_OF_LIST_A_CONS in
let rec set_of_list_conv_raw = fun h_tm t_tm ->
if (is_comb t_tm) then
let h_tm', t_tm' = dest_comb t_tm in
let th0 = INST[h_tm, h_var; t_tm, t_var] set_of_list_cons in
let ltm, rtm = dest_comb(rand(concl th0)) in
TRANS th0 (AP_TERM ltm (set_of_list_conv_raw (rand h_tm') t_tm'))
else
INST[h_tm, h_var] set_of_list_h in
if (is_comb list_tm) then
let h_tm, t_tm = dest_comb list_tm in
set_of_list_conv_raw (rand h_tm) t_tm
else
inst_t SET_OF_LIST_A_EMPTY;;
(*
let tm = `set_of_list [&1; &5; &6; &3; &5; &8; &9]`;;
set_of_list_conv tm;;
(* 0.872 *)
test 1000 (REWRITE_CONV[set_of_list]) tm;;
(* 0.076 *)
test 1000 set_of_list_conv tm;;
*)
(*************************************)
(* list_sum conversions *)
let list_sum_conv f_conv tm =
let ltm, f_tm = dest_comb tm in
let list_tm = rand ltm in
let list_ty = type_of list_tm in
let f_ty = type_of f_tm in
let ty = (hd o snd o dest_type) list_ty in
let f_var = mk_var("f", f_ty) and
h_var = mk_var("h", ty) and
t_var = mk_var("t", list_ty) in
let inst_t = INST[f_tm, f_var] o INST_TYPE[ty, aty] in
let list_sum_h = inst_t LIST_SUM_A_H and
list_sum_cons = inst_t LIST_SUM_A_CONS in
let rec list_sum_conv_raw = fun h_tm t_tm ->
if (is_comb t_tm) then
let h_tm', t_tm' = dest_comb t_tm in
let th0 = INST[h_tm, h_var; t_tm, t_var] list_sum_cons in
let ltm, rtm = dest_comb(rand(concl th0)) in
let plus_op, fh_tm = dest_comb ltm in
let f_th = f_conv fh_tm in
let th1 = list_sum_conv_raw (rand h_tm') t_tm' in
let th2 = MK_COMB(AP_TERM plus_op f_th, th1) in
TRANS th0 th2
else
let th0 = INST[h_tm, h_var] list_sum_h in
let f_th = f_conv (rand(concl th0)) in
TRANS th0 f_th in
if (is_comb list_tm) then
let h_tm, t_tm = dest_comb list_tm in
list_sum_conv_raw (rand h_tm) t_tm
else
inst_t LIST_SUM_A_EMPTY;;
(*
let tm = `list_sum [&1; &3; &4; pi; #0.1] cos`;;
list_sum_conv ALL_CONV tm;;
(* 2.812 *)
test 1000 (REWRITE_CONV[list_sum; ITLIST; REAL_ADD_RID]) tm;;
(* 0.076 *)
test 1000 (list_sum_conv ALL_CONV) tm;;
let tm = `list_sum [&1; &3; &4; pi; #0.1] (\x. cos x)`;;
(* 0.104 *)
test 1000 (list_sum_conv BETA_CONV) tm;;
*)