l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem infinite_sum : Infinite (Sum α β) ↔ Infinite α ∨ Infinite β := by
  refine' ⟨fun H => _, fun H => H.elim (@Sum.infinite_of_left α β) (@Sum.infinite_of_right α β)⟩
  contrapose! H; haveI := fintypeOfNotInfinite H.1; haveI := fintypeOfNotInfinite H.2
  

Proof state:
α : Type u_1
β : Type u_2
H : ¬Infinite α ∧ ¬Infinite β
this✝ : Fintype α
this : Fintype β
⊢ ¬Infinite (α ⊕ β)

Next tactic:
exact Infinite.false
@[simps]
def Foldl.ofFreeMonoid (f : β → α → β) : FreeMonoid α →* Monoid.Foldl β
    where
  toFun xs := op <| flip (List.foldl f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by
    

Proof state:
m : Type u → Type u
inst✝ : Monad m
α β : Type u
f : β → α → β
⊢ ∀ (x y : FreeMonoid α),
    OneHom.toFun
        { toFun := fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs)),
          map_one' :=
            (_ :
              (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1 =
                (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1) }
        (x * y) =
      OneHom.toFun
          { toFun := fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs)),
            map_one' :=
              (_ :
                (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1 =
                  (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1) }
          x *
        OneHom.toFun
          { toFun := fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs)),
            map_one' :=
              (_ :
                (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1 =
                  (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1) }
          y

Next tactic:
intros
@[simps]
def Foldl.ofFreeMonoid (f : β → α → β) : FreeMonoid α →* Monoid.Foldl β
    where
  toFun xs := op <| flip (List.foldl f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by
    intros; 

Proof state:
m : Type u → Type u
inst✝ : Monad m
α β : Type u
f : β → α → β
x✝ y✝ : FreeMonoid α
⊢ OneHom.toFun
      { toFun := fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs)),
        map_one' :=
          (_ :
            (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1 =
              (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1) }
      (x✝ * y✝) =
    OneHom.toFun
        { toFun := fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs)),
          map_one' :=
            (_ :
              (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1 =
                (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1) }
        x✝ *
      OneHom.toFun
        { toFun := fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs)),
          map_one' :=
            (_ :
              (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1 =
                (fun xs => op (flip (List.foldl f) (FreeMonoid.toList xs))) 1) }
        y✝

Next tactic:
simp only [FreeMonoid.toList_mul, flip, unop_op, List.foldl_append, op_inj]
@[simps]
def Foldl.ofFreeMonoid (f : β → α → β) : FreeMonoid α →* Monoid.Foldl β
    where
  toFun xs := op <| flip (List.foldl f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by
    intros; simp only [FreeMonoid.toList_mul, flip, unop_op, List.foldl_append, op_inj]; 

Proof state:
m : Type u → Type u
inst✝ : Monad m
α β : Type u
f : β → α → β
x✝ y✝ : FreeMonoid α
⊢ (op fun a => List.foldl f (List.foldl f a (FreeMonoid.toList x✝)) (FreeMonoid.toList y✝)) =
    (op fun a => List.foldl f a (FreeMonoid.toList x✝)) * op fun a => List.foldl f a (FreeMonoid.toList y✝)

Next tactic:
rfl
@[simps]
def foldlM.ofFreeMonoid [LawfulMonad m] (f : β → α → m β) : FreeMonoid α →* Monoid.foldlM m β
    where
  toFun xs := op <| flip (List.foldlM f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by 

Proof state:
m : Type u → Type u
inst✝¹ : Monad m
α β : Type u
inst✝ : LawfulMonad m
f : β → α → m β
⊢ ∀ (x y : FreeMonoid α),
    OneHom.toFun
        { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
          map_one' :=
            (_ :
              (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
        (x * y) =
      OneHom.toFun
          { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
            map_one' :=
              (_ :
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                  (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
          x *
        OneHom.toFun
          { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
            map_one' :=
              (_ :
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                  (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
          y

Next tactic:
intros
@[simps]
def foldlM.ofFreeMonoid [LawfulMonad m] (f : β → α → m β) : FreeMonoid α →* Monoid.foldlM m β
    where
  toFun xs := op <| flip (List.foldlM f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by intros; 

Proof state:
m : Type u → Type u
inst✝¹ : Monad m
α β : Type u
inst✝ : LawfulMonad m
f : β → α → m β
x✝ y✝ : FreeMonoid α
⊢ OneHom.toFun
      { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
        map_one' :=
          (_ :
            (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
              (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
      (x✝ * y✝) =
    OneHom.toFun
        { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
          map_one' :=
            (_ :
              (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
        x✝ *
      OneHom.toFun
        { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
          map_one' :=
            (_ :
              (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
        y✝

Next tactic:
apply unop_injective
@[simps]
def foldlM.ofFreeMonoid [LawfulMonad m] (f : β → α → m β) : FreeMonoid α →* Monoid.foldlM m β
    where
  toFun xs := op <| flip (List.foldlM f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by intros; apply unop_injective; 

Proof state:
case a
m : Type u → Type u
inst✝¹ : Monad m
α β : Type u
inst✝ : LawfulMonad m
f : β → α → m β
x✝ y✝ : FreeMonoid α
⊢ unop
      (OneHom.toFun
        { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
          map_one' :=
            (_ :
              (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
        (x✝ * y✝)) =
    unop
      (OneHom.toFun
          { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
            map_one' :=
              (_ :
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                  (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
          x✝ *
        OneHom.toFun
          { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
            map_one' :=
              (_ :
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                  (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
          y✝)

Next tactic:
funext
@[simps]
def foldlM.ofFreeMonoid [LawfulMonad m] (f : β → α → m β) : FreeMonoid α →* Monoid.foldlM m β
    where
  toFun xs := op <| flip (List.foldlM f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by intros; apply unop_injective; funext; 

Proof state:
case a.h
m : Type u → Type u
inst✝¹ : Monad m
α β : Type u
inst✝ : LawfulMonad m
f : β → α → m β
x✝¹ y✝ : FreeMonoid α
x✝ : KleisliCat.mk m β
⊢ unop
      (OneHom.toFun
        { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
          map_one' :=
            (_ :
              (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
        (x✝¹ * y✝))
      x✝ =
    unop
      (OneHom.toFun
          { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
            map_one' :=
              (_ :
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                  (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
          x✝¹ *
        OneHom.toFun
          { toFun := fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs)),
            map_one' :=
              (_ :
                (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1 =
                  (fun xs => op (flip (List.foldlM f) (FreeMonoid.toList xs))) 1) }
          y✝)
      x✝

Next tactic:
apply List.foldlM_append
@[simps]
def foldrM.ofFreeMonoid [LawfulMonad m] (f : α → β → m β) : FreeMonoid α →* Monoid.foldrM m β
    where
  toFun xs := flip (List.foldrM f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by 

Proof state:
m : Type u → Type u
inst✝¹ : Monad m
α β : Type u
inst✝ : LawfulMonad m
f : α → β → m β
⊢ ∀ (x y : FreeMonoid α),
    OneHom.toFun
        { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
          map_one' :=
            (_ :
              (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
                (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
        (x * y) =
      OneHom.toFun
          { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
            map_one' :=
              (_ :
                (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
                  (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
          x *
        OneHom.toFun
          { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
            map_one' :=
              (_ :
                (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
                  (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
          y

Next tactic:
intros
@[simps]
def foldrM.ofFreeMonoid [LawfulMonad m] (f : α → β → m β) : FreeMonoid α →* Monoid.foldrM m β
    where
  toFun xs := flip (List.foldrM f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by intros; 

Proof state:
m : Type u → Type u
inst✝¹ : Monad m
α β : Type u
inst✝ : LawfulMonad m
f : α → β → m β
x✝ y✝ : FreeMonoid α
⊢ OneHom.toFun
      { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
        map_one' :=
          (_ :
            (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
              (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
      (x✝ * y✝) =
    OneHom.toFun
        { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
          map_one' :=
            (_ :
              (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
                (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
        x✝ *
      OneHom.toFun
        { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
          map_one' :=
            (_ :
              (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
                (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
        y✝

Next tactic:
funext
@[simps]
def foldrM.ofFreeMonoid [LawfulMonad m] (f : α → β → m β) : FreeMonoid α →* Monoid.foldrM m β
    where
  toFun xs := flip (List.foldrM f) (FreeMonoid.toList xs)
  map_one' := rfl
  map_mul' := by intros; funext; 

Proof state:
case h
m : Type u → Type u
inst✝¹ : Monad m
α β : Type u
inst✝ : LawfulMonad m
f : α → β → m β
x✝¹ y✝ : FreeMonoid α
x✝ : KleisliCat.mk m β
⊢ OneHom.toFun
      { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
        map_one' :=
          (_ :
            (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
              (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
      (x✝¹ * y✝) x✝ =
    (OneHom.toFun
          { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
            map_one' :=
              (_ :
                (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
                  (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
          x✝¹ *
        OneHom.toFun
          { toFun := fun xs => flip (List.foldrM f) (FreeMonoid.toList xs),
            map_one' :=
              (_ :
                (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1 =
                  (fun xs => flip (List.foldrM f) (FreeMonoid.toList xs)) 1) }
          y✝)
      x✝

Next tactic:
apply List.foldrM_append
def mapFold [Monoid α] [Monoid β] (f : α →* β) : ApplicativeTransformation (Const α) (Const β)
    where
  app _ := f
  preserves_seq' := by intros; simp only [Seq.seq, map_mul]
  preserves_pure' := by 

Proof state:
α β γ : Type u
inst✝¹ : Monoid α
inst✝ : Monoid β
f : α →* β
⊢ ∀ {α_1 : Type ?u.11039} (x : α_1), (fun x => ⇑f) α_1 (pure x) = pure x

Next tactic:
intros
def mapFold [Monoid α] [Monoid β] (f : α →* β) : ApplicativeTransformation (Const α) (Const β)
    where
  app _ := f
  preserves_seq' := by intros; simp only [Seq.seq, map_mul]
  preserves_pure' := by intros; 

Proof state:
α β γ : Type u
inst✝¹ : Monoid α
inst✝ : Monoid β
f : α →* β
α✝ : Type ?u.11039
x✝ : α✝
⊢ (fun x => ⇑f) α✝ (pure x✝) = pure x✝

Next tactic:
simp only [map_one, pure]
def mapFold [Monoid α] [Monoid β] (f : α →* β) : ApplicativeTransformation (Const α) (Const β)
    where
  app _ := f
  preserves_seq' := by 

Proof state:
α β γ : Type u
inst✝¹ : Monoid α
inst✝ : Monoid β
f : α →* β
⊢ ∀ {α_1 β_1 : Type ?u.11039} (x : Const α (α_1 → β_1)) (y : Const α α_1),
    (fun x => ⇑f) β_1 (Seq.seq x fun x => y) = Seq.seq ((fun x => ⇑f) (α_1 → β_1) x) fun x => (fun x => ⇑f) α_1 y

Next tactic:
intros
def mapFold [Monoid α] [Monoid β] (f : α →* β) : ApplicativeTransformation (Const α) (Const β)
    where
  app _ := f
  preserves_seq' := by intros; 

Proof state:
α β γ : Type u
inst✝¹ : Monoid α
inst✝ : Monoid β
f : α →* β
α✝ β✝ : Type ?u.11039
x✝ : Const α (α✝ → β✝)
y✝ : Const α α✝
⊢ (fun x => ⇑f) β✝ (Seq.seq x✝ fun x => y✝) = Seq.seq ((fun x => ⇑f) (α✝ → β✝) x✝) fun x => (fun x => ⇑f) α✝ y✝

Next tactic:
simp only [Seq.seq, map_mul]
@[simp]
theorem foldlm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : α → β → m α) :
    foldlM.ofFreeMonoid f ∘ FreeMonoid.of = foldlM.mk ∘ flip f := by
  

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝³ : Traversable t
inst✝² : LawfulTraversable t
m : Type u → Type u
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → β → m α
⊢ ⇑(foldlM.ofFreeMonoid f) ∘ FreeMonoid.of = foldlM.mk ∘ flip f

Next tactic:
ext1 x
@[simp]
theorem foldlm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : α → β → m α) :
    foldlM.ofFreeMonoid f ∘ FreeMonoid.of = foldlM.mk ∘ flip f := by
  ext1 x
  

Proof state:
case h
α β γ : Type u
t : Type u → Type u
inst✝³ : Traversable t
inst✝² : LawfulTraversable t
m : Type u → Type u
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → β → m α
x : β
⊢ (⇑(foldlM.ofFreeMonoid f) ∘ FreeMonoid.of) x = (foldlM.mk ∘ flip f) x

Next tactic:
simp [(· ∘ ·), foldlM.ofFreeMonoid, foldlM.mk, flip]
@[simp]
theorem foldlm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : α → β → m α) :
    foldlM.ofFreeMonoid f ∘ FreeMonoid.of = foldlM.mk ∘ flip f := by
  ext1 x
  simp [(· ∘ ·), foldlM.ofFreeMonoid, foldlM.mk, flip]
  

Proof state:
case h
α β γ : Type u
t : Type u → Type u
inst✝³ : Traversable t
inst✝² : LawfulTraversable t
m : Type u → Type u
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → β → m α
x : β
⊢ (fun a => f a x) = fun a => f a x

Next tactic:
rfl
@[simp]
theorem foldrm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : β → α → m α) :
    foldrM.ofFreeMonoid f ∘ FreeMonoid.of = foldrM.mk ∘ f := by
  

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝³ : Traversable t
inst✝² : LawfulTraversable t
m : Type u → Type u
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : β → α → m α
⊢ ⇑(foldrM.ofFreeMonoid f) ∘ FreeMonoid.of = foldrM.mk ∘ f

Next tactic:
ext
@[simp]
theorem foldrm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : β → α → m α) :
    foldrM.ofFreeMonoid f ∘ FreeMonoid.of = foldrM.mk ∘ f := by
  ext
  

Proof state:
case h
α β γ : Type u
t : Type u → Type u
inst✝³ : Traversable t
inst✝² : LawfulTraversable t
m : Type u → Type u
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : β → α → m α
x✝ : β
⊢ (⇑(foldrM.ofFreeMonoid f) ∘ FreeMonoid.of) x✝ = (foldrM.mk ∘ f) x✝

Next tactic:
simp [(· ∘ ·), foldrM.ofFreeMonoid, foldrM.mk, flip]
theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMonoid.of xs) :=
  Eq.symm <|
    calc
      FreeMonoid.toList (foldMap FreeMonoid.of xs) =
          FreeMonoid.toList (foldMap FreeMonoid.of xs).reverse.reverse :=
          by 

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
xs : t α
⊢ FreeMonoid.toList (foldMap FreeMonoid.of xs) =
    FreeMonoid.toList (List.reverse (List.reverse (foldMap FreeMonoid.of xs)))

Next tactic:
simp only [List.reverse_reverse]
theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMonoid.of xs) :=
  Eq.symm <|
    calc
      FreeMonoid.toList (foldMap FreeMonoid.of xs) =
          FreeMonoid.toList (foldMap FreeMonoid.of xs).reverse.reverse :=
          by simp only [List.reverse_reverse]
      _ = FreeMonoid.toList (List.foldr cons [] (foldMap FreeMonoid.of xs).reverse).reverse :=
          by 

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
xs : t α
⊢ FreeMonoid.toList (List.reverse (List.reverse (foldMap FreeMonoid.of xs))) =
    FreeMonoid.toList (List.reverse (List.foldr cons [] (List.reverse (foldMap FreeMonoid.of xs))))

Next tactic:
simp only [List.foldr_eta]
theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMonoid.of xs) :=
  Eq.symm <|
    calc
      FreeMonoid.toList (foldMap FreeMonoid.of xs) =
          FreeMonoid.toList (foldMap FreeMonoid.of xs).reverse.reverse :=
          by simp only [List.reverse_reverse]
      _ = FreeMonoid.toList (List.foldr cons [] (foldMap FreeMonoid.of xs).reverse).reverse :=
          by simp only [List.foldr_eta]
      _ = (unop (Foldl.ofFreeMonoid (flip cons) (foldMap FreeMonoid.of xs)) []).reverse :=
          by 

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
xs : t α
⊢ FreeMonoid.toList (List.reverse (List.foldr cons [] (List.reverse (foldMap FreeMonoid.of xs)))) =
    List.reverse (unop ((Foldl.ofFreeMonoid (flip cons)) (foldMap FreeMonoid.of xs)) [])

Next tactic:
simp [flip, List.foldr_reverse, Foldl.ofFreeMonoid, unop_op]
theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMonoid.of xs) :=
  Eq.symm <|
    calc
      FreeMonoid.toList (foldMap FreeMonoid.of xs) =
          FreeMonoid.toList (foldMap FreeMonoid.of xs).reverse.reverse :=
          by simp only [List.reverse_reverse]
      _ = FreeMonoid.toList (List.foldr cons [] (foldMap FreeMonoid.of xs).reverse).reverse :=
          by simp only [List.foldr_eta]
      _ = (unop (Foldl.ofFreeMonoid (flip cons) (foldMap FreeMonoid.of xs)) []).reverse :=
          by simp [flip, List.foldr_reverse, Foldl.ofFreeMonoid, unop_op]
      _ = toList xs :=
          by 

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
xs : t α
⊢ List.reverse (unop ((Foldl.ofFreeMonoid (flip cons)) (foldMap FreeMonoid.of xs)) []) = toList xs

Next tactic:
rw [foldMap_hom_free (Foldl.ofFreeMonoid (flip <| @cons α))]
theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMonoid.of xs) :=
  Eq.symm <|
    calc
      FreeMonoid.toList (foldMap FreeMonoid.of xs) =
          FreeMonoid.toList (foldMap FreeMonoid.of xs).reverse.reverse :=
          by simp only [List.reverse_reverse]
      _ = FreeMonoid.toList (List.foldr cons [] (foldMap FreeMonoid.of xs).reverse).reverse :=
          by simp only [List.foldr_eta]
      _ = (unop (Foldl.ofFreeMonoid (flip cons) (foldMap FreeMonoid.of xs)) []).reverse :=
          by simp [flip, List.foldr_reverse, Foldl.ofFreeMonoid, unop_op]
      _ = toList xs :=
          by rw [foldMap_hom_free (Foldl.ofFreeMonoid (flip <| @cons α))]
             

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
xs : t α
⊢ List.reverse (unop (foldMap (⇑(Foldl.ofFreeMonoid (flip cons)) ∘ FreeMonoid.of) xs) []) = toList xs

Next tactic:
simp only [toList, foldl, List.reverse_inj, Foldl.get, foldl.ofFreeMonoid_comp_of,
               Function.comp_apply]
theorem foldMap_map [Monoid γ] (f : α → β) (g : β → γ) (xs : t α) :
    foldMap g (f <$> xs) = foldMap (g ∘ f) xs := by 

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝² : Traversable t
inst✝¹ : LawfulTraversable t
inst✝ : Monoid γ
f : α → β
g : β → γ
xs : t α
⊢ foldMap g (f <$> xs) = foldMap (g ∘ f) xs

Next tactic:
simp only [foldMap, traverse_map, Function.comp]
theorem foldl_toList (f : α → β → α) (xs : t β) (x : α) :
    foldl f x xs = List.foldl f x (toList xs) := by
  

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
f : α → β → α
xs : t β
x : α
⊢ foldl f x xs = List.foldl f x (toList xs)

Next tactic:
rw [← FreeMonoid.toList_ofList (toList xs), ← foldl.unop_ofFreeMonoid]
theorem foldl_toList (f : α → β → α) (xs : t β) (x : α) :
    foldl f x xs = List.foldl f x (toList xs) := by
  rw [← FreeMonoid.toList_ofList (toList xs), ← foldl.unop_ofFreeMonoid]
  

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
f : α → β → α
xs : t β
x : α
⊢ foldl f x xs = unop ((Foldl.ofFreeMonoid f) (FreeMonoid.ofList (toList xs))) x

Next tactic:
simp only [foldl, toList_spec, foldMap_hom_free, foldl.ofFreeMonoid_comp_of, Foldl.get,
    FreeMonoid.ofList_toList]
theorem foldr_toList (f : α → β → β) (xs : t α) (x : β) :
    foldr f x xs = List.foldr f x (toList xs) := by
  

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
f : α → β → β
xs : t α
x : β
⊢ foldr f x xs = List.foldr f x (toList xs)

Next tactic:
change _ = Foldr.ofFreeMonoid _ (FreeMonoid.ofList <| toList xs) _
theorem foldr_toList (f : α → β → β) (xs : t α) (x : β) :
    foldr f x xs = List.foldr f x (toList xs) := by
  change _ = Foldr.ofFreeMonoid _ (FreeMonoid.ofList <| toList xs) _
  

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
f : α → β → β
xs : t α
x : β
⊢ foldr f x xs = (Foldr.ofFreeMonoid f) (FreeMonoid.ofList (toList xs)) x

Next tactic:
rw [toList_spec, foldr, Foldr.get, FreeMonoid.ofList_toList, foldMap_hom_free,
    foldr.ofFreeMonoid_comp_of]
theorem toList_map (f : α → β) (xs : t α) : toList (f <$> xs) = f <$> toList xs := by
  

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
f : α → β
xs : t α
⊢ toList (f <$> xs) = f <$> toList xs

Next tactic:
simp only [toList_spec, Free.map_eq_map, foldMap_hom, foldMap_map, FreeMonoid.ofList_toList,
    FreeMonoid.map_of, (· ∘ ·)]
@[simp]
theorem foldl_map (g : β → γ) (f : α → γ → α) (a : α) (l : t β) :
    foldl f a (g <$> l) = foldl (fun x y => f x (g y)) a l := by
  

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
g : β → γ
f : α → γ → α
a : α
l : t β
⊢ foldl f a (g <$> l) = foldl (fun x y => f x (g y)) a l

Next tactic:
simp only [foldl, foldMap_map, (· ∘ ·), flip]
@[simp]
theorem foldr_map (g : β → γ) (f : γ → α → α) (a : α) (l : t β) :
    foldr f a (g <$> l) = foldr (f ∘ g) a l := by 

Proof state:
α β γ : Type u
t : Type u → Type u
inst✝¹ : Traversable t
inst✝ : LawfulTraversable t
g : β → γ
f : γ → α → α
a : α
l : t β
⊢ foldr f a (g <$> l) = foldr (f ∘ g) a l

Next tactic:
simp only [foldr, foldMap_map, (· ∘ ·), flip]