let aacons_tm = `CONS:A -> A list -> A list` ;; let HD_CONV conv tm = let h::rest = dest_list tm in let ty = type_of h in let thm = conv h in let thm2 = REFL (mk_list(rest,ty)) in let cs = inst [ty,aty] aacons_tm in MK_COMB ((AP_TERM cs thm),thm2);; let TL_CONV conv tm = (* try *) let h::t = dest_list tm in let lty = type_of h in let cs = inst [lty,aty] aacons_tm in MK_COMB ((AP_TERM cs (REFL h)), (LIST_CONV conv (mk_list(t,lty)))) (* with _ -> failwith "TL_CONV" *) let rec EL_CONV conv i tm = if i = 0 then HD_CONV conv tm else let h::t = dest_list tm in let lty = type_of h in let cs = inst [lty,aty] aacons_tm in MK_COMB ((AP_TERM cs (REFL h)), (EL_CONV conv (i - 1) (mk_list(t,lty)))) (* let conv = (REWRITE_CONV[ARITH_RULE `x + x = &2 * x`]) let tm = `[&5 + &5; &6 + &6; &7 + &7]` HD_CONV conv tm TL_CONV conv tm HD_CONV(TL_CONV conv) tm CONS_CONV conv tm EL_CONV conv 0 tm EL_CONV conv 1 tm EL_CONV conv 2 tm *) let NOT_CONS = prove_by_refinement( `!l. (~ ?(h:A) t. (l = CONS h t)) ==> (l = [])`, (* {{{ Proof *) [ MESON_TAC[list_CASES]; ]);; (* }}} *) let REMOVE = new_recursive_definition list_RECURSION `(REMOVE x [] = []) /\ (REMOVE x (CONS (h:A) t) = let rest = REMOVE x t in if x = h then rest else CONS h rest)`;; let CHOP_LIST = new_recursive_definition num_RECURSION `(CHOP_LIST 0 l = [],l) /\ (CHOP_LIST (SUC n) l = let a,b = CHOP_LIST n (TL l) in CONS (HD l) a,b)`;; let REM_NIL = prove( `REMOVE x [] = []`, MESON_TAC[REMOVE]);; let REM_FALSE = prove_by_refinement( `!x l. ~(MEM x (REMOVE x l))`, (* {{{ Proof *) [ STRIP_TAC; LIST_INDUCT_TAC; ASM_MESON_TAC[MEM;REM_NIL]; CASES_ON `x = h`; ASM_REWRITE_TAC[]; ASM_REWRITE_TAC[REMOVE;LET_DEF;LET_END_DEF]; ASM_MESON_TAC[]; ASM_REWRITE_TAC[REMOVE;LET_DEF;LET_END_DEF]; ASM_MESON_TAC[MEM]; ]);; (* }}} *) let MEM_REMOVE = prove_by_refinement( `!x y z l. MEM x (REMOVE y l) ==> MEM x (REMOVE y (CONS z l))`, (* {{{ Proof *) [ REPEAT_N 3 STRIP_TAC; CASES_ON `y = z`; ASM_REWRITE_TAC[REMOVE;LET_DEF;LET_END_DEF]; ASM_REWRITE_TAC[REMOVE;LET_DEF;LET_END_DEF]; ASM_MESON_TAC[MEM]; ]);; (* }}} *) let REM_NEQ = prove_by_refinement( `!x x1 l. MEM x l /\ ~(x = x1) ==> MEM x (REMOVE x1 l)`, (* {{{ Proof *) [ STRIP_TAC THEN STRIP_TAC; LIST_INDUCT_TAC; MESON_TAC[MEM]; CASES_ON `x = h`; POP_ASSUM SUBST1_TAC; STRIP_TAC; ASM_REWRITE_TAC[REMOVE;LET_DEF;LET_END_DEF;COND_CLAUSES;MEM]; STRIP_TAC; CLAIM `MEM x t`; ASM_MESON_TAC[MEM]; STRIP_TAC; CLAIM `MEM x (REMOVE x1 t)`; ASM_MESON_TAC[]; STRIP_TAC; MATCH_MP_TAC MEM_REMOVE; FIRST_ASSUM MATCH_ACCEPT_TAC; ]);; (* }}} *) let LAST_SING = prove_by_refinement( `!h. LAST [h] = h`, (* {{{ Proof *) [ MESON_TAC[LAST]; ]);; (* }}} *) let LAST_CONS = prove_by_refinement( `!h t. ~(t = []) ==> (LAST (CONS h t) = LAST t)`, (* {{{ Proof *) [ ASM_MESON_TAC[LAST]; ]);; (* }}} *) let LAST_CONS_CONS = prove_by_refinement( `!h1 h2 t. ~(t = []) ==> (LAST (CONS h1 (CONS h2 t)) = LAST (CONS h1 t))`, (* {{{ Proof *) [ REWRITE_TAC[LAST;NOT_CONS_NIL]; MESON_TAC[LAST;NOT_CONS_NIL;COND_CLAUSES]; ]);; (* }}} *) let HD_APPEND = prove_by_refinement( `!h t l. HD (APPEND (CONS h t) l) = h`, (* {{{ Proof *) [ ASM_MESON_TAC[HD;APPEND]; ]);; (* }}} *) let LENGTH_0 = prove_by_refinement( `!l. (LENGTH l = 0) <=> (l = [])`, (* {{{ Proof *) [ LIST_INDUCT_TAC; REWRITE_TAC[LENGTH]; ASM_MESON_TAC[LENGTH;NOT_CONS_NIL;ARITH_RULE `~(0 = SUC n)`]; ]);; (* }}} *) let LENGTH_1 = prove_by_refinement( `!l. (LENGTH l = 1) <=> ?x. l = [x]`, (* {{{ Proof *) [ LIST_INDUCT_TAC; EQ_TAC; MESON_TAC[LENGTH;ARITH_RULE `~(1 = 0)`]; MESON_TAC[NOT_CONS_NIL]; EQ_TAC; REWRITE_TAC[LENGTH;ARITH_RULE `~(0 = 1)`]; REWRITE_TAC[LENGTH]; STRIP_TAC; CLAIM `LENGTH t = 0`; POP_ASSUM MP_TAC THEN ARITH_TAC; STRIP_TAC; CLAIM `t = []`; ASM_MESON_TAC[LENGTH_0]; STRIP_TAC; ASM_REWRITE_TAC[]; ASM_MESON_TAC[]; STRIP_TAC; ASM_MESON_TAC[LENGTH;ONE]; ]);; (* }}} *) let LIST_TRI = prove_by_refinement( `!p. (p = []) \/ (?x. p = [x:A]) \/ (?x y t. p = CONS x (CONS y t))`, (* {{{ Proof *) [ STRIP_TAC; DISJ_CASES_TAC (ISPEC `p:A list` list_CASES); ASM_REWRITE_TAC[]; POP_ASSUM MP_TAC THEN STRIP_TAC; DISJ_CASES_TAC (ISPEC `t:A list` list_CASES); ASM_MESON_TAC[]; ASM_MESON_TAC[]; ]);; (* }}} *) let LENGTH_PAIR = prove_by_refinement( `!p. (LENGTH p = 2) <=> ?h t. p = [h:A; t]`, (* {{{ Proof *) [ STRIP_TAC THEN EQ_TAC; STRIP_TAC; MP_TAC (ISPEC `p:A list` list_CASES); STRIP_TAC; ASM_MESON_TAC[LENGTH_0;ARITH_RULE `~(2 = 0)`]; MP_TAC (ISPEC `t:A list` list_CASES); STRIP_TAC; ASM_MESON_TAC[LENGTH_1;ARITH_RULE `~(1 = 2)`]; MP_TAC (ISPEC `t':A list` list_CASES); STRIP_TAC; EXISTS_TAC `h:A`; EXISTS_TAC `h':A`; ASM_MESON_TAC[]; CLAIM `p = CONS h (CONS h' (CONS h'' t''))`; ASM_MESON_TAC[]; STRIP_TAC; CLAIM `2 < LENGTH p`; POP_ASSUM SUBST1_TAC; REWRITE_TAC[LENGTH]; ARITH_TAC; ASM_MESON_TAC[LT_REFL]; STRIP_TAC; ASM_REWRITE_TAC[LENGTH]; ARITH_TAC; ]);; (* }}} *) let LENGTH_SING = prove_by_refinement( `!p. (LENGTH p = 1) <=> ?h. p = [h:A]`, (* {{{ Proof *) [ STRIP_TAC THEN EQ_TAC; STRIP_TAC; MP_TAC (ISPEC `p:A list` list_CASES); STRIP_TAC; ASM_MESON_TAC[LENGTH_0;ARITH_RULE `~(1 = 0)`]; MP_TAC (ISPEC `t:A list` list_CASES); STRIP_TAC; EXISTS_TAC `h:A`; ASM_MESON_TAC[]; CLAIM `p = CONS h (CONS h' t')`; ASM_MESON_TAC[]; STRIP_TAC; CLAIM `1 < LENGTH p`; POP_ASSUM SUBST1_TAC; REWRITE_TAC[LENGTH]; ARITH_TAC; ASM_REWRITE_TAC[]; ARITH_TAC; STRIP_TAC; ASM_REWRITE_TAC[LENGTH;]; ARITH_TAC; ]);; (* }}} *) let TL_NIL = prove_by_refinement( `!l. ~(l = []) ==> ((TL l = []) <=> ?x. l = [x])`, (* {{{ Proof *) [ REPEAT STRIP_TAC THEN EQ_TAC; CLAIM `?h t. l = CONS h t`; ASM_MESON_TAC[list_CASES]; STRIP_TAC; ASM_REWRITE_TAC[TL]; ASM_MESON_TAC !LIST_REWRITES; ASM_MESON_TAC !LIST_REWRITES; ]);; (* }}} *) let LAST_TL = prove_by_refinement( `!l. ~(l = []) /\ ~(TL l = []) ==> (LAST (TL l) = LAST l)`, (* {{{ Proof *) [ LIST_INDUCT_TAC; REWRITE_TAC[]; REWRITE_TAC[TL;LAST]; ASM_MESON_TAC[NOT_CONS_NIL]; ]);; (* }}} *) let LENGTH_TL = prove_by_refinement( `!l. ~(l = []) /\ ~(TL l = []) ==> (LENGTH (TL l) = PRE(LENGTH l))`, (* {{{ Proof *) [ LIST_INDUCT_TAC; REWRITE_TAC[]; REPEAT STRIP_TAC; LIST_SIMP_TAC; NUM_SIMP_TAC; ]);; (* }}} *) let LENGTH_NZ = prove_by_refinement( `!p. 0 < LENGTH p <=> ~(p = [])`, (* {{{ Proof *) [ REPEAT STRIP_TAC; EQ_TAC; ASM_MESON_TAC[LENGTH;NOT_CONS_NIL;LT_REFL]; REWRITE_TAC[LENGTH;NOT_CONS_NIL;LT_REFL;NOT_NIL]; STRIP_TAC THEN ASM_REWRITE_TAC[]; REWRITE_TAC[LENGTH]; ARITH_TAC; ]);; (* }}} *)