/-
Copyright (c) 2019 Michael Howes. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Michael Howes

! This file was ported from Lean 3 source module group_theory.presented_group
! leanprover-community/mathlib commit 0ebfdb71919ac6ca5d7fbc61a082fa2519556818
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.GroupTheory.FreeGroup
import Mathbin.GroupTheory.QuotientGroup

/-!
# Defining a group given by generators and relations

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

Given a subset `rels` of relations of the free group on a type `α`, this file constructs the group
given by generators `x : α` and relations `r ∈ rels`.

## Main definitions

* `presented_group rels`: the quotient group of the free group on a type `α` by a subset `rels` of
  relations of the free group on `α`.
* `of`: The canonical map from `α` to a presented group with generators `α`.
* `to_group f`: the canonical group homomorphism `presented_group rels → G`, given a function
  `f : α → G` from a type `α` to a group `G` which satisfies the relations `rels`.

## Tags

generators, relations, group presentations
-/

variable {α : Type _}

#print PresentedGroup /-
/-- Given a set of relations, rels, over a type `α`, presented_group constructs the group with
generators `x : α` and relations `rels` as a quotient of free_group `α`.-/
def PresentedGroup (rels : Set (FreeGroup α)) :=
  FreeGroup α ⧸ Subgroup.normalClosure rels
#align presented_group PresentedGroup
-/

namespace PresentedGroup

instance (rels : Set (FreeGroup α)) : Group (PresentedGroup rels) :=
  QuotientGroup.Quotient.group _

#print PresentedGroup.of /-
/-- `of` is the canonical map from `α` to a presented group with generators `x : α`. The term `x` is
mapped to the equivalence class of the image of `x` in `free_group α`. -/
def of {rels : Set (FreeGroup α)} (x : α) : PresentedGroup rels :=
  QuotientGroup.mk (FreeGroup.of x)
#align presented_group.of PresentedGroup.of
-/

section ToGroup

/-
Presented groups satisfy a universal property. If `G` is a group and `f : α → G` is a map such that
the images of `f` satisfy all the given relations, then `f` extends uniquely to a group homomorphism
from `presented_group rels` to `G`.
-/
variable {G : Type _} [Group G] {f : α → G} {rels : Set (FreeGroup α)}

-- mathport name: exprF
local notation "F" => FreeGroup.lift f

variable (h : ∀ r ∈ rels, F r = 1)

/- warning: presented_group.closure_rels_subset_ker -> PresentedGroup.closure_rels_subset_ker is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {G : Type.{u2}} [_inst_1 : Group.{u2} G] {f : α -> G} {rels : Set.{u1} (FreeGroup.{u1} α)}, (forall (r : FreeGroup.{u1} α), (Membership.Mem.{u1, u1} (FreeGroup.{u1} α) (Set.{u1} (FreeGroup.{u1} α)) (Set.hasMem.{u1} (FreeGroup.{u1} α)) r rels) -> (Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (FreeGroup.{u1} α) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (coeFn.{max 1 (max (max (succ u1) (succ u2)) (succ u2) (succ u1)) (max (succ u2) (succ u1)) (succ u1) (succ u2), max (max (succ u1) (succ u2)) (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (fun (_x : Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) => (α -> G) -> (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (Equiv.hasCoeToFun.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f) r) (OfNat.ofNat.{u2} G 1 (OfNat.mk.{u2} G 1 (One.one.{u2} G (MulOneClass.toHasOne.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))))))) -> (LE.le.{u1} (Subgroup.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)) (Preorder.toLE.{u1} (Subgroup.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)) (PartialOrder.toPreorder.{u1} (Subgroup.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)) (SetLike.partialOrder.{u1, u1} (Subgroup.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)) (FreeGroup.{u1} α) (Subgroup.setLike.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α))))) (Subgroup.normalClosure.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α) rels) (MonoidHom.ker.{u1, u2} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α) G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))) (coeFn.{max 1 (max (max (succ u1) (succ u2)) (succ u2) (succ u1)) (max (succ u2) (succ u1)) (succ u1) (succ u2), max (max (succ u1) (succ u2)) (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (fun (_x : Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) => (α -> G) -> (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (Equiv.hasCoeToFun.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f)))
but is expected to have type
  forall {α : Type.{u2}} {G : Type.{u1}} [_inst_1 : Group.{u1} G] {f : α -> G} {rels : Set.{u2} (FreeGroup.{u2} α)}, (forall (r : FreeGroup.{u2} α), (Membership.mem.{u2, u2} (FreeGroup.{u2} α) (Set.{u2} (FreeGroup.{u2} α)) (Set.instMembershipSet.{u2} (FreeGroup.{u2} α)) r rels) -> (Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) (fun (_x : FreeGroup.{u2} α) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) G (MulOneClass.toMul.{u2} (FreeGroup.{u2} α) (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α))))) (MulOneClass.toMul.{u1} G (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u2 u1, u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (MonoidHom.monoidHomClass.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))))) (FunLike.coe.{max (succ u1) (succ u2), max (succ u1) (succ u2), max (succ u1) (succ u2)} (Equiv.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (α -> G) (fun (_x : α -> G) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) _x) (Equiv.instFunLikeEquiv.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (FreeGroup.lift.{u2, u1} α G _inst_1) f) r) (OfNat.ofNat.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) 1 (One.toOfNat1.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (InvOneClass.toOne.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (DivInvOneMonoid.toInvOneClass.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (DivisionMonoid.toDivInvOneMonoid.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (Group.toDivisionMonoid.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) _inst_1)))))))) -> (LE.le.{u2} (Subgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)) (Preorder.toLE.{u2} (Subgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)) (PartialOrder.toPreorder.{u2} (Subgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)) (CompleteSemilatticeInf.toPartialOrder.{u2} (Subgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)) (CompleteLattice.toCompleteSemilatticeInf.{u2} (Subgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)) (Subgroup.instCompleteLatticeSubgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))))) (Subgroup.normalClosure.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α) rels) (MonoidHom.ker.{u2, u1} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α) G (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (FunLike.coe.{max (succ u1) (succ u2), max (succ u1) (succ u2), max (succ u1) (succ u2)} (Equiv.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (α -> G) (fun (_x : α -> G) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) _x) (Equiv.instFunLikeEquiv.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (FreeGroup.lift.{u2, u1} α G _inst_1) f)))
