When you see: a goal of the form P ∧ Q or P ↔ Q
Strategy: Prove each half separately.
Tactic: constructor
When your goal is a conjunction or biconditional, you can't prove it in one shot. You need to split it into pieces and prove each one. The constructor tactic does exactly this — it replaces one goal with two (or more) subgoals.
This works because P ∧ Q is defined as a structure with two fields, and P ↔ Q is (P → Q) ∧ (Q → P). The constructor tactic asks you to provide each field.
Goal shape: P ∧ Q (or P ↔ Q) Action: constructor Effect: Goal splits into two: first prove P, then prove Q Think: "I need to prove both halves."
Prove that conjunction is associative: (P ∧ Q) ∧ R ↔ P ∧ (Q ∧ R). You will need constructor multiple times.
theorem and_assoc (P Q R : Prop) : (P ∧ Q) ∧ R ↔ P ∧ (Q ∧ R) := by sorry
Start with constructor to split the iff into two implications. Each implication needs intro h, then obtain to destructure the conjunction, then exact ⟨...⟩ to rebuild it.
theorem and_assoc (P Q R : Prop) : (P ∧ Q) ∧ R ↔ P ∧ (Q ∧ R) := by
constructor
· intro ⟨⟨hp, hq⟩, hr⟩
exact ⟨hp, hq, hr⟩
· intro ⟨hp, hq, hr⟩
exact ⟨⟨hp, hq⟩, hr⟩
See also: Logic §03 — Conjunction, Logic §05 — If and only if | Proof Theory §04 — ∧-Intro