l3lab/ntp-mathlib huggingface dataset:
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> 

Proof state:
case id.left
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
⊢ {
          obj := fun x =>
            match x with
            | zero => X
            | one => Y,
          map := fun {X_1 Y_1} h =>
            match X_1, Y_1, h with
            | x, .(x), WalkingParallelPairHom.id .(x) =>
              𝟙
                ((fun x =>
                    match x with
                    | zero => X
                    | one => Y)
                  x)
            | .(zero), .(one), left => f
            | .(zero), .(one), right => g }.map
      (WalkingParallelPairHom.id zero ≫ left) =
    {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        (WalkingParallelPairHom.id zero) ≫
      {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        left

Next tactic:
{dsimp; simp}
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> {

Proof state:
case id.left
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
⊢ {
          obj := fun x =>
            match x with
            | zero => X
            | one => Y,
          map := fun {X_1 Y_1} h =>
            match X_1, Y_1, h with
            | x, .(x), WalkingParallelPairHom.id .(x) =>
              𝟙
                ((fun x =>
                    match x with
                    | zero => X
                    | one => Y)
                  x)
            | .(zero), .(one), left => f
            | .(zero), .(one), right => g }.map
      (WalkingParallelPairHom.id zero ≫ left) =
    {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        (WalkingParallelPairHom.id zero) ≫
      {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        left

Next tactic:
dsimp
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> {dsimp; 

Proof state:
case id.left
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
⊢ (match zero, one, 𝟙 zero ≫ left with
    | x, .(x), WalkingParallelPairHom.id .(x) =>
      𝟙
        (match x with
        | zero => X
        | one => Y)
    | .(zero), .(one), left => f
    | .(zero), .(one), right => g) =
    𝟙 X ≫ f

Next tactic:
simp
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> 

Proof state:
case id.right
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
⊢ {
          obj := fun x =>
            match x with
            | zero => X
            | one => Y,
          map := fun {X_1 Y_1} h =>
            match X_1, Y_1, h with
            | x, .(x), WalkingParallelPairHom.id .(x) =>
              𝟙
                ((fun x =>
                    match x with
                    | zero => X
                    | one => Y)
                  x)
            | .(zero), .(one), left => f
            | .(zero), .(one), right => g }.map
      (WalkingParallelPairHom.id zero ≫ right) =
    {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        (WalkingParallelPairHom.id zero) ≫
      {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        right

Next tactic:
{dsimp; simp}
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> {

Proof state:
case id.right
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
⊢ {
          obj := fun x =>
            match x with
            | zero => X
            | one => Y,
          map := fun {X_1 Y_1} h =>
            match X_1, Y_1, h with
            | x, .(x), WalkingParallelPairHom.id .(x) =>
              𝟙
                ((fun x =>
                    match x with
                    | zero => X
                    | one => Y)
                  x)
            | .(zero), .(one), left => f
            | .(zero), .(one), right => g }.map
      (WalkingParallelPairHom.id zero ≫ right) =
    {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        (WalkingParallelPairHom.id zero) ≫
      {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        right

Next tactic:
dsimp
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> {dsimp; 

Proof state:
case id.right
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
⊢ (match zero, one, 𝟙 zero ≫ right with
    | x, .(x), WalkingParallelPairHom.id .(x) =>
      𝟙
        (match x with
        | zero => X
        | one => Y)
    | .(zero), .(one), left => f
    | .(zero), .(one), right => g) =
    𝟙 X ≫ g

Next tactic:
simp
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> 

Proof state:
case id.id
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
X✝ : WalkingParallelPair
⊢ {
          obj := fun x =>
            match x with
            | zero => X
            | one => Y,
          map := fun {X_1 Y_1} h =>
            match X_1, Y_1, h with
            | x, .(x), WalkingParallelPairHom.id .(x) =>
              𝟙
                ((fun x =>
                    match x with
                    | zero => X
                    | one => Y)
                  x)
            | .(zero), .(one), left => f
            | .(zero), .(one), right => g }.map
      (WalkingParallelPairHom.id X✝ ≫ WalkingParallelPairHom.id X✝) =
    {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        (WalkingParallelPairHom.id X✝) ≫
      {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        (WalkingParallelPairHom.id X✝)

Next tactic:
{dsimp; simp}
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> {

Proof state:
case id.id
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
X✝ : WalkingParallelPair
⊢ {
          obj := fun x =>
            match x with
            | zero => X
            | one => Y,
          map := fun {X_1 Y_1} h =>
            match X_1, Y_1, h with
            | x, .(x), WalkingParallelPairHom.id .(x) =>
              𝟙
                ((fun x =>
                    match x with
                    | zero => X
                    | one => Y)
                  x)
            | .(zero), .(one), left => f
            | .(zero), .(one), right => g }.map
      (WalkingParallelPairHom.id X✝ ≫ WalkingParallelPairHom.id X✝) =
    {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        (WalkingParallelPairHom.id X✝) ≫
      {
            obj := fun x =>
              match x with
              | zero => X
              | one => Y,
            map := fun {X_1 Y_1} h =>
              match X_1, Y_1, h with
              | x, .(x), WalkingParallelPairHom.id .(x) =>
                𝟙
                  ((fun x =>
                      match x with
                      | zero => X
                      | one => Y)
                    x)
              | .(zero), .(one), left => f
              | .(zero), .(one), right => g }.map
        (WalkingParallelPairHom.id X✝)

Next tactic:
dsimp
/-- `parallelPair f g` is the diagram in `C` consisting of the two morphisms `f` and `g` with
    common domain and codomain. -/
def parallelPair (f g : X ⟶ Y) : WalkingParallelPair ⥤ C where
  obj x :=
    match x with
    | zero => X
    | one => Y
  map h :=
    match h with
    | WalkingParallelPairHom.id _ => 𝟙 _
    | left => f
    | right => g
  -- `sorry` can cope with this, but it's too slow:
  map_comp := by
    rintro _ _ _ ⟨⟩ g <;> cases g <;> {dsimp; 

Proof state:
case id.id
C : Type u
inst✝ : Category.{v, u} C
X Y : C
f g : X ⟶ Y
X✝ : WalkingParallelPair
⊢ (match X✝, X✝, 𝟙 X✝ ≫ 𝟙 X✝ with
    | x, .(x), WalkingParallelPairHom.id .(x) =>
      𝟙
        (match x with
        | zero => X
        | one => Y)
    | .(zero), .(one), left => f
    | .(zero), .(one), right => g) =
    𝟙
        (match X✝ with
        | zero => X
        | one => Y) ≫
      𝟙
        (match X✝ with
        | zero => X
        | one => Y)

Next tactic:
simp
@[simp]
theorem parallelPair_functor_obj {F : WalkingParallelPair ⥤ C} (j : WalkingParallelPair) :
    (parallelPair (F.map left) (F.map right)).obj j = F.obj j := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
j : WalkingParallelPair
⊢ (parallelPair (F.map left) (F.map right)).obj j = F.obj j

Next tactic:
cases j
@[simp]
theorem parallelPair_functor_obj {F : WalkingParallelPair ⥤ C} (j : WalkingParallelPair) :
    (parallelPair (F.map left) (F.map right)).obj j = F.obj j := by cases j <;> 

Proof state:
case zero
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
⊢ (parallelPair (F.map left) (F.map right)).obj zero = F.obj zero

Next tactic:
rfl
@[simp]
theorem parallelPair_functor_obj {F : WalkingParallelPair ⥤ C} (j : WalkingParallelPair) :
    (parallelPair (F.map left) (F.map right)).obj j = F.obj j := by cases j <;> 

Proof state:
case one
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
⊢ (parallelPair (F.map left) (F.map right)).obj one = F.obj one

Next tactic:
rfl
/-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) :=
  NatIso.ofComponents (fun j => eqToIso <| by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
j : WalkingParallelPair
⊢ F.obj j = (parallelPair (F.map left) (F.map right)).obj j

Next tactic:
cases j
/-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) :=
  NatIso.ofComponents (fun j => eqToIso <| by cases j <;> 

Proof state:
case zero
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
⊢ F.obj zero = (parallelPair (F.map left) (F.map right)).obj zero

Next tactic:
rfl
/-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) :=
  NatIso.ofComponents (fun j => eqToIso <| by cases j <;> 

Proof state:
case one
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
⊢ F.obj one = (parallelPair (F.map left) (F.map right)).obj one

Next tactic:
rfl
/-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) :=
  NatIso.ofComponents (fun j => eqToIso <| by cases j <;> rfl) (by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
⊢ ∀ {X Y : WalkingParallelPair} (f : X ⟶ Y),
    F.map f ≫ ((fun j => eqToIso (_ : F.obj j = (parallelPair (F.map left) (F.map right)).obj j)) Y).hom =
      ((fun j => eqToIso (_ : F.obj j = (parallelPair (F.map left) (F.map right)).obj j)) X).hom ≫
        (parallelPair (F.map left) (F.map right)).map f

Next tactic:
rintro _ _ (_|_|_)
/-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) :=
  NatIso.ofComponents (fun j => eqToIso <| by cases j <;> rfl) (by rintro _ _ (_|_|_) <;> 

Proof state:
case left
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
⊢ F.map left ≫ ((fun j => eqToIso (_ : F.obj j = (parallelPair (F.map left) (F.map right)).obj j)) one).hom =
    ((fun j => eqToIso (_ : F.obj j = (parallelPair (F.map left) (F.map right)).obj j)) zero).hom ≫
      (parallelPair (F.map left) (F.map right)).map left

Next tactic:
simp
/-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) :=
  NatIso.ofComponents (fun j => eqToIso <| by cases j <;> rfl) (by rintro _ _ (_|_|_) <;> 

Proof state:
case right
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
⊢ F.map right ≫ ((fun j => eqToIso (_ : F.obj j = (parallelPair (F.map left) (F.map right)).obj j)) one).hom =
    ((fun j => eqToIso (_ : F.obj j = (parallelPair (F.map left) (F.map right)).obj j)) zero).hom ≫
      (parallelPair (F.map left) (F.map right)).map right

Next tactic:
simp
/-- Every functor indexing a (co)equalizer is naturally isomorphic (actually, equal) to a
    `parallelPair` -/
@[simps!]
def diagramIsoParallelPair (F : WalkingParallelPair ⥤ C) :
    F ≅ parallelPair (F.map left) (F.map right) :=
  NatIso.ofComponents (fun j => eqToIso <| by cases j <;> rfl) (by rintro _ _ (_|_|_) <;> 

Proof state:
case id
C : Type u
inst✝ : Category.{v, u} C
X Y : C
F : WalkingParallelPair ⥤ C
X✝ : WalkingParallelPair
⊢ F.map (WalkingParallelPairHom.id X✝) ≫
      ((fun j => eqToIso (_ : F.obj j = (parallelPair (F.map left) (F.map right)).obj j)) X✝).hom =
    ((fun j => eqToIso (_ : F.obj j = (parallelPair (F.map left) (F.map right)).obj j)) X✝).hom ≫
      (parallelPair (F.map left) (F.map right)).map (WalkingParallelPairHom.id X✝)

Next tactic:
simp
/-- Construct a morphism between parallel pairs. -/
def parallelPairHom {X' Y' : C} (f g : X ⟶ Y) (f' g' : X' ⟶ Y') (p : X ⟶ X') (q : Y ⟶ Y')
    (wf : f ≫ q = p ≫ f') (wg : g ≫ q = p ≫ g') : parallelPair f g ⟶ parallelPair f' g'
    where
  app j :=
    match j with
    | zero => p
    | one => q
  naturality := by
    

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y X' Y' : C
f g : X ⟶ Y
f' g' : X' ⟶ Y'
p : X ⟶ X'
q : Y ⟶ Y'
wf : f ≫ q = p ≫ f'
wg : g ≫ q = p ≫ g'
⊢ ∀ ⦃X_1 Y_1 : WalkingParallelPair⦄ (f_1 : X_1 ⟶ Y_1),
    (parallelPair f g).map f_1 ≫
        (fun j =>
            match j with
            | zero => p
            | one => q)
          Y_1 =
      (fun j =>
            match j with
            | zero => p
            | one => q)
          X_1 ≫
        (parallelPair f' g').map f_1

Next tactic:
rintro _ _ ⟨⟩
/-- Construct a morphism between parallel pairs. -/
def parallelPairHom {X' Y' : C} (f g : X ⟶ Y) (f' g' : X' ⟶ Y') (p : X ⟶ X') (q : Y ⟶ Y')
    (wf : f ≫ q = p ≫ f') (wg : g ≫ q = p ≫ g') : parallelPair f g ⟶ parallelPair f' g'
    where
  app j :=
    match j with
    | zero => p
    | one => q
  naturality := by
    rintro _ _ ⟨⟩ <;> 

Proof state:
case left
C : Type u
inst✝ : Category.{v, u} C
X Y X' Y' : C
f g : X ⟶ Y
f' g' : X' ⟶ Y'
p : X ⟶ X'
q : Y ⟶ Y'
wf : f ≫ q = p ≫ f'
wg : g ≫ q = p ≫ g'
⊢ (parallelPair f g).map left ≫
      (fun j =>
          match j with
          | zero => p
          | one => q)
        one =
    (fun j =>
          match j with
          | zero => p
          | one => q)
        zero ≫
      (parallelPair f' g').map left

Next tactic:
{dsimp; simp [wf,wg]}
/-- Construct a morphism between parallel pairs. -/
def parallelPairHom {X' Y' : C} (f g : X ⟶ Y) (f' g' : X' ⟶ Y') (p : X ⟶ X') (q : Y ⟶ Y')
    (wf : f ≫ q = p ≫ f') (wg : g ≫ q = p ≫ g') : parallelPair f g ⟶ parallelPair f' g'
    where
  app j :=
    match j with
    | zero => p
    | one => q
  naturality := by
    rintro _ _ ⟨⟩ <;> {

Proof state:
case left
C : Type u
inst✝ : Category.{v, u} C
X Y X' Y' : C
f g : X ⟶ Y
f' g' : X' ⟶ Y'
p : X ⟶ X'
q : Y ⟶ Y'
wf : f ≫ q = p ≫ f'
wg : g ≫ q = p ≫ g'
⊢ (parallelPair f g).map left ≫
      (fun j =>
          match j with
          | zero => p
          | one => q)
        one =
    (fun j =>
          match j with
          | zero => p
          | one => q)
        zero ≫
      (parallelPair f' g').map left

Next tactic:
dsimp
/-- Construct a morphism between parallel pairs. -/
def parallelPairHom {X' Y' : C} (f g : X ⟶ Y) (f' g' : X' ⟶ Y') (p : X ⟶ X') (q : Y ⟶ Y')
    (wf : f ≫ q = p ≫ f') (wg : g ≫ q = p ≫ g') : parallelPair f g ⟶ parallelPair f' g'
    where
  app j :=
    match j with
    | zero => p
    | one => q
  naturality := by
    rintro _ _ ⟨⟩ <;> {dsimp; 

Proof state:
case left
C : Type u
inst✝ : Category.{v, u} C
X Y X' Y' : C
f g : X ⟶ Y
f' g' : X' ⟶ Y'
p : X ⟶ X'
q : Y ⟶ Y'
wf : f ≫ q = p ≫ f'
wg : g ≫ q = p ≫ g'
⊢ f ≫ q = p ≫ f'

Next tactic:
simp [wf,wg]