Case conversion may be inaccurate. Consider using '#align presented_group.closure_rels_subset_ker PresentedGroup.closure_rels_subset_kerₓ'. -/
theorem closure_rels_subset_ker : Subgroup.normalClosure rels ≤ MonoidHom.ker F :=
  Subgroup.normalClosure_le_normal fun x w => (MonoidHom.mem_ker _).2 (h x w)
#align presented_group.closure_rels_subset_ker PresentedGroup.closure_rels_subset_ker

/- warning: presented_group.to_group_eq_one_of_mem_closure -> PresentedGroup.to_group_eq_one_of_mem_closure is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {G : Type.{u2}} [_inst_1 : Group.{u2} G] {f : α -> G} {rels : Set.{u1} (FreeGroup.{u1} α)}, (forall (r : FreeGroup.{u1} α), (Membership.Mem.{u1, u1} (FreeGroup.{u1} α) (Set.{u1} (FreeGroup.{u1} α)) (Set.hasMem.{u1} (FreeGroup.{u1} α)) r rels) -> (Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (FreeGroup.{u1} α) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (coeFn.{max 1 (max (max (succ u1) (succ u2)) (succ u2) (succ u1)) (max (succ u2) (succ u1)) (succ u1) (succ u2), max (max (succ u1) (succ u2)) (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (fun (_x : Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) => (α -> G) -> (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (Equiv.hasCoeToFun.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f) r) (OfNat.ofNat.{u2} G 1 (OfNat.mk.{u2} G 1 (One.one.{u2} G (MulOneClass.toHasOne.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))))))) -> (forall (x : FreeGroup.{u1} α), (Membership.Mem.{u1, u1} (FreeGroup.{u1} α) (Subgroup.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)) (SetLike.hasMem.{u1, u1} (Subgroup.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)) (FreeGroup.{u1} α) (Subgroup.setLike.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α))) x (Subgroup.normalClosure.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α) rels)) -> (Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (FreeGroup.{u1} α) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (coeFn.{max 1 (max (max (succ u1) (succ u2)) (succ u2) (succ u1)) (max (succ u2) (succ u1)) (succ u1) (succ u2), max (max (succ u1) (succ u2)) (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (fun (_x : Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) => (α -> G) -> (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (Equiv.hasCoeToFun.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f) x) (OfNat.ofNat.{u2} G 1 (OfNat.mk.{u2} G 1 (One.one.{u2} G (MulOneClass.toHasOne.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))))))))
but is expected to have type
  forall {α : Type.{u2}} {G : Type.{u1}} [_inst_1 : Group.{u1} G] {f : α -> G} {rels : Set.{u2} (FreeGroup.{u2} α)}, (forall (r : FreeGroup.{u2} α), (Membership.mem.{u2, u2} (FreeGroup.{u2} α) (Set.{u2} (FreeGroup.{u2} α)) (Set.instMembershipSet.{u2} (FreeGroup.{u2} α)) r rels) -> (Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) (fun (_x : FreeGroup.{u2} α) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) G (MulOneClass.toMul.{u2} (FreeGroup.{u2} α) (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α))))) (MulOneClass.toMul.{u1} G (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u2 u1, u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (MonoidHom.monoidHomClass.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))))) (FunLike.coe.{max (succ u1) (succ u2), max (succ u1) (succ u2), max (succ u1) (succ u2)} (Equiv.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (α -> G) (fun (_x : α -> G) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) _x) (Equiv.instFunLikeEquiv.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (FreeGroup.lift.{u2, u1} α G _inst_1) f) r) (OfNat.ofNat.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) 1 (One.toOfNat1.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (InvOneClass.toOne.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (DivInvOneMonoid.toInvOneClass.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (DivisionMonoid.toDivInvOneMonoid.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (Group.toDivisionMonoid.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) _inst_1)))))))) -> (forall (x : FreeGroup.{u2} α), (Membership.mem.{u2, u2} (FreeGroup.{u2} α) (Subgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)) (SetLike.instMembership.{u2, u2} (Subgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)) (FreeGroup.{u2} α) (Subgroup.instSetLikeSubgroup.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α))) x (Subgroup.normalClosure.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α) rels)) -> (Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) x) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) (fun (_x : FreeGroup.{u2} α) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) G (MulOneClass.toMul.{u2} (FreeGroup.{u2} α) (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α))))) (MulOneClass.toMul.{u1} G (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u2 u1, u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (MonoidHom.monoidHomClass.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))))) (FunLike.coe.{max (succ u1) (succ u2), max (succ u1) (succ u2), max (succ u1) (succ u2)} (Equiv.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (α -> G) (fun (_x : α -> G) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) _x) (Equiv.instFunLikeEquiv.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (FreeGroup.lift.{u2, u1} α G _inst_1) f) x) (OfNat.ofNat.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) x) 1 (One.toOfNat1.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) x) (InvOneClass.toOne.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) x) (DivInvOneMonoid.toInvOneClass.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) x) (DivisionMonoid.toDivInvOneMonoid.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) x) (Group.toDivisionMonoid.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) x) _inst_1))))))))
