Zulip Chat Archive

Stream: new members

Topic: golfing help


Jack J Garzella (Aug 23 2022 at 05:25):

Hi,

I'm struggling how to figure out how to write proofs that aren't super super long. In particular, my current workflow is to write a bunch of have statements and then rewrite using them. This matches my mental model of how I think about how I would prove something on paper--in particular the have statements seem to be nice for communicating a proof to a human. However, they get quite cumbersome and people who answer my questions here (thanks again, especially @Adam Topaz ) seem to be able to prove things more efficiently. Or at least, they know how to golf all of the have statements away.

A good example is the following lemma, part of proving that a monoid object in the category of types is a monoid:

Each of the have statements/auxillary lemmas pretty much comes down to simp. Does anyone have any tips and tricks on how one golfs such a proof?

Andrew Yang (Aug 23 2022 at 06:24):

This is how I would have approached this problem:

instance : monoidal_category (Type u) :=
  monoidal_of_has_finite_products (Type u)

instance has_one_of_Mon__Type (M : Mon_ (Type u)) : has_one M.X :=
{ one := ((terminal_iso.symm.hom  M.one) punit.star) }

instance has_mul_of_Mon__Type (M : Mon_ (Type u)) : has_mul M.X :=
{ mul := (λ a b, ((binary_product_iso _ _).symm.hom  M.mul) (a,b)) }

lemma one_mul_of_Mon__Type (M : Mon_ (Type u)) :  (a : M.X), 1 * a = a :=
begin
  intro a,
  dsimp [has_mul.mul, has_one.one],
  have : (binary_product_iso _ _).inv  (M.one  𝟙 M.X)  M.mul =
    (binary_product_iso _ _).inv  (λ_ M.X).hom,
  { rw M.one_mul },
  convert _root_.congr_fun this (terminal_iso.inv punit.star, a),
  { have : function.injective (binary_product_iso M.X M.X).hom,
    { rw  mono_iff_injective, apply_instance },
    apply this,
    ext; simp [elementwise_of (limits.prod.map_fst M.one (𝟙 M.X)),
      elementwise_of (limits.prod.map_snd M.one (𝟙 M.X))] },
  { simp }
end

This is roughly how I came up with this proof:

  1. I know that the proof "is just M.one_mul", so I first applied a into M.one_mul (by composing with binary_product_iso and using congr_fun.
  2. I applied simp on both the goal and the hypothesis obtained, and see what I have. In this case the hypothesis already looks like the goal, so I used convert.
  3. In the lhs, the two elements (in limits.prod _ _) are equal since the components are (this is usually done by ext). I moved into prod since the extlemmas there looks better.
  4. Apply simp again. The only barrier seems to be limits.prod.fst (limits.prod.map foo) so the elementwise_of versions of them are provided. simp then closes the goal.
  5. The rhs can also be closed by simp.

Jack J Garzella (Aug 23 2022 at 23:00):

Ok, I have one question:

how would I "use congr_fun" without knowing that I already had to use the convert tactic? All of the tactics I use seem to give errors.

Andrew Yang (Aug 23 2022 at 23:30):

I would first have := _root_.congr_fun this (terminal_iso.inv punit.star, a)
And then I could simp at this ⊢.


Last updated: Dec 20 2023 at 11:08 UTC