Restructure and improve Isabelle or Coq proofs to enhance readability, modularity, and maintainability without changing semantics. Use when proofs are long and monolithic, have repeated patterns, use unclear naming, lack documentation, or when the user asks to refactor, clean up, improve, or reorganize their formal proofs.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
proof-refactoring-assistant
description
Restructure and improve Isabelle or Coq proofs to enhance readability, modularity, and maintainability without changing semantics. Use when proofs are long and monolithic, have repeated patterns, use unclear naming, lack documentation, or when the user asks to refactor, clean up, improve, or reorganize their formal proofs.
Proof Refactoring Assistant
Overview
Improve proof quality by restructuring Isabelle and Coq proofs for better readability, modularity, and maintainability while preserving semantics. This skill applies proven refactoring patterns to make proofs easier to understand and maintain.
Refactoring Workflow
Step 1: Analyze Current Proof
Identify code smells and improvement opportunities:
Lemma complex_theorem : forall n m : nat,
n > 0 -> m > 0 -> n + m > 0 /\ n * m > 0.
Proof.
intros n m Hn Hm.
split.
- destruct n. inversion Hn.
destruct m. inversion Hm.
simpl. lia.
- destruct n. inversion Hn.
destruct m. inversion Hm.
simpl. apply Nat.mul_pos_pos; lia.
Qed.
After (Coq):
Lemma add_pos : forall n m : nat,
n > 0 -> m > 0 -> n + m > 0.
Proof. intros. lia. Qed.
Lemma mul_pos : forall n m : nat,
n > 0 -> m > 0 -> n * m > 0.
Proof. intros. apply Nat.mul_pos_pos; lia. Qed.
Lemma complex_theorem : forall n m : nat,
n > 0 -> m > 0 -> n + m > 0 /\ n * m > 0.
Proof.
intros. split.
- apply add_pos; assumption.
- apply mul_pos; assumption.
Qed.
Improvements:
Extracted reusable helper lemmas
Main proof now clear and concise
Helpers can be used elsewhere
Example 2: Simplify Proof Structure
Before (Coq):
Lemma add_comm : forall n m : nat, n + m = m + n.
Proof.
intros n m.
induction n.
- simpl. rewrite <- plus_n_O. reflexivity.
- simpl. rewrite IHn. rewrite <- plus_n_Sm. reflexivity.
Qed.
After (Coq):
Lemma add_comm : forall n m : nat, n + m = m + n.
Proof.
intros. lia.
Qed.
Improvements:
Replaced manual proof with automation
Much shorter and clearer
Less maintenance burden
Example 3: Improve Naming
Before (Isabelle):
lemma l1: "length (xs @ ys) = length xs + length ys"
by (induction xs) auto
lemma l2: "length (rev xs) = length xs"
by (induction xs) auto
lemma thm: "length (xs @ ys) = length xs + length ys ∧
length (rev xs) = length xs"
using l1 l2 by simp
After (Isabelle):
lemma append_length: "length (xs @ ys) = length xs + length ys"
by (induction xs) auto
lemma rev_length: "length (rev xs) = length xs"
by (induction xs) auto
lemma list_length_properties:
"length (xs @ ys) = length xs + length ys ∧
length (rev xs) = length xs"
using append_length rev_length by simp
Improvements:
Descriptive names indicate what each lemma proves
Follows naming conventions
Easier to find and understand
Example 4: Add Documentation
Before (Coq):
Lemma partition_spec : forall (A : Type) (f : A -> bool) (l : list A),
let (l1, l2) := partition f l in
filter f l = l1 /\ filter (fun x => negb (f x)) l = l2.
Proof.
(* Complex 20-line proof *)
Admitted.
After (Coq):
(** Specification of list partition function.
Given a predicate f and a list l, partition splits l into two lists:
- l1 contains all elements satisfying f
- l2 contains all elements not satisfying f
This lemma proves that partition is equivalent to filtering twice.
Proof strategy: Induction on l, with case analysis on f(head).
*)
Lemma partition_spec : forall (A : Type) (f : A -> bool) (l : list A),
let (l1, l2) := partition f l in
filter f l = l1 /\ filter (fun x => negb (f x)) l = l2.
Proof.
(* Complex 20-line proof *)
Admitted.
Improvements:
Clear explanation of what lemma proves
Documents proof strategy
Easier for others to understand
Example 5: Break Down Long Proof
Before (Isabelle):
lemma complex_cases: "P x"
proof (cases x)
case (C1 a b c)
(* 15 lines of proof *)
then show ?thesis by auto
next
case (C2 d e)
(* 12 lines of proof *)
then show ?thesis by auto
next
case (C3 f)
(* 10 lines of proof *)
then show ?thesis by auto
qed
After (Isabelle):
lemma case_C1: "⋀a b c. x = C1 a b c ⟹ P x"
(* 15 lines of proof *)
by auto
lemma case_C2: "⋀d e. x = C2 d e ⟹ P x"
(* 12 lines of proof *)
by auto
lemma case_C3: "⋀f. x = C3 f ⟹ P x"
(* 10 lines of proof *)
by auto
lemma complex_cases: "P x"
by (cases x) (auto simp: case_C1 case_C2 case_C3)
Improvements:
Each case in separate lemma
Main proof now simple
Cases can be tested independently
Example 6: Strengthen Induction Hypothesis
Before (Coq):
Fixpoint sum (n : nat) : nat :=
match n with
| 0 => 0
| S n' => n + sum n'
end.
Lemma sum_formula : forall n : nat, 2 * sum n = n * (n + 1).
Proof.
induction n.
- reflexivity.
- simpl. (* Gets stuck - IH not strong enough *)
Admitted.
After (Coq):
(* Strengthen by generalizing with accumulator *)
Lemma sum_formula_gen : forall n acc : nat,
2 * (sum n + acc) = n * (n + 1) + 2 * acc.
Proof.
induction n; intros.
- simpl. lia.
- simpl. rewrite IHn. lia.
Qed.
Lemma sum_formula : forall n : nat, 2 * sum n = n * (n + 1).
Proof.
intros. pose proof (sum_formula_gen n 0). lia.
Qed.
Improvements:
Generalized lemma with stronger IH
Original lemma now follows easily
Proof completes successfully
Refactoring Guidelines
When to Refactor
Good times:
After proof works but before moving on
When adding related proofs
During code review
When proof is hard to understand
Before major changes
Bad times:
While proof is still broken
Under tight deadline
Without understanding the proof
When it already works well
What to Refactor
High priority:
Long, monolithic proofs
Unclear naming
Missing documentation
Duplicated code
Overly complex tactics
Low priority:
Working proofs that are clear
Well-structured code
Good naming and documentation
Appropriate abstraction level
How Much to Refactor
Balance:
Improve readability vs. time spent
Modularity vs. over-engineering
Generality vs. simplicity
Documentation vs. verbosity
Guidelines:
Stop when proof is clear and maintainable
Don't over-abstract
Keep it simple
Follow project conventions
Best Practices
Understand before refactoring: Know what the proof does
One change at a time: Incremental refactoring
Test continuously: Verify after each change
Preserve semantics: Don't change what's proved
Follow conventions: Match project style
Document complex parts: Add helpful comments
Use automation wisely: When it improves clarity
Keep it simple: Don't over-engineer
Anti-Patterns to Avoid
Over-extraction: Too many tiny lemmas
Premature generalization: Generalize before understanding
Inconsistent naming: No naming convention
Over-documentation: Obvious comments
Breaking working code: Refactor without testing
Ignoring performance: Slow compilation after refactoring