Case conversion may be inaccurate. Consider using '#align presented_group.to_group_eq_one_of_mem_closure PresentedGroup.to_group_eq_one_of_mem_closureₓ'. -/
theorem to_group_eq_one_of_mem_closure : ∀ x ∈ Subgroup.normalClosure rels, F x = 1 := fun x w =>
  (MonoidHom.mem_ker _).1 <| closure_rels_subset_ker h w
#align presented_group.to_group_eq_one_of_mem_closure PresentedGroup.to_group_eq_one_of_mem_closure

/- warning: presented_group.to_group -> PresentedGroup.toGroup is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {G : Type.{u2}} [_inst_1 : Group.{u2} G] {f : α -> G} {rels : Set.{u1} (FreeGroup.{u1} α)}, (forall (r : FreeGroup.{u1} α), (Membership.Mem.{u1, u1} (FreeGroup.{u1} α) (Set.{u1} (FreeGroup.{u1} α)) (Set.hasMem.{u1} (FreeGroup.{u1} α)) r rels) -> (Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (FreeGroup.{u1} α) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (coeFn.{max 1 (max (max (succ u1) (succ u2)) (succ u2) (succ u1)) (max (succ u2) (succ u1)) (succ u1) (succ u2), max (max (succ u1) (succ u2)) (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (fun (_x : Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) => (α -> G) -> (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (Equiv.hasCoeToFun.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f) r) (OfNat.ofNat.{u2} G 1 (OfNat.mk.{u2} G 1 (One.one.{u2} G (MulOneClass.toHasOne.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))))))) -> (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))
but is expected to have type
  forall {α : Type.{u1}} {G : Type.{u2}} [_inst_1 : Group.{u2} G] {f : α -> G} {rels : Set.{u1} (FreeGroup.{u1} α)}, (forall (r : FreeGroup.{u1} α), (Membership.mem.{u1, u1} (FreeGroup.{u1} α) (Set.{u1} (FreeGroup.{u1} α)) (Set.instMembershipSet.{u1} (FreeGroup.{u1} α)) r rels) -> (Eq.{succ u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) f) (FreeGroup.{u1} α) (fun (_x : FreeGroup.{u1} α) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) _x) (MulHomClass.toFunLike.{max u1 u2, u1, u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) f) (FreeGroup.{u1} α) G (MulOneClass.toMul.{u1} (FreeGroup.{u1} α) (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α))))) (MulOneClass.toMul.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u1 u2, u1, u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) f) (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))) (MonoidHom.monoidHomClass.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))))) (FunLike.coe.{max (succ u2) (succ u1), max (succ u2) (succ u1), max (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (α -> G) (fun (_x : α -> G) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) _x) (Equiv.instFunLikeEquiv.{max (succ u2) (succ u1), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f) r) (OfNat.ofNat.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) 1 (One.toOfNat1.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (InvOneClass.toOne.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (DivInvOneMonoid.toInvOneClass.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (DivisionMonoid.toDivInvOneMonoid.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (Group.toDivisionMonoid.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) _inst_1)))))))) -> (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.instGroupPresentedGroup.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))
Case conversion may be inaccurate. Consider using '#align presented_group.to_group PresentedGroup.toGroupₓ'. -/
/-- The extension of a map `f : α → G` that satisfies the given relations to a group homomorphism
from `presented_group rels → G`. -/
def toGroup : PresentedGroup rels →* G :=
  QuotientGroup.lift (Subgroup.normalClosure rels) F (to_group_eq_one_of_mem_closure h)
#align presented_group.to_group PresentedGroup.toGroup

