mirror of
https://github.com/leanprover/lean4.git
synced 2026-04-16 09:04:09 +00:00
Compare commits
2 Commits
sg/partial
...
simp_index
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38e70429cc | ||
|
|
8301a700df |
@@ -169,6 +169,11 @@ structure Config where
|
||||
That is, given a local context containing entry `x : t := e`, the free variable `x` reduces to `e`.
|
||||
-/
|
||||
zetaDelta : Bool := false
|
||||
/--
|
||||
When `index` (default : `true`) is `false`, `simp` will only use the root symbol
|
||||
to find candidate `simp` theorems. It approximates Lean 3 `simp` behavior.
|
||||
-/
|
||||
index : Bool := true
|
||||
deriving Inhabited, BEq
|
||||
|
||||
-- Configuration object for `simp_all`
|
||||
|
||||
@@ -634,6 +634,55 @@ where
|
||||
else
|
||||
return result
|
||||
|
||||
/--
|
||||
Return the root symbol for `e`, and the number of arguments after `reduceDT`.
|
||||
-/
|
||||
def getMatchKeyRootFor (e : Expr) (config : WhnfCoreConfig) : MetaM (Key × Nat) := do
|
||||
let e ← reduceDT e (root := true) config
|
||||
let numArgs := e.getAppNumArgs
|
||||
let key := match e.getAppFn with
|
||||
| .lit v => .lit v
|
||||
| .fvar fvarId => .fvar fvarId numArgs
|
||||
| .mvar _ => .other
|
||||
| .proj s i _ .. => .proj s i numArgs
|
||||
| .forallE .. => .arrow
|
||||
| .const c _ =>
|
||||
-- This method is used by the simplifier only, we do **not** support
|
||||
-- (← getConfig).isDefEqStuckEx
|
||||
.const c numArgs
|
||||
| _ => .other
|
||||
return (key, numArgs)
|
||||
|
||||
/--
|
||||
Get all results under key `k`.
|
||||
-/
|
||||
private partial def getAllValuesForKey (d : DiscrTree α) (k : Key) (result : Array α) : Array α :=
|
||||
match d.root.find? k with
|
||||
| none => result
|
||||
| some trie => go trie result
|
||||
where
|
||||
go (trie : Trie α) (result : Array α) : Array α := Id.run do
|
||||
match trie with
|
||||
| .node vs cs =>
|
||||
let mut result := result ++ vs
|
||||
for (_, trie) in cs do
|
||||
result := go trie result
|
||||
return result
|
||||
|
||||
/--
|
||||
A liberal version of `getMatch` which only takes the root symbol of `e` into account.
|
||||
We use this method to simulate Lean 3's indexing.
|
||||
|
||||
The natural number in the result is the number of arguments in `e` after `reduceDT`.
|
||||
-/
|
||||
def getMatchLiberal (d : DiscrTree α) (e : Expr) (config : WhnfCoreConfig) : MetaM (Array α × Nat) := do
|
||||
withReducible do
|
||||
let result := getStarResult d
|
||||
let (k, numArgs) ← getMatchKeyRootFor e config
|
||||
match k with
|
||||
| .star => return (result, numArgs)
|
||||
| _ => return (getAllValuesForKey d k result, numArgs)
|
||||
|
||||
partial def getUnify (d : DiscrTree α) (e : Expr) (config : WhnfCoreConfig) : MetaM (Array α) :=
|
||||
withReducible do
|
||||
let (k, args) ← getUnifyKeyArgs e (root := true) config
|
||||
|
||||
@@ -9,6 +9,16 @@ import Lean.Meta.Tactic.Simp.Types
|
||||
|
||||
namespace Lean.Meta.Simp
|
||||
|
||||
private def originToKey (thmId : Origin) : MetaM MessageData := do
|
||||
match thmId with
|
||||
| .decl declName _ _ =>
|
||||
if (← getEnv).contains declName then
|
||||
pure m!"{MessageData.ofConst (← mkConstWithLevelParams declName)}"
|
||||
else
|
||||
pure m!"{declName} (builtin simproc)"
|
||||
| .fvar fvarId => pure m!"{mkFVar fvarId}"
|
||||
| _ => pure thmId.key
|
||||
|
||||
def mkSimpDiagSummary (counters : PHashMap Origin Nat) (usedCounters? : Option (PHashMap Origin Nat) := none) : MetaM DiagSummary := do
|
||||
let threshold := diagnostics.threshold.get (← getOptions)
|
||||
let entries := collectAboveThreshold counters threshold (fun _ => true) (lt := (· < ·))
|
||||
@@ -17,14 +27,7 @@ def mkSimpDiagSummary (counters : PHashMap Origin Nat) (usedCounters? : Option (
|
||||
else
|
||||
let mut data := #[]
|
||||
for (thmId, counter) in entries do
|
||||
let key ← match thmId with
|
||||
| .decl declName _ _ =>
|
||||
if (← getEnv).contains declName then
|
||||
pure m!"{MessageData.ofConst (← mkConstWithLevelParams declName)}"
|
||||
else
|
||||
pure m!"{declName} (builtin simproc)"
|
||||
| .fvar fvarId => pure m!"{mkFVar fvarId}"
|
||||
| _ => pure thmId.key
|
||||
let key ← originToKey thmId
|
||||
let usedMsg ← if let some usedCounters := usedCounters? then
|
||||
if let some c := usedCounters.find? thmId then pure s!", succeeded: {c}" else pure s!" {crossEmoji}" -- not used
|
||||
else
|
||||
@@ -32,16 +35,28 @@ def mkSimpDiagSummary (counters : PHashMap Origin Nat) (usedCounters? : Option (
|
||||
data := data.push m!"{if data.isEmpty then " " else "\n"}{key} ↦ {counter}{usedMsg}"
|
||||
return { data, max := entries[0]!.2 }
|
||||
|
||||
private def mkTheoremsWithBadKeySummary (thms : PArray SimpTheorem) : MetaM DiagSummary := do
|
||||
if thms.isEmpty then
|
||||
return {}
|
||||
else
|
||||
let mut data := #[]
|
||||
for thm in thms do
|
||||
data := data.push m!"{if data.isEmpty then " " else "\n"}{← originToKey thm.origin}, key: {thm.keys.map (·.format)}"
|
||||
pure ()
|
||||
return { data }
|
||||
|
||||
def reportDiag (diag : Simp.Diagnostics) : MetaM Unit := do
|
||||
if (← isDiagnosticsEnabled) then
|
||||
let used ← mkSimpDiagSummary diag.usedThmCounter
|
||||
let tried ← mkSimpDiagSummary diag.triedThmCounter diag.usedThmCounter
|
||||
let congr ← mkDiagSummary diag.congrThmCounter
|
||||
unless used.isEmpty && tried.isEmpty && congr.isEmpty do
|
||||
let thmsWithBadKeys ← mkTheoremsWithBadKeySummary diag.thmsWithBadKeys
|
||||
unless used.isEmpty && tried.isEmpty && congr.isEmpty && thmsWithBadKeys.isEmpty do
|
||||
let m := MessageData.nil
|
||||
let m := appendSection m `simp "used theorems" used
|
||||
let m := appendSection m `simp "tried theorems" tried
|
||||
let m := appendSection m `simp "tried congruence theorems" congr
|
||||
let m := appendSection m `simp "theorems with bad keys" thmsWithBadKeys (resultSummary := false)
|
||||
let m := m ++ "use `set_option diagnostics.threshold <num>` to control threshold for reporting counters"
|
||||
logInfo m
|
||||
|
||||
|
||||
@@ -189,19 +189,62 @@ def tryTheorem? (e : Expr) (thm : SimpTheorem) : SimpM (Option Result) := do
|
||||
Remark: the parameter tag is used for creating trace messages. It is irrelevant otherwise.
|
||||
-/
|
||||
def rewrite? (e : Expr) (s : SimpTheoremTree) (erased : PHashSet Origin) (tag : String) (rflOnly : Bool) : SimpM (Option Result) := do
|
||||
let candidates ← s.getMatchWithExtra e (getDtConfig (← getConfig))
|
||||
if candidates.isEmpty then
|
||||
trace[Debug.Meta.Tactic.simp] "no theorems found for {tag}-rewriting {e}"
|
||||
return none
|
||||
if (← getConfig).index then
|
||||
rewriteUsingIndex?
|
||||
else
|
||||
let candidates := candidates.insertionSort fun e₁ e₂ => e₁.1.priority > e₂.1.priority
|
||||
for (thm, numExtraArgs) in candidates do
|
||||
unless inErasedSet thm || (rflOnly && !thm.rfl) do
|
||||
if let some result ← tryTheoremWithExtraArgs? e thm numExtraArgs then
|
||||
trace[Debug.Meta.Tactic.simp] "rewrite result {e} => {result.expr}"
|
||||
return some result
|
||||
return none
|
||||
rewriteNoIndex?
|
||||
where
|
||||
/-- For `(← getConfig).index := true`, use discrimination tree structure when collecting `simp` theorem candidates. -/
|
||||
rewriteUsingIndex? : SimpM (Option Result) := do
|
||||
let candidates ← s.getMatchWithExtra e (getDtConfig (← getConfig))
|
||||
if candidates.isEmpty then
|
||||
trace[Debug.Meta.Tactic.simp] "no theorems found for {tag}-rewriting {e}"
|
||||
return none
|
||||
else
|
||||
let candidates := candidates.insertionSort fun e₁ e₂ => e₁.1.priority > e₂.1.priority
|
||||
for (thm, numExtraArgs) in candidates do
|
||||
unless inErasedSet thm || (rflOnly && !thm.rfl) do
|
||||
if let some result ← tryTheoremWithExtraArgs? e thm numExtraArgs then
|
||||
trace[Debug.Meta.Tactic.simp] "rewrite result {e} => {result.expr}"
|
||||
return some result
|
||||
return none
|
||||
|
||||
/--
|
||||
For `(← getConfig).index := false`, Lean 3 style `simp` theorem retrieval.
|
||||
Only the root symbol is taken into account. Most of the structure of the discrimination tree is ignored.
|
||||
-/
|
||||
rewriteNoIndex? : SimpM (Option Result) := do
|
||||
let (candidates, numArgs) ← s.getMatchLiberal e (getDtConfig (← getConfig))
|
||||
if candidates.isEmpty then
|
||||
trace[Debug.Meta.Tactic.simp] "no theorems found for {tag}-rewriting {e}"
|
||||
return none
|
||||
else
|
||||
let candidates := candidates.insertionSort fun e₁ e₂ => e₁.priority > e₂.priority
|
||||
for thm in candidates do
|
||||
unless inErasedSet thm || (rflOnly && !thm.rfl) do
|
||||
let result? ← withNewMCtxDepth do
|
||||
let val ← thm.getValue
|
||||
let type ← inferType val
|
||||
let (xs, bis, type) ← forallMetaTelescopeReducing type
|
||||
let type ← whnf (← instantiateMVars type)
|
||||
let lhs := type.appFn!.appArg!
|
||||
let lhsNumArgs := lhs.getAppNumArgs
|
||||
tryTheoremCore lhs xs bis val type e thm (numArgs - lhsNumArgs)
|
||||
if let some result := result? then
|
||||
trace[Debug.Meta.Tactic.simp] "rewrite result {e} => {result.expr}"
|
||||
diagnoseWhenNoIndex thm
|
||||
return some result
|
||||
return none
|
||||
|
||||
diagnoseWhenNoIndex (thm : SimpTheorem) : SimpM Unit := do
|
||||
if (← isDiagnosticsEnabled) then
|
||||
let candidates ← s.getMatchWithExtra e (getDtConfig (← getConfig))
|
||||
for (candidate, _) in candidates do
|
||||
if unsafe ptrEq thm candidate then
|
||||
return ()
|
||||
-- `thm` would not have been applied if `index := true`
|
||||
recordTheoremWithBadKeys thm
|
||||
|
||||
inErasedSet (thm : SimpTheorem) : Bool :=
|
||||
erased.contains thm.origin
|
||||
|
||||
|
||||
@@ -111,6 +111,13 @@ structure Diagnostics where
|
||||
triedThmCounter : PHashMap Origin Nat := {}
|
||||
/-- Number of times each congr theorem has been tried. -/
|
||||
congrThmCounter : PHashMap Name Nat := {}
|
||||
/--
|
||||
When using `Simp.Config.index := false`, and `set_option diagnostics true`,
|
||||
for every theorem used by `simp`, we check whether the theorem would be
|
||||
also applied if `index := true`, and we store it here if it would not have
|
||||
been tried.
|
||||
-/
|
||||
thmsWithBadKeys : PArray SimpTheorem := {}
|
||||
deriving Inhabited
|
||||
|
||||
structure State where
|
||||
@@ -325,14 +332,14 @@ Save current cache, reset it, execute `x`, and then restore original cache.
|
||||
withReader (fun r => { MethodsRef.toMethods r with discharge?, wellBehavedDischarge }.toMethodsRef) x
|
||||
|
||||
def recordTriedSimpTheorem (thmId : Origin) : SimpM Unit := do
|
||||
modifyDiag fun { usedThmCounter, triedThmCounter, congrThmCounter } =>
|
||||
let cNew := if let some c := triedThmCounter.find? thmId then c + 1 else 1
|
||||
{ usedThmCounter, triedThmCounter := triedThmCounter.insert thmId cNew, congrThmCounter }
|
||||
modifyDiag fun s =>
|
||||
let cNew := if let some c := s.triedThmCounter.find? thmId then c + 1 else 1
|
||||
{ s with triedThmCounter := s.triedThmCounter.insert thmId cNew }
|
||||
|
||||
def recordSimpTheorem (thmId : Origin) : SimpM Unit := do
|
||||
modifyDiag fun { usedThmCounter, triedThmCounter, congrThmCounter } =>
|
||||
let cNew := if let some c := usedThmCounter.find? thmId then c + 1 else 1
|
||||
{ usedThmCounter := usedThmCounter.insert thmId cNew, triedThmCounter, congrThmCounter }
|
||||
modifyDiag fun s =>
|
||||
let cNew := if let some c := s.usedThmCounter.find? thmId then c + 1 else 1
|
||||
{ s with usedThmCounter := s.usedThmCounter.insert thmId cNew }
|
||||
/-
|
||||
If `thmId` is an equational theorem (e.g., `foo.eq_1`), we should record `foo` instead.
|
||||
See issue #3547.
|
||||
@@ -353,9 +360,17 @@ def recordSimpTheorem (thmId : Origin) : SimpM Unit := do
|
||||
{ s with usedTheorems := s.usedTheorems.insert thmId n }
|
||||
|
||||
def recordCongrTheorem (declName : Name) : SimpM Unit := do
|
||||
modifyDiag fun { usedThmCounter, triedThmCounter, congrThmCounter } =>
|
||||
let cNew := if let some c := congrThmCounter.find? declName then c + 1 else 1
|
||||
{ congrThmCounter := congrThmCounter.insert declName cNew, triedThmCounter, usedThmCounter }
|
||||
modifyDiag fun s =>
|
||||
let cNew := if let some c := s.congrThmCounter.find? declName then c + 1 else 1
|
||||
{ s with congrThmCounter := s.congrThmCounter.insert declName cNew }
|
||||
|
||||
def recordTheoremWithBadKeys (thm : SimpTheorem) : SimpM Unit := do
|
||||
modifyDiag fun s =>
|
||||
-- check whether it is already there
|
||||
if unsafe s.thmsWithBadKeys.any fun thm' => ptrEq thm thm' then
|
||||
s
|
||||
else
|
||||
{ s with thmsWithBadKeys := s.thmsWithBadKeys.push thm }
|
||||
|
||||
def Result.getProof (r : Result) : MetaM Expr := do
|
||||
match r.proof? with
|
||||
|
||||
782
tests/lean/run/4171.lean
Normal file
782
tests/lean/run/4171.lean
Normal file
@@ -0,0 +1,782 @@
|
||||
/-!
|
||||
This is a minimization of a problem in Mathlib where a simp lemma `foo` would not fire,
|
||||
but variants:
|
||||
* `simp [(foo)]`
|
||||
* `simp [foo.{v₁ + 1}]`
|
||||
* `simp [foo']`, where a `no_index` is added in the statement
|
||||
all work.
|
||||
-/
|
||||
|
||||
section Mathlib.Data.Opposite
|
||||
|
||||
universe v u
|
||||
|
||||
variable (α : Sort u)
|
||||
|
||||
structure Opposite :=
|
||||
op ::
|
||||
unop : α
|
||||
|
||||
notation:max α "ᵒᵖ" => Opposite α
|
||||
|
||||
end Mathlib.Data.Opposite
|
||||
|
||||
section Mathlib.Combinatorics.Quiver.Basic
|
||||
|
||||
open Opposite
|
||||
|
||||
universe v v₁ v₂ u u₁ u₂
|
||||
|
||||
class Quiver (V : Type u) where
|
||||
Hom : V → V → Sort v
|
||||
|
||||
infixr:10 " ⟶ " => Quiver.Hom
|
||||
|
||||
structure Prefunctor (V : Type u₁) [Quiver.{v₁} V] (W : Type u₂) [Quiver.{v₂} W] where
|
||||
obj : V → W
|
||||
map : ∀ {X Y : V}, (X ⟶ Y) → (obj X ⟶ obj Y)
|
||||
namespace Quiver
|
||||
|
||||
instance opposite {V} [Quiver V] : Quiver Vᵒᵖ :=
|
||||
⟨fun a b => (unop b ⟶ unop a)ᵒᵖ⟩
|
||||
|
||||
def Hom.op {V} [Quiver V] {X Y : V} (f : X ⟶ Y) : op Y ⟶ op X := ⟨f⟩
|
||||
|
||||
def Hom.unop {V} [Quiver V] {X Y : Vᵒᵖ} (f : X ⟶ Y) : unop Y ⟶ unop X := Opposite.unop f
|
||||
|
||||
end Quiver
|
||||
|
||||
|
||||
end Mathlib.Combinatorics.Quiver.Basic
|
||||
|
||||
section Mathlib.CategoryTheory.Category.Basic
|
||||
|
||||
universe v u
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
class CategoryStruct (obj : Type u) extends Quiver.{v + 1} obj : Type max u (v + 1) where
|
||||
id : ∀ X : obj, Hom X X
|
||||
comp : ∀ {X Y Z : obj}, (X ⟶ Y) → (Y ⟶ Z) → (X ⟶ Z)
|
||||
|
||||
scoped notation "𝟙" => CategoryStruct.id
|
||||
|
||||
scoped infixr:80 " ≫ " => CategoryStruct.comp
|
||||
|
||||
class Category (obj : Type u) extends CategoryStruct.{v} obj : Type max u (v + 1) where
|
||||
id_comp : ∀ {X Y : obj} (f : X ⟶ Y), 𝟙 X ≫ f = f
|
||||
comp_id : ∀ {X Y : obj} (f : X ⟶ Y), f ≫ 𝟙 Y = f
|
||||
|
||||
attribute [simp] Category.id_comp Category.comp_id
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
end Mathlib.CategoryTheory.Category.Basic
|
||||
|
||||
section Mathlib.CategoryTheory.Functor.Basic
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
universe v v₁ v₂ v₃ u u₁ u₂ u₃
|
||||
|
||||
structure Functor (C : Type u₁) [Category.{v₁} C] (D : Type u₂) [Category.{v₂} D]
|
||||
extends Prefunctor C D : Type max v₁ v₂ u₁ u₂ where
|
||||
|
||||
infixr:26 " ⥤ " => Functor
|
||||
|
||||
namespace Functor
|
||||
|
||||
section
|
||||
|
||||
variable (C : Type u₁) [Category.{v₁} C]
|
||||
|
||||
protected def id : C ⥤ C where
|
||||
obj X := X
|
||||
map f := f
|
||||
|
||||
notation "𝟭" => Functor.id
|
||||
|
||||
variable {C}
|
||||
|
||||
@[simp]
|
||||
theorem id_obj (X : C) : (𝟭 C).obj X = X := rfl
|
||||
|
||||
end
|
||||
|
||||
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D]
|
||||
{E : Type u₃} [Category.{v₃} E]
|
||||
|
||||
@[simp]
|
||||
def comp (F : C ⥤ D) (G : D ⥤ E) : C ⥤ E where
|
||||
obj X := G.obj (F.obj X)
|
||||
map f := G.map (F.map f)
|
||||
|
||||
infixr:80 " ⋙ " => Functor.comp
|
||||
|
||||
end Functor
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
|
||||
end Mathlib.CategoryTheory.Functor.Basic
|
||||
|
||||
section Mathlib.CategoryTheory.NatTrans
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
universe v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄
|
||||
|
||||
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D]
|
||||
|
||||
structure NatTrans (F G : C ⥤ D) : Type max u₁ v₂ where
|
||||
app : ∀ X : C, F.obj X ⟶ G.obj X
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
end Mathlib.CategoryTheory.NatTrans
|
||||
|
||||
section Mathlib.CategoryTheory.Iso
|
||||
|
||||
universe v u
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
open Category
|
||||
|
||||
structure Iso {C : Type u} [Category.{v} C] (X Y : C) where
|
||||
hom : X ⟶ Y
|
||||
inv : Y ⟶ X
|
||||
|
||||
infixr:10 " ≅ " => Iso
|
||||
|
||||
variable {C : Type u} [Category.{v} C] {X Y Z : C}
|
||||
|
||||
namespace Iso
|
||||
|
||||
@[simp]
|
||||
def symm (I : X ≅ Y) : Y ≅ X where
|
||||
hom := I.inv
|
||||
inv := I.hom
|
||||
|
||||
@[simp]
|
||||
def refl (X : C) : X ≅ X where
|
||||
hom := 𝟙 X
|
||||
inv := 𝟙 X
|
||||
|
||||
@[simp]
|
||||
def trans (α : X ≅ Y) (β : Y ≅ Z) : X ≅ Z where
|
||||
hom := α.hom ≫ β.hom
|
||||
inv := β.inv ≫ α.inv
|
||||
|
||||
infixr:80 " ≪≫ " => Iso.trans
|
||||
|
||||
end Iso
|
||||
|
||||
namespace Functor
|
||||
|
||||
universe u₂ v₂
|
||||
|
||||
variable {D : Type u₂} [Category.{v₂} D]
|
||||
|
||||
@[simp]
|
||||
def mapIso (F : C ⥤ D) {X Y : C} (i : X ≅ Y) : F.obj X ≅ F.obj Y where
|
||||
hom := F.map i.hom
|
||||
inv := F.map i.inv
|
||||
|
||||
end Functor
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
|
||||
end Mathlib.CategoryTheory.Iso
|
||||
|
||||
section Mathlib.CategoryTheory.Functor.Category
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
universe v₁ v₂ v₃ u₁ u₂ u₃
|
||||
|
||||
variable (C : Type u₁) [Category.{v₁} C] (D : Type u₂) [Category.{v₂} D]
|
||||
|
||||
instance Functor.category : Category.{max u₁ v₂} (C ⥤ D) where
|
||||
Hom F G := NatTrans F G
|
||||
id F := sorry
|
||||
comp α β := sorry
|
||||
id_comp := sorry
|
||||
comp_id := sorry
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
end Mathlib.CategoryTheory.Functor.Category
|
||||
|
||||
section Mathlib.CategoryTheory.NatIso
|
||||
|
||||
|
||||
open CategoryTheory
|
||||
|
||||
universe v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D]
|
||||
|
||||
namespace Iso
|
||||
|
||||
@[simp]
|
||||
def app {F G : C ⥤ D} (α : F ≅ G) (X : C) : F.obj X ≅ G.obj X where
|
||||
hom := α.hom.app X
|
||||
inv := α.inv.app X
|
||||
|
||||
end Iso
|
||||
|
||||
namespace NatIso
|
||||
|
||||
variable {F G : C ⥤ D} {X : C}
|
||||
|
||||
@[simp]
|
||||
def ofComponents (app : ∀ X : C, F.obj X ≅ G.obj X) :
|
||||
F ≅ G where
|
||||
hom :=
|
||||
{ app := fun X => (app X).hom }
|
||||
inv :=
|
||||
{ app := fun X => (app X).inv }
|
||||
|
||||
end NatIso
|
||||
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
|
||||
end Mathlib.CategoryTheory.NatIso
|
||||
|
||||
section Mathlib.CategoryTheory.Equivalence
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
open CategoryTheory.Functor NatIso Category
|
||||
|
||||
universe v₁ v₂ v₃ u₁ u₂ u₃
|
||||
|
||||
structure Equivalence (C : Type u₁) (D : Type u₂) [Category.{v₁} C] [Category.{v₂} D] where mk' ::
|
||||
functor : C ⥤ D
|
||||
inverse : D ⥤ C
|
||||
unitIso : 𝟭 C ≅ functor ⋙ inverse
|
||||
counitIso : inverse ⋙ functor ≅ 𝟭 D
|
||||
|
||||
infixr:10 " ≌ " => Equivalence
|
||||
|
||||
variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D]
|
||||
|
||||
@[simp]
|
||||
def Equivalence.symm (e : C ≌ D) : D ≌ C :=
|
||||
⟨e.inverse, e.functor, e.counitIso.symm, e.unitIso.symm⟩
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
|
||||
end Mathlib.CategoryTheory.Equivalence
|
||||
|
||||
section Mathlib.CategoryTheory.Opposites
|
||||
|
||||
universe v₁ v₂ u₁ u₂
|
||||
|
||||
open Opposite
|
||||
|
||||
variable {C : Type u₁}
|
||||
|
||||
@[simp]
|
||||
theorem Quiver.Hom.unop_op [Quiver.{v₁} C] {X Y : C} (f : X ⟶ Y) : f.op.unop = f :=
|
||||
rfl
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
variable [Category.{v₁} C]
|
||||
|
||||
instance Category.opposite : Category.{v₁} Cᵒᵖ where
|
||||
comp f g := (g.unop ≫ f.unop).op
|
||||
id X := (𝟙 (unop X)).op
|
||||
id_comp := sorry
|
||||
comp_id := sorry
|
||||
|
||||
protected def Iso.op {X Y : C} (α : X ≅ Y) : op Y ≅ op X where
|
||||
hom := α.hom.op
|
||||
inv := α.inv.op
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
|
||||
end Mathlib.CategoryTheory.Opposites
|
||||
|
||||
section Mathlib.CategoryTheory.Monoidal.Category
|
||||
|
||||
universe v u
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
class MonoidalCategoryStruct (C : Type u) [𝒞 : Category.{v} C] where
|
||||
tensorObj : C → C → C
|
||||
whiskerLeft (X : C) {Y₁ Y₂ : C} (f : Y₁ ⟶ Y₂) : tensorObj X Y₁ ⟶ tensorObj X Y₂
|
||||
whiskerRight {X₁ X₂ : C} (f : X₁ ⟶ X₂) (Y : C) : tensorObj X₁ Y ⟶ tensorObj X₂ Y
|
||||
tensorHom {X₁ Y₁ X₂ Y₂ : C} (f : X₁ ⟶ Y₁) (g: X₂ ⟶ Y₂) : (tensorObj X₁ X₂ ⟶ tensorObj Y₁ Y₂) :=
|
||||
whiskerRight f X₂ ≫ whiskerLeft Y₁ g
|
||||
tensorUnit : C
|
||||
rightUnitor : ∀ X : C, tensorObj X tensorUnit ≅ X
|
||||
|
||||
namespace MonoidalCategory
|
||||
|
||||
scoped infixr:70 " ⊗ " => MonoidalCategoryStruct.tensorObj
|
||||
scoped infixr:81 " ◁ " => MonoidalCategoryStruct.whiskerLeft
|
||||
scoped infixl:81 " ▷ " => MonoidalCategoryStruct.whiskerRight
|
||||
scoped infixr:70 " ⊗ " => MonoidalCategoryStruct.tensorHom
|
||||
scoped notation "𝟙_ " C:max => (MonoidalCategoryStruct.tensorUnit : C)
|
||||
scoped notation "ρ_" => MonoidalCategoryStruct.rightUnitor
|
||||
|
||||
end MonoidalCategory
|
||||
|
||||
open MonoidalCategory
|
||||
|
||||
class MonoidalCategory (C : Type u) [𝒞 : Category.{v} C] extends MonoidalCategoryStruct C where
|
||||
id_whiskerRight : ∀ (X Y : C), 𝟙 X ▷ Y = 𝟙 (X ⊗ Y)
|
||||
|
||||
attribute [simp] MonoidalCategory.id_whiskerRight
|
||||
|
||||
namespace MonoidalCategory
|
||||
|
||||
variable {C : Type u} [𝒞 : Category.{v} C] [MonoidalCategory C]
|
||||
|
||||
@[simp]
|
||||
theorem id_tensorHom (X : C) {Y₁ Y₂ : C} (f : Y₁ ⟶ Y₂) :
|
||||
𝟙 X ⊗ f = X ◁ f := sorry
|
||||
|
||||
@[simp]
|
||||
theorem tensorHom_id {X₁ X₂ : C} (f : X₁ ⟶ X₂) (Y : C) :
|
||||
f ⊗ 𝟙 Y = f ▷ Y := sorry
|
||||
|
||||
end MonoidalCategory
|
||||
|
||||
@[simp]
|
||||
def tensorIso {C : Type u} {X Y X' Y' : C} [Category.{v} C] [MonoidalCategory.{v} C] (f : X ≅ Y)
|
||||
(g : X' ≅ Y') : X ⊗ X' ≅ Y ⊗ Y' where
|
||||
hom := f.hom ⊗ g.hom
|
||||
inv := f.inv ⊗ g.inv
|
||||
|
||||
infixr:70 " ⊗ " => tensorIso
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
end Mathlib.CategoryTheory.Monoidal.Category
|
||||
|
||||
section Mathlib.CategoryTheory.Monoidal.Opposite
|
||||
|
||||
universe v₁ v₂ u₁ u₂
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
variable {C : Type u₁} [Category.{v₁} C] [MonoidalCategory.{v₁} C]
|
||||
|
||||
open Opposite MonoidalCategory
|
||||
|
||||
instance monoidalCategoryOp : MonoidalCategory Cᵒᵖ where
|
||||
tensorObj X Y := op (unop X ⊗ unop Y)
|
||||
whiskerLeft X _ _ f := (X.unop ◁ f.unop).op
|
||||
whiskerRight f X := (f.unop ▷ X.unop).op
|
||||
tensorHom f g := (f.unop ⊗ g.unop).op
|
||||
tensorUnit := op (𝟙_ C)
|
||||
id_whiskerRight := sorry
|
||||
rightUnitor X := (ρ_ (unop X)).symm.op
|
||||
|
||||
|
||||
@[simp] theorem op_whiskerLeft (X : C) {Y Z : C} (f : Y ⟶ Z) :
|
||||
(X ◁ f).op = op X ◁ f.op := rfl
|
||||
@[simp] theorem unop_whiskerLeft (X : Cᵒᵖ) {Y Z : Cᵒᵖ} (f : Y ⟶ Z) :
|
||||
(X ◁ f).unop = unop X ◁ f.unop := rfl
|
||||
|
||||
@[simp] theorem op_hom_rightUnitor (X : C) : (ρ_ X).hom.op = (ρ_ (op X)).inv := rfl
|
||||
@[simp] theorem unop_hom_rightUnitor (X : Cᵒᵖ) : (ρ_ X).hom.unop = (ρ_ (unop X)).inv := rfl
|
||||
|
||||
@[simp] theorem op_inv_rightUnitor (X : C) : (ρ_ X).inv.op = (ρ_ (op X)).hom := rfl
|
||||
@[simp] theorem unop_inv_rightUnitor (X : Cᵒᵖ) : (ρ_ X).inv.unop = (ρ_ (unop X)).hom := rfl
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
|
||||
end Mathlib.CategoryTheory.Monoidal.Opposite
|
||||
|
||||
section Mathlib.CategoryTheory.Monoidal.Transport
|
||||
|
||||
universe v₁ v₂ u₁ u₂
|
||||
|
||||
noncomputable section
|
||||
|
||||
open CategoryTheory Category MonoidalCategory
|
||||
|
||||
namespace CategoryTheory.Monoidal
|
||||
|
||||
variable {C : Type u₁} [Category.{v₁} C] [MonoidalCategory.{v₁} C]
|
||||
variable {D : Type u₂} [Category.{v₂} D]
|
||||
|
||||
abbrev induced [MonoidalCategoryStruct D] (F : D ⥤ C) :
|
||||
MonoidalCategory.{v₂} D where
|
||||
id_whiskerRight X Y := sorry
|
||||
|
||||
def transportStruct (e : C ≌ D) : MonoidalCategoryStruct.{v₂} D where
|
||||
tensorObj X Y := e.functor.obj (e.inverse.obj X ⊗ e.inverse.obj Y)
|
||||
whiskerLeft X _ _ f := e.functor.map (e.inverse.obj X ◁ e.inverse.map f)
|
||||
whiskerRight f X := sorry
|
||||
tensorHom f g := sorry
|
||||
tensorUnit := e.functor.obj (𝟙_ C)
|
||||
rightUnitor X :=
|
||||
e.functor.mapIso ((Iso.refl _ ⊗ (e.unitIso.app _).symm) ≪≫ ρ_ (e.inverse.obj X)) ≪≫
|
||||
e.counitIso.app _
|
||||
|
||||
@[simp] theorem transportStruct_whiskerLeft (e : C ≌ D) (X x x_1 : D) (f : x ⟶ x_1) :
|
||||
(transportStruct e).whiskerLeft X f = e.functor.map (e.inverse.obj X ◁ e.inverse.map f) := rfl
|
||||
|
||||
@[simp] theorem transportStruct_rightUnitor (e : C ≌ D) (X : D) :
|
||||
(transportStruct e).rightUnitor X =
|
||||
e.functor.mapIso ((Iso.refl _ ⊗ (e.unitIso.app _).symm) ≪≫ ρ_ (e.inverse.obj X)) ≪≫
|
||||
e.counitIso.app _ := rfl
|
||||
|
||||
def transport (e : C ≌ D) : MonoidalCategory.{v₂} D :=
|
||||
letI : MonoidalCategoryStruct.{v₂} D := transportStruct e
|
||||
induced e.inverse
|
||||
|
||||
end CategoryTheory.Monoidal
|
||||
|
||||
end
|
||||
|
||||
end Mathlib.CategoryTheory.Monoidal.Transport
|
||||
|
||||
section Mathlib.CategoryTheory.Monoidal.Braided.Basic
|
||||
|
||||
open CategoryTheory MonoidalCategory
|
||||
|
||||
universe v v₁ v₂ v₃ u u₁ u₂ u₃
|
||||
|
||||
namespace CategoryTheory
|
||||
|
||||
variable (C : Type u₁) [Category.{v₁} C] [MonoidalCategory C]
|
||||
|
||||
def tensor_μ (X Y : C × C) : (X.1 ⊗ X.2) ⊗ Y.1 ⊗ Y.2 ⟶ (X.1 ⊗ Y.1) ⊗ X.2 ⊗ Y.2 :=
|
||||
sorry
|
||||
|
||||
end CategoryTheory
|
||||
|
||||
end Mathlib.CategoryTheory.Monoidal.Braided.Basic
|
||||
|
||||
section Mathlib.CategoryTheory.Monoidal.Mon_
|
||||
|
||||
universe v₁ v₂ u₁ u₂ u
|
||||
|
||||
open CategoryTheory MonoidalCategory
|
||||
|
||||
variable (C : Type u₁) [Category.{v₁} C] [MonoidalCategory.{v₁} C]
|
||||
|
||||
structure Mon_ where
|
||||
X : C
|
||||
one : 𝟙_ C ⟶ X
|
||||
mul : X ⊗ X ⟶ X
|
||||
mul_one : (X ◁ one) ≫ mul = (ρ_ X).hom
|
||||
|
||||
attribute [simp] Mon_.mul_one
|
||||
namespace Mon_
|
||||
|
||||
@[simp]
|
||||
def trivial : Mon_ C where
|
||||
X := 𝟙_ C
|
||||
one := 𝟙 _
|
||||
mul := sorry
|
||||
mul_one := sorry
|
||||
|
||||
variable {C}
|
||||
variable {M : Mon_ C}
|
||||
|
||||
structure Hom (M N : Mon_ C) where
|
||||
hom : M.X ⟶ N.X
|
||||
|
||||
@[simp]
|
||||
def id (M : Mon_ C) : Hom M M where
|
||||
hom := 𝟙 M.X
|
||||
|
||||
@[simp]
|
||||
def comp {M N O : Mon_ C} (f : Hom M N) (g : Hom N O) : Hom M O where
|
||||
hom := f.hom ≫ g.hom
|
||||
|
||||
instance : Category (Mon_ C) where
|
||||
Hom M N := Hom M N
|
||||
id := id
|
||||
comp f g := comp f g
|
||||
id_comp := sorry
|
||||
comp_id := sorry
|
||||
|
||||
@[ext]
|
||||
theorem ext {X Y : Mon_ C} {f g : X ⟶ Y} (w : f.hom = g.hom) : f = g := sorry
|
||||
|
||||
@[simp]
|
||||
theorem id_hom' (M : Mon_ C) : (𝟙 M : Hom M M).hom = 𝟙 M.X := sorry
|
||||
|
||||
@[simp]
|
||||
theorem comp_hom' {M N K : Mon_ C} (f : M ⟶ N) (g : N ⟶ K) :
|
||||
(f ≫ g : Hom M K).hom = f.hom ≫ g.hom := sorry
|
||||
|
||||
variable (C) in
|
||||
@[simp]
|
||||
def forget : Mon_ C ⥤ C where
|
||||
obj A := A.X
|
||||
map f := f.hom
|
||||
|
||||
@[simp]
|
||||
def isoOfIso {M N : Mon_ C} (f : M.X ≅ N.X) : M ≅ N where
|
||||
hom := { hom := f.hom }
|
||||
inv := { hom := f.inv }
|
||||
|
||||
|
||||
|
||||
@[simp]
|
||||
instance monMonoidalStruct : MonoidalCategoryStruct (Mon_ C) :=
|
||||
let tensorObj (M N : Mon_ C) : Mon_ C :=
|
||||
{ X := M.X ⊗ N.X
|
||||
one := sorry
|
||||
mul := tensor_μ C (M.X, N.X) (M.X, N.X) ≫ (M.mul ⊗ N.mul)
|
||||
mul_one := sorry }
|
||||
let tensorHom {X₁ Y₁ X₂ Y₂ : Mon_ C} (f : X₁ ⟶ Y₁) (g : X₂ ⟶ Y₂) :
|
||||
tensorObj _ _ ⟶ tensorObj _ _ :=
|
||||
{ hom := f.hom ⊗ g.hom }
|
||||
{ tensorObj := tensorObj
|
||||
tensorHom := tensorHom
|
||||
whiskerRight := fun f Y => tensorHom f (𝟙 Y)
|
||||
whiskerLeft := fun X _ _ g => tensorHom (𝟙 X) g
|
||||
tensorUnit := trivial C
|
||||
rightUnitor := fun M ↦ isoOfIso (ρ_ M.X) }
|
||||
|
||||
@[simp]
|
||||
theorem whiskerLeft_hom {X Y : Mon_ C} (f : X ⟶ Y) (Z : Mon_ C) :
|
||||
(f ▷ Z).hom = f.hom ▷ Z.X := by
|
||||
rw [← tensorHom_id]; rfl
|
||||
|
||||
@[simp]
|
||||
theorem whiskerRight_hom (X : Mon_ C) {Y Z : Mon_ C} (f : Y ⟶ Z) :
|
||||
(X ◁ f).hom = X.X ◁ f.hom := by
|
||||
rw [← id_tensorHom]; rfl
|
||||
|
||||
@[simp]
|
||||
theorem rightUnitor_inv_hom (X : Mon_ C) : (ρ_ X).inv.hom = (ρ_ X.X).inv := rfl
|
||||
|
||||
instance monMonoidal : MonoidalCategory (Mon_ C) where
|
||||
id_whiskerRight := sorry
|
||||
|
||||
end Mon_
|
||||
|
||||
end Mathlib.CategoryTheory.Monoidal.Mon_
|
||||
|
||||
section Mathlib.CategoryTheory.Monoidal.Comon_
|
||||
|
||||
universe v₁ v₂ u₁ u₂ u
|
||||
|
||||
open CategoryTheory MonoidalCategory
|
||||
|
||||
variable (C : Type u₁) [Category.{v₁} C] [MonoidalCategory.{v₁} C]
|
||||
|
||||
structure Comon_ where
|
||||
X : C
|
||||
counit : X ⟶ 𝟙_ C
|
||||
comul : X ⟶ X ⊗ X
|
||||
|
||||
namespace Comon_
|
||||
|
||||
variable {C}
|
||||
variable {M : Comon_ C}
|
||||
|
||||
structure Hom (M N : Comon_ C) where
|
||||
hom : M.X ⟶ N.X
|
||||
|
||||
@[simp]
|
||||
def id (M : Comon_ C) : Hom M M where
|
||||
hom := 𝟙 M.X
|
||||
|
||||
@[simp]
|
||||
def comp {M N O : Comon_ C} (f : Hom M N) (g : Hom N O) : Hom M O where
|
||||
hom := f.hom ≫ g.hom
|
||||
|
||||
instance : Category (Comon_ C) where
|
||||
Hom M N := Hom M N
|
||||
id := id
|
||||
comp f g := comp f g
|
||||
comp_id := sorry
|
||||
id_comp := sorry
|
||||
|
||||
@[ext] theorem ext {X Y : Comon_ C} {f g : X ⟶ Y} (w : f.hom = g.hom) : f = g := sorry
|
||||
|
||||
@[simp] theorem id_hom' (M : Comon_ C) : (𝟙 M : Hom M M).hom = 𝟙 M.X := rfl
|
||||
|
||||
@[simp]
|
||||
theorem comp_hom' {M N K : Comon_ C} (f : M ⟶ N) (g : N ⟶ K) : (f ≫ g).hom = f.hom ≫ g.hom :=
|
||||
rfl
|
||||
|
||||
open Opposite
|
||||
|
||||
variable (C)
|
||||
|
||||
def Comon_to_Mon_op_op_obj' (A : Comon_ C) : Mon_ (Cᵒᵖ) where
|
||||
X := op A.X
|
||||
one := A.counit.op
|
||||
mul := A.comul.op
|
||||
mul_one := sorry
|
||||
|
||||
@[simp] theorem Comon_to_Mon_op_op_obj'_X (A : Comon_ C) : (Comon_to_Mon_op_op_obj' C A).X = op A.X := rfl
|
||||
|
||||
@[simp] def Comon_to_Mon_op_op : Comon_ C ⥤ (Mon_ (Cᵒᵖ))ᵒᵖ where
|
||||
obj A := op (Comon_to_Mon_op_op_obj' C A)
|
||||
map := fun f => op <| { hom := f.hom.op }
|
||||
|
||||
def Mon_op_op_to_Comon_obj' (A : (Mon_ (Cᵒᵖ))) : Comon_ C where
|
||||
X := unop A.X
|
||||
counit := A.one.unop
|
||||
comul := A.mul.unop
|
||||
|
||||
@[simp] theorem Mon_op_op_to_Comon_obj'_X (A : (Mon_ (Cᵒᵖ))) : (Mon_op_op_to_Comon_obj' C A).X = unop A.X := rfl
|
||||
|
||||
@[simp]
|
||||
def Mon_op_op_to_Comon : (Mon_ (Cᵒᵖ))ᵒᵖ ⥤ Comon_ C where
|
||||
obj A := Mon_op_op_to_Comon_obj' C (unop A)
|
||||
map := fun f =>
|
||||
{ hom := f.unop.hom.unop }
|
||||
|
||||
@[simp]
|
||||
def Comon_equiv_Mon_op_op : Comon_ C ≌ (Mon_ (Cᵒᵖ))ᵒᵖ :=
|
||||
{ functor := Comon_to_Mon_op_op C
|
||||
inverse := Mon_op_op_to_Comon C
|
||||
unitIso := NatIso.ofComponents (fun _ => Iso.refl _)
|
||||
counitIso := NatIso.ofComponents (fun _ => Iso.refl _) }
|
||||
|
||||
instance : MonoidalCategory (Comon_ C) :=
|
||||
Monoidal.transport (Comon_equiv_Mon_op_op C).symm
|
||||
|
||||
end Comon_
|
||||
|
||||
namespace CategoryTheory.Functor
|
||||
|
||||
variable {C} {D : Type u₂} [Category.{v₂} D] [MonoidalCategory.{v₂} D]
|
||||
|
||||
def mapComon (F : C ⥤ D) : Comon_ C ⥤ Comon_ D where
|
||||
obj A :=
|
||||
{ X := F.obj A.X
|
||||
counit := sorry
|
||||
comul := sorry }
|
||||
map f := sorry
|
||||
|
||||
end CategoryTheory.Functor
|
||||
|
||||
|
||||
end Mathlib.CategoryTheory.Monoidal.Comon_
|
||||
|
||||
section Mathlib.CategoryTheory.Monoidal.Bimon_
|
||||
|
||||
noncomputable section
|
||||
|
||||
universe v₁ v₂ u₁ u₂ u
|
||||
|
||||
open CategoryTheory MonoidalCategory
|
||||
|
||||
variable (C : Type u₁) [Category.{v₁} C] [MonoidalCategory.{v₁} C]
|
||||
|
||||
def toComon_ : Comon_ (Mon_ C) ⥤ Comon_ C := (Mon_.forget C).mapComon
|
||||
|
||||
@[simp] theorem toComon_obj_X (M : Comon_ (Mon_ C)) : ((toComon_ C).obj M).X = M.X.X := rfl
|
||||
|
||||
theorem foo {V} [Quiver V] {X Y x} :
|
||||
@Quiver.Hom.unop V _ X Y (Opposite.op (unop := x)) = x := rfl
|
||||
|
||||
example (M : Comon_ (Mon_ C)) : Mon_ (Comon_ C) where
|
||||
X := (toComon_ C).obj M
|
||||
one := { hom := M.X.one }
|
||||
mul := { hom := M.X.mul }
|
||||
mul_one := by
|
||||
ext
|
||||
simp [(foo)] -- parentheses around `foo` works
|
||||
|
||||
example (M : Comon_ (Mon_ C)) : Mon_ (Comon_ C) where
|
||||
X := (toComon_ C).obj M
|
||||
one := { hom := M.X.one }
|
||||
mul := { hom := M.X.mul }
|
||||
mul_one := by
|
||||
ext
|
||||
simp [foo.{v₁ + 1}] -- specifying the universe level explicitly works!
|
||||
|
||||
theorem foo' {V} [Quiver V] {X Y x} :
|
||||
@Quiver.Hom.unop V _ X Y no_index (Opposite.op (unop := x)) = x := rfl
|
||||
|
||||
example (M : Comon_ (Mon_ C)) : Mon_ (Comon_ C) where
|
||||
X := (toComon_ C).obj M
|
||||
one := { hom := M.X.one }
|
||||
mul := { hom := M.X.mul }
|
||||
mul_one := by
|
||||
ext
|
||||
simp [foo'] -- or adding a `no_index` in the statement
|
||||
|
||||
|
||||
/--
|
||||
info: [simp] theorems with bad keys
|
||||
foo, key: [Quiver.Hom.unop,
|
||||
*,
|
||||
*,
|
||||
*,
|
||||
*,
|
||||
Opposite.op,
|
||||
Quiver.Hom,
|
||||
*,
|
||||
*,
|
||||
Opposite.0,
|
||||
*,
|
||||
Opposite.0,
|
||||
*,
|
||||
*]use `set_option diagnostics.threshold <num>` to control threshold for reporting counters
|
||||
-/
|
||||
#guard_msgs in
|
||||
example (M : Comon_ (Mon_ C)) : Mon_ (Comon_ C) where
|
||||
X := (toComon_ C).obj M
|
||||
one := { hom := M.X.one }
|
||||
mul := { hom := M.X.mul, }
|
||||
mul_one := by
|
||||
ext
|
||||
-- increase the threshold to ensure the guard_msgs docstring is not too big.
|
||||
set_option diagnostics.threshold 100000 in
|
||||
set_option diagnostics true in
|
||||
-- `index := false` ignores most of the discrimination tree structure.
|
||||
simp (config := { index := false }) [foo]
|
||||
|
||||
attribute [simp] foo
|
||||
|
||||
/--
|
||||
info: [simp] theorems with bad keys
|
||||
foo, key: [Quiver.Hom.unop,
|
||||
*,
|
||||
*,
|
||||
*,
|
||||
*,
|
||||
Opposite.op,
|
||||
Quiver.Hom,
|
||||
*,
|
||||
*,
|
||||
Opposite.0,
|
||||
*,
|
||||
Opposite.0,
|
||||
*,
|
||||
*]use `set_option diagnostics.threshold <num>` to control threshold for reporting counters
|
||||
-/
|
||||
#guard_msgs in
|
||||
example (M : Comon_ (Mon_ C)) : Mon_ (Comon_ C) where
|
||||
X := (toComon_ C).obj M
|
||||
one := { hom := M.X.one }
|
||||
mul := { hom := M.X.mul, }
|
||||
mul_one := by
|
||||
ext
|
||||
-- increase the threshold to ensure the guard_msgs docstring is not too big.
|
||||
set_option diagnostics.threshold 100000 in
|
||||
set_option diagnostics true in
|
||||
-- `index := false` ignores most of the discrimination tree structure.
|
||||
simp (config := { index := false })
|
||||
|
||||
end
|
||||
|
||||
end Mathlib.CategoryTheory.Monoidal.Bimon_
|
||||
Reference in New Issue
Block a user