Dealing with let-in expressions in current goal
Question
I got stuck while doing some coq proofs around the state monad. Concretely, I've simplified the situation to this proof:
Definition my_call {A B C} (f : A -> B * C) (a : A) : B * C := let (b, c) := f a in (b, c).forall (A B C : Type) (f : A -> B * C) (a : A), my_call f a = f aforall (A B C : Type) (f : A -> B * C) (a : A), my_call f a = f aA, B, C: Type
f: A -> B * C
a: Amy_call f a = f a(* stuck! *)A, B, C: Type
f: A -> B * C
a: A(let (b, c) := f a in (b, c)) = f a
The resulting goal after invoking unfold is
If I'm not wrong, both sides of the equality should be exactly the same, but I don't know how to show it from here. Any help?
As a side note, I've seen that coq automatically applies the simplification when no product types are involved in the result of the function:
Definition my_call' {A B : Type} (f : A -> B) (a : A) : B := let b := f a in b.forall (A B : Type) (f : A -> B) (a : A), my_call' f a = f aforall (A B : Type) (f : A -> B) (a : A), my_call' f a = f aA, B: Type
f: A -> B
a: Amy_call' f a = f areflexivity. Qed.A, B: Type
f: A -> B
a: Af a = f a
Answer
It's easy to see what you need to do next, once you recall that
let (b, c) := f a in (b, c)
is syntactic sugar for
match f a with (b, c) => (b, c) end
This means you need to destruct on f a to finish the proof:
A, B, C: Type
f: A -> B * C
a: Amy_call f a = f aA, B, C: Type
f: A -> B * C
a: Amy_call f a = f anow destruct (f a). Qed.A, B, C: Type
f: A -> B * C
a: A(let (b, c) := f a in (b, c)) = f a
A: Note that you can Set Printing All to make the syntactic sugar go away.
A: With pairs defined with primitive projections (as here), we can prove mycall_is_call lemma using just reflexivity.