/- warning: presented_group.to_group.of -> PresentedGroup.toGroup.of is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {G : Type.{u2}} [_inst_1 : Group.{u2} G] {f : α -> G} {rels : Set.{u1} (FreeGroup.{u1} α)} (h : forall (r : FreeGroup.{u1} α), (Membership.Mem.{u1, u1} (FreeGroup.{u1} α) (Set.{u1} (FreeGroup.{u1} α)) (Set.hasMem.{u1} (FreeGroup.{u1} α)) r rels) -> (Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (FreeGroup.{u1} α) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (coeFn.{max 1 (max (max (succ u1) (succ u2)) (succ u2) (succ u1)) (max (succ u2) (succ u1)) (succ u1) (succ u2), max (max (succ u1) (succ u2)) (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (fun (_x : Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) => (α -> G) -> (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (Equiv.hasCoeToFun.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f) r) (OfNat.ofNat.{u2} G 1 (OfNat.mk.{u2} G 1 (One.one.{u2} G (MulOneClass.toHasOne.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))))))) {x : α}, Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (PresentedGroup.{u1} α rels) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (PresentedGroup.toGroup.{u1, u2} α G _inst_1 f rels h) (PresentedGroup.of.{u1} α rels x)) (f x)
but is expected to have type
  forall {α : Type.{u1}} {G : Type.{u2}} [_inst_1 : Group.{u2} G] {f : α -> G} {rels : Set.{u1} (FreeGroup.{u1} α)} (h : forall (r : FreeGroup.{u1} α), (Membership.mem.{u1, u1} (FreeGroup.{u1} α) (Set.{u1} (FreeGroup.{u1} α)) (Set.instMembershipSet.{u1} (FreeGroup.{u1} α)) r rels) -> (Eq.{succ u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) f) (FreeGroup.{u1} α) (fun (_x : FreeGroup.{u1} α) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) _x) (MulHomClass.toFunLike.{max u1 u2, u1, u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) f) (FreeGroup.{u1} α) G (MulOneClass.toMul.{u1} (FreeGroup.{u1} α) (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α))))) (MulOneClass.toMul.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u1 u2, u1, u2} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) f) (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))) (MonoidHom.monoidHomClass.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))))) (FunLike.coe.{max (succ u2) (succ u1), max (succ u2) (succ u1), max (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (α -> G) (fun (_x : α -> G) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) _x) (Equiv.instFunLikeEquiv.{max (succ u2) (succ u1), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.instGroupFreeGroup.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f) r) (OfNat.ofNat.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) 1 (One.toOfNat1.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (InvOneClass.toOne.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (DivInvOneMonoid.toInvOneClass.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (DivisionMonoid.toDivInvOneMonoid.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) (Group.toDivisionMonoid.{u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u1} α) => G) r) _inst_1)))))))) {x : α}, Eq.{succ u2} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : PresentedGroup.{u1} α rels) => G) (PresentedGroup.of.{u1} α rels x)) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.instGroupPresentedGroup.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (PresentedGroup.{u1} α rels) (fun (_x : PresentedGroup.{u1} α rels) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : PresentedGroup.{u1} α rels) => G) _x) (MulHomClass.toFunLike.{max u1 u2, u1, u2} (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.instGroupPresentedGroup.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (PresentedGroup.{u1} α rels) G (MulOneClass.toMul.{u1} (PresentedGroup.{u1} α rels) (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.instGroupPresentedGroup.{u1} α rels))))) (MulOneClass.toMul.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u1 u2, u1, u2} (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.instGroupPresentedGroup.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.instGroupPresentedGroup.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))) (MonoidHom.monoidHomClass.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.instGroupPresentedGroup.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))))) (PresentedGroup.toGroup.{u1, u2} α G _inst_1 f rels h) (PresentedGroup.of.{u1} α rels x)) (f x)
Case conversion may be inaccurate. Consider using '#align presented_group.to_group.of PresentedGroup.toGroup.ofₓ'. -/
@[simp]
theorem toGroup.of {x : α} : toGroup h (of x) = f x :=
  FreeGroup.lift.of
#align presented_group.to_group.of PresentedGroup.toGroup.of

/- warning: presented_group.to_group.unique -> PresentedGroup.toGroup.unique is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {G : Type.{u2}} [_inst_1 : Group.{u2} G] {f : α -> G} {rels : Set.{u1} (FreeGroup.{u1} α)} (h : forall (r : FreeGroup.{u1} α), (Membership.Mem.{u1, u1} (FreeGroup.{u1} α) (Set.{u1} (FreeGroup.{u1} α)) (Set.hasMem.{u1} (FreeGroup.{u1} α)) r rels) -> (Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (FreeGroup.{u1} α) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (coeFn.{max 1 (max (max (succ u1) (succ u2)) (succ u2) (succ u1)) (max (succ u2) (succ u1)) (succ u1) (succ u2), max (max (succ u1) (succ u2)) (succ u2) (succ u1)} (Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (fun (_x : Equiv.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) => (α -> G) -> (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (Equiv.hasCoeToFun.{max (succ u1) (succ u2), max (succ u2) (succ u1)} (α -> G) (MonoidHom.{u1, u2} (FreeGroup.{u1} α) G (Monoid.toMulOneClass.{u1} (FreeGroup.{u1} α) (DivInvMonoid.toMonoid.{u1} (FreeGroup.{u1} α) (Group.toDivInvMonoid.{u1} (FreeGroup.{u1} α) (FreeGroup.group.{u1} α)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))) (FreeGroup.lift.{u1, u2} α G _inst_1) f) r) (OfNat.ofNat.{u2} G 1 (OfNat.mk.{u2} G 1 (One.one.{u2} G (MulOneClass.toHasOne.{u2} G (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1))))))))) (g : MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))), (forall (x : α), Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (PresentedGroup.{u1} α rels) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) g (PresentedGroup.of.{u1} α rels x)) (f x)) -> (forall {x : PresentedGroup.{u1} α rels}, Eq.{succ u2} G (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (PresentedGroup.{u1} α rels) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) g x) (coeFn.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (fun (_x : MonoidHom.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) => (PresentedGroup.{u1} α rels) -> G) (MonoidHom.hasCoeToFun.{u1, u2} (PresentedGroup.{u1} α rels) G (Monoid.toMulOneClass.{u1} (PresentedGroup.{u1} α rels) (DivInvMonoid.toMonoid.{u1} (PresentedGroup.{u1} α rels) (Group.toDivInvMonoid.{u1} (PresentedGroup.{u1} α rels) (PresentedGroup.group.{u1} α rels)))) (Monoid.toMulOneClass.{u2} G (DivInvMonoid.toMonoid.{u2} G (Group.toDivInvMonoid.{u2} G _inst_1)))) (PresentedGroup.toGroup.{u1, u2} α G _inst_1 f rels h) x))
but is expected to have type
  forall {α : Type.{u2}} {G : Type.{u1}} [_inst_1 : Group.{u1} G] {f : α -> G} {rels : Set.{u2} (FreeGroup.{u2} α)} (h : forall (r : FreeGroup.{u2} α), (Membership.mem.{u2, u2} (FreeGroup.{u2} α) (Set.{u2} (FreeGroup.{u2} α)) (Set.instMembershipSet.{u2} (FreeGroup.{u2} α)) r rels) -> (Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) (fun (_x : FreeGroup.{u2} α) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) G (MulOneClass.toMul.{u2} (FreeGroup.{u2} α) (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α))))) (MulOneClass.toMul.{u1} G (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u2 u1, u2, u1} ((fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) f) (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (MonoidHom.monoidHomClass.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))))) (FunLike.coe.{max (succ u1) (succ u2), max (succ u1) (succ u2), max (succ u1) (succ u2)} (Equiv.{max (succ u2) (succ u1), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (α -> G) (fun (_x : α -> G) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : α -> G) => MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) _x) (Equiv.instFunLikeEquiv.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (α -> G) (MonoidHom.{u2, u1} (FreeGroup.{u2} α) G (Monoid.toMulOneClass.{u2} (FreeGroup.{u2} α) (DivInvMonoid.toMonoid.{u2} (FreeGroup.{u2} α) (Group.toDivInvMonoid.{u2} (FreeGroup.{u2} α) (FreeGroup.instGroupFreeGroup.{u2} α)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))))) (FreeGroup.lift.{u2, u1} α G _inst_1) f) r) (OfNat.ofNat.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) 1 (One.toOfNat1.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (InvOneClass.toOne.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (DivInvOneMonoid.toInvOneClass.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (DivisionMonoid.toDivInvOneMonoid.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) (Group.toDivisionMonoid.{u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : FreeGroup.{u2} α) => G) r) _inst_1)))))))) (g : MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))), (forall (x : α), Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : PresentedGroup.{u2} α rels) => G) (PresentedGroup.of.{u2} α rels x)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) (fun (_x : PresentedGroup.{u2} α rels) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : PresentedGroup.{u2} α rels) => G) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) G (MulOneClass.toMul.{u2} (PresentedGroup.{u2} α rels) (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels))))) (MulOneClass.toMul.{u1} G (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u2 u1, u2, u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (MonoidHom.monoidHomClass.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))))) g (PresentedGroup.of.{u2} α rels x)) (f x)) -> (forall {x : PresentedGroup.{u2} α rels}, Eq.{succ u1} ((fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : PresentedGroup.{u2} α rels) => G) x) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) (fun (_x : PresentedGroup.{u2} α rels) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : PresentedGroup.{u2} α rels) => G) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) G (MulOneClass.toMul.{u2} (PresentedGroup.{u2} α rels) (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels))))) (MulOneClass.toMul.{u1} G (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u2 u1, u2, u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (MonoidHom.monoidHomClass.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))))) g x) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) (fun (_x : PresentedGroup.{u2} α rels) => (fun (x._@.Mathlib.Algebra.Hom.Group._hyg.2391 : PresentedGroup.{u2} α rels) => G) _x) (MulHomClass.toFunLike.{max u2 u1, u2, u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) G (MulOneClass.toMul.{u2} (PresentedGroup.{u2} α rels) (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels))))) (MulOneClass.toMul.{u1} G (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (MonoidHomClass.toMulHomClass.{max u2 u1, u2, u1} (MonoidHom.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))) (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1))) (MonoidHom.monoidHomClass.{u2, u1} (PresentedGroup.{u2} α rels) G (Monoid.toMulOneClass.{u2} (PresentedGroup.{u2} α rels) (DivInvMonoid.toMonoid.{u2} (PresentedGroup.{u2} α rels) (Group.toDivInvMonoid.{u2} (PresentedGroup.{u2} α rels) (PresentedGroup.instGroupPresentedGroup.{u2} α rels)))) (Monoid.toMulOneClass.{u1} G (DivInvMonoid.toMonoid.{u1} G (Group.toDivInvMonoid.{u1} G _inst_1)))))) (PresentedGroup.toGroup.{u2, u1} α G _inst_1 f rels h) x))
Case conversion may be inaccurate. Consider using '#align presented_group.to_group.unique PresentedGroup.toGroup.uniqueₓ'. -/
theorem toGroup.unique (g : PresentedGroup rels →* G) (hg : ∀ x : α, g (of x) = f x) :
    ∀ {x}, g x = toGroup h x := fun x =>
  QuotientGroup.induction_on x fun _ => FreeGroup.lift.unique (g.comp (QuotientGroup.mk' _)) hg
#align presented_group.to_group.unique PresentedGroup.toGroup.unique

end ToGroup

instance (rels : Set (FreeGroup α)) : Inhabited (PresentedGroup rels) :=
  ⟨1⟩

end PresentedGroup


/-
Copyright (c) 2018 Jeremy Avigad. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Jeremy Avigad
-/

import data.equiv.encodable data.equiv.list data.fin data.finset data.fintype

/-
`Wfin α ar` is the type of finitely branching trees with labels from α, where
a node labeled `a` has `ar a` children.
-/

inductive Wfin {α : Type*} (ar : α → ℕ)
| mk (a : α) (f : fin (ar a) → Wfin) : Wfin

namespace Wfin

variables {α : Type*} {ar : α → ℕ}

def depth : Wfin ar → ℕ
| ⟨a, f⟩ := finset.sup finset.univ (λ n, depth (f n)) + 1

def not_depth_le_zero (t : Wfin ar) : ¬ t.depth ≤ 0 :=
by { cases t, apply nat.not_succ_le_zero }

lemma depth_lt_depth_mk (a : α) (f : fin (ar a) → Wfin ar) (i : fin (ar a)) :
  depth (f i) < depth ⟨a, f⟩ :=
nat.lt_succ_of_le (finset.le_sup (finset.mem_univ i))

end Wfin

/-
Show `Wfin` types are encodable.
-/

namespace encodable

@[reducible] private def Wfin' {α : Type*} (ar : α → ℕ) (n : ℕ) :=
{ t : Wfin ar // t.depth ≤ n}

variables {α : Type*} {ar : α → ℕ}

private def encodable_zero : encodable (Wfin' ar 0) :=
let f    : Wfin' ar 0 → empty := λ ⟨x, h⟩, absurd h (Wfin.not_depth_le_zero _),
    finv : empty → Wfin' ar 0 := by { intro x, cases x} in
have ∀ x, finv (f x) = x, from λ ⟨x, h⟩, absurd h (Wfin.not_depth_le_zero _),
encodable.of_left_inverse f finv this

private def f (n : ℕ) : Wfin' ar (n + 1) → Σ a : α, fin (ar a) → Wfin' ar n
| ⟨t, h⟩ :=
  begin
    cases t with a f,
    have h₀ : ∀ i : fin (ar a), Wfin.depth (f i) ≤ n,
      from λ i, nat.le_of_lt_succ (lt_of_lt_of_le (Wfin.depth_lt_depth_mk a f i) h),
    exact ⟨a, λ i : fin (ar a), ⟨f i, h₀ i⟩⟩
  end

private def finv (n : ℕ) :
  (Σ a : α, fin (ar a) → Wfin' ar n) → Wfin' ar (n + 1)
| ⟨a, f⟩ :=
  let f' := λ i : fin (ar a), (f i).val in
  have Wfin.depth ⟨a, f'⟩ ≤ n + 1,
    from add_le_add_right (finset.sup_le (λ b h, (f b).2)) 1,
  ⟨⟨a, f'⟩, this⟩

variable [encodable α]

private def encodable_succ (n : nat) (h : encodable (Wfin' ar n)) :
  encodable (Wfin' ar (n + 1)) :=
encodable.of_left_inverse (f n) (finv n)
  (by { intro t, cases t with t h, cases t with a fn, reflexivity })

instance : encodable (Wfin ar) :=
begin
  haveI h' : Π n, encodable (Wfin' ar n) :=
    λ n, nat.rec_on n encodable_zero encodable_succ,
  let f    : Wfin ar → Σ n, Wfin' ar n   := λ t, ⟨t.depth, ⟨t, le_refl _⟩⟩,
  let finv : (Σ n, Wfin' ar n) → Wfin ar := λ p, p.2.1,
  have : ∀ t, finv (f t) = t, from λ t, rfl,
  exact encodable.of_left_inverse f finv this
end

end encodable

/-
Make it easier to construct funtions from a small `fin`.
-/

namespace fin
variable {α : Type*}

def mk_fn0 : fin 0 → α
| ⟨_, h⟩ := absurd h dec_trivial

def mk_fn1 (t : α) : fin 1 → α
| ⟨0, _⟩   := t
| ⟨n+1, h⟩ := absurd h dec_trivial

def mk_fn2 (s t : α) : fin 2 → α
| ⟨0, _⟩   := s
| ⟨1, _⟩   := t
| ⟨n+2, h⟩ := absurd h dec_trivial

attribute [simp] mk_fn0 mk_fn1 mk_fn2
end fin


/-
Copyright (c) 2020 Oliver Nash. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Oliver Nash
-/
import algebra.direct_sum.module
import algebra.lie.of_associative
import algebra.lie.submodule
import algebra.lie.basic

/-!
# Direct sums of Lie algebras and Lie modules

Direct sums of Lie algebras and Lie modules carry natural algebra and module structures.

## Tags

lie algebra, lie module, direct sum
-/

universes u v w w₁

namespace direct_sum
open dfinsupp
open_locale direct_sum

variables {R : Type u} {ι : Type v} [comm_ring R]

section modules

/-! The direct sum of Lie modules over a fixed Lie algebra carries a natural Lie module
structure. -/

variables {L : Type w₁} {M : ι → Type w}
variables [lie_ring L] [lie_algebra R L]
variables [Π i, add_comm_group (M i)] [Π i, module R (M i)]
variables [Π i, lie_ring_module L (M i)] [Π i, lie_module R L (M i)]

instance : lie_ring_module L (⨁ i, M i) :=
{ bracket     := λ x m, m.map_range (λ i m', ⁅x, m'⁆) (λ i, lie_zero x),
  add_lie     := λ x y m, by { ext, simp only [map_range_apply, add_apply, add_lie], },
  lie_add     := λ x m n, by { ext, simp only [map_range_apply, add_apply, lie_add], },
  leibniz_lie := λ x y m, by { ext, simp only [map_range_apply, lie_lie, add_apply,
    sub_add_cancel], }, }

@[simp] lemma lie_module_bracket_apply (x : L) (m : ⨁ i, M i) (i : ι) :
  ⁅x, m⁆ i = ⁅x, m i⁆ := map_range_apply _ _ m i

instance : lie_module R L (⨁ i, M i) :=
{ smul_lie := λ t x m, by { ext i, simp only [smul_lie, lie_module_bracket_apply, smul_apply], },
  lie_smul := λ t x m, by { ext i, simp only [lie_smul, lie_module_bracket_apply, smul_apply], }, }

variables (R ι L M)

/-- The inclusion of each component into a direct sum as a morphism of Lie modules. -/
def lie_module_of [decidable_eq ι] (j : ι) : M j →ₗ⁅R,L⁆ ⨁ i, M i :=
{ map_lie' := λ x m,
    begin
      ext i, by_cases h : j = i,
      { rw ← h, simp, },
      { simp [lof, single_eq_of_ne h], },
    end,
  ..lof R ι M j }

/-- The projection map onto one component, as a morphism of Lie modules. -/
def lie_module_component (j : ι) : (⨁ i, M i) →ₗ⁅R,L⁆ M j :=
{ map_lie' := λ x m,
    by simp only [component, lapply_apply, lie_module_bracket_apply, linear_map.to_fun_eq_coe],
  ..component R ι M j }

end modules

section algebras

/-! The direct sum of Lie algebras carries a natural Lie algebra structure. -/

variables (L : ι → Type w)
variables [Π i, lie_ring (L i)] [Π i, lie_algebra R (L i)]

instance lie_ring : lie_ring (⨁ i, L i) :=
{ bracket     := zip_with (λ i, λ x y, ⁅x, y⁆) (λ i, lie_zero 0),
  add_lie     := λ x y z, by { ext, simp only [zip_with_apply, add_apply, add_lie], },
  lie_add     := λ x y z, by { ext, simp only [zip_with_apply, add_apply, lie_add], },
  lie_self    := λ x, by { ext, simp only [zip_with_apply, add_apply, lie_self, zero_apply], },
  leibniz_lie := λ x y z, by { ext, simp only [sub_apply,
    zip_with_apply, add_apply, zero_apply], apply leibniz_lie, },
  ..(infer_instance : add_comm_group _) }

@[simp] lemma bracket_apply (x y : ⨁ i, L i) (i : ι) :
  ⁅x, y⁆ i = ⁅x i, y i⁆ := zip_with_apply _ _ x y i

instance lie_algebra : lie_algebra R (⨁ i, L i) :=
{ lie_smul := λ c x y, by { ext, simp only [
    zip_with_apply, smul_apply, bracket_apply, lie_smul] },
  ..(infer_instance : module R _) }

variables (R ι L)

/-- The inclusion of each component into the direct sum as morphism of Lie algebras. -/
@[simps] def lie_algebra_of [decidable_eq ι] (j : ι) : L j →ₗ⁅R⁆ ⨁ i, L i :=
{ to_fun   := of L j,
  map_lie' := λ x y, by
  { ext i, by_cases h : j = i,
    { rw ← h, simp [of], },
    { simp [of, single_eq_of_ne h], }, },
  ..lof R ι L j, }

/-- The projection map onto one component, as a morphism of Lie algebras. -/
@[simps] def lie_algebra_component (j : ι) : (⨁ i, L i) →ₗ⁅R⁆ L j :=
{ to_fun   := component R ι L j,
  map_lie' := λ x y,
    by simp only [component, bracket_apply, lapply_apply, linear_map.to_fun_eq_coe],
  ..component R ι L j }

@[ext] lemma lie_algebra_ext {x y : ⨁ i, L i}
  (h : ∀ i, lie_algebra_component R ι L i x = lie_algebra_component R ι L i y) : x = y :=
dfinsupp.ext h

include R

lemma lie_of_of_ne [decidable_eq ι] {i j : ι} (hij : j ≠ i) (x : L i) (y : L j) :
  ⁅of L i x, of L j y⁆ = 0 :=
begin
  apply lie_algebra_ext R ι L, intros k,
  rw lie_hom.map_lie,
  simp only [component, of, lapply_apply, single_add_hom_apply, lie_algebra_component_apply,
    single_apply, zero_apply],
  by_cases hik : i = k,
  { simp only [dif_neg, not_false_iff, lie_zero, hik.symm, hij], },
  { simp only [dif_neg, not_false_iff, zero_lie, hik], },
end

lemma lie_of_of_eq [decidable_eq ι] {i j : ι} (hij : j = i) (x : L i) (y : L j) :
  ⁅of L i x, of L j y⁆ = of L i ⁅x, hij.rec_on y⁆ :=
begin
  have : of L j y = of L i (hij.rec_on y), { exact eq.drec (eq.refl _) hij, },
  rw [this, ← lie_algebra_of_apply R ι L i ⁅x, hij.rec_on y⁆, lie_hom.map_lie,
    lie_algebra_of_apply, lie_algebra_of_apply],
end

@[simp] lemma lie_of [decidable_eq ι] {i j : ι} (x : L i) (y : L j) :
  ⁅of L i x, of L j y⁆ =
  if hij : j = i then lie_algebra_of R ι L i ⁅x, hij.rec_on y⁆ else 0 :=
begin
  by_cases hij : j = i,
  { simp only [lie_of_of_eq R ι L hij x y, hij, dif_pos, not_false_iff, lie_algebra_of_apply], },
  { simp only [lie_of_of_ne R ι L hij x y, hij, dif_neg, not_false_iff], },
end

variables {R L ι}

/-- Given a family of Lie algebras `L i`, together with a family of morphisms of Lie algebras
`f i : L i →ₗ⁅R⁆ L'` into a fixed Lie algebra `L'`, we have a natural linear map:
`(⨁ i, L i) →ₗ[R] L'`. If in addition `⁅f i x, f j y⁆ = 0` for any `x ∈ L i` and `y ∈ L j` (`i ≠ j`)
then this map is a morphism of Lie algebras. -/
@[simps] def to_lie_algebra [decidable_eq ι] (L' : Type w₁) [lie_ring L'] [lie_algebra R L']
  (f : Π i, L i →ₗ⁅R⁆ L') (hf : ∀ (i j : ι), i ≠ j → ∀ (x : L i) (y : L j), ⁅f i x, f j y⁆ = 0) :
  (⨁ i, L i) →ₗ⁅R⁆ L' :=
{ to_fun   := to_module R ι L' (λ i, (f i : L i →ₗ[R] L')),
  map_lie' := λ x y,
    begin
      let f' := λ i, (f i : L i →ₗ[R] L'),
      /- The goal is linear in `y`. We can use this to reduce to the case that `y` has only one
        non-zero component. -/
      suffices : ∀ (i : ι) (y : L i), to_module R ι L' f' ⁅x, of L i y⁆ =
        ⁅to_module R ι L' f' x, to_module R ι L' f' (of L i y)⁆,
      { simp only [← lie_algebra.ad_apply R],
        rw [← linear_map.comp_apply, ← linear_map.comp_apply],
        congr, clear y, ext i y, exact this i y, },
      /- Similarly, we can reduce to the case that `x` has only one non-zero component. -/
      suffices : ∀ i j (y : L i) (x : L j), to_module R ι L' f' ⁅of L j x, of L i y⁆ =
        ⁅to_module R ι L' f' (of L j x), to_module R ι L' f' (of L i y)⁆,
      { intros i y,
        rw [← lie_skew x, ← lie_skew (to_module R ι L' f' x)],
        simp only [linear_map.map_neg, neg_inj, ← lie_algebra.ad_apply R],
        rw [← linear_map.comp_apply, ← linear_map.comp_apply],
        congr, clear x, ext j x, exact this j i x y, },
      /- Tidy up and use `lie_of`. -/
      intros i j y x,
      simp only [lie_of R, lie_algebra_of_apply, lie_hom.coe_to_linear_map, to_add_monoid_of,
        coe_to_module_eq_coe_to_add_monoid, linear_map.to_add_monoid_hom_coe],
      /- And finish with trivial case analysis. -/
      rcases eq_or_ne i j with h | h,
      { have h' : f j (h.rec_on y) = f i y, { exact eq.drec (eq.refl _) h, },
        simp only [h, h', lie_hom.coe_to_linear_map, dif_pos, lie_hom.map_lie, to_add_monoid_of,
          linear_map.to_add_monoid_hom_coe], },
      { simp only [h, hf j i h.symm x y, dif_neg, not_false_iff, add_monoid_hom.map_zero], },
    end,
.. to_module R ι L' (λ i, (f i : L i →ₗ[R] L')) }

end algebras

section ideals

variables {L : Type w} [lie_ring L] [lie_algebra R L] (I : ι → lie_ideal R L)

/-- The fact that this instance is necessary seems to be a bug in typeclass inference. See
[this Zulip thread](https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/
Typeclass.20resolution.20under.20binders/near/245151099). -/
instance lie_ring_of_ideals : lie_ring (⨁ i, I i) := direct_sum.lie_ring (λ i, ↥(I i))

/-- See `direct_sum.lie_ring_of_ideals` comment. -/
instance lie_algebra_of_ideals : lie_algebra R (⨁ i, I i) := direct_sum.lie_algebra (λ i, ↥(I i))

end ideals

end direct_sum