@@ -3,6 +3,8 @@ Copyright (c) 2017 Johannes Hölzl. All rights reserved.
33Released under Apache 2.0 license as described in the file LICENSE.
44Authors: Johannes Hölzl, Yury Kudryashov, Yaël Dillies
55-/
6+ import Qq
7+ import Mathlib.Lean.PrettyPrinter.Delaborator
68import Mathlib.Tactic.TypeStar
79import Mathlib.Tactic.Simps.NotationClass
810
@@ -13,17 +15,22 @@ In this file we introduce typeclasses and definitions for lattice operations.
1315
1416## Main definitions
1517
16- * the `⊔` notation is used for `Max` since November 2024
17- * the `⊓` notation is used for `Min` since November 2024
1818* `HasCompl`: type class for the `ᶜ` notation
1919* `Top`: type class for the `⊤` notation
2020* `Bot`: type class for the `⊥` notation
2121
2222 ## Notations
2323
24- * `x ⊔ y`: lattice join operation;
25- * `x ⊓ y`: lattice meet operation;
2624* `xᶜ`: complement in a lattice;
25+ * `x ⊔ y`: supremum/join, which is notation for `max x y`;
26+ * `x ⊓ y`: infimum/meet, which is notation for `min x y`;
27+
28+ We implement a delaborator that pretty prints `max x y`/`min x y` as `x ⊔ y`/`x ⊓ y`
29+ if and only if the order on `α` does not have a `LinearOrder α` instance (where `x y : α`).
30+
31+ This is so that in a lattice we can use the same underlying constants `max`/`min`
32+ as in linear orders, while using the more idiomatic notation `x ⊔ y`/`x ⊓ y`.
33+ Lemmas about the operators `⊔` and `⊓` should use the names `sup` and `inf` respectively.
2734
2835-/
2936
@@ -54,11 +61,80 @@ class Inf (α : Type*) where
5461
5562attribute [ext] Min Max
5663
57- @[inherit_doc]
58- infixl :68 " ⊔ " => Max.max
64+ /--
65+ The supremum/join operation: `x ⊔ y`. It is notation for `max x y`
66+ and should be used when the type is not a linear order.
67+ -/
68+ syntax :68 term:68 " ⊔ " term:69 : term
5969
60- @[inherit_doc]
61- infixl :69 " ⊓ " => Min.min
70+ /--
71+ The infimum/meet operation: `x ⊓ y`. It is notation for `min x y`
72+ and should be used when the type is not a linear order.
73+ -/
74+ syntax :69 term:69 " ⊓ " term:70 : term
75+
76+ macro_rules
77+ | `($a ⊔ $b) => `(Max.max $a $b)
78+ | `($a ⊓ $b) => `(Min.min $a $b)
79+
80+ namespace Mathlib.Meta
81+
82+ open Lean Meta PrettyPrinter Delaborator SubExpr Qq
83+
84+ -- irreducible to not confuse Qq
85+ @[irreducible] private def linearOrderExpr (u : Level) : Q(Type u → Type u) :=
86+ .const `LinearOrder [u]
87+ private def linearOrderToMax (u : Level) : Q((a : Type u) → $(linearOrderExpr u) a → Max a) :=
88+ .const `LinearOrder.toMax [u]
89+ private def linearOrderToMin (u : Level) : Q((a : Type u) → $(linearOrderExpr u) a → Min a) :=
90+ .const `LinearOrder.toMin [u]
91+
92+ /--
93+ Return `true` if `LinearOrder` is imported and `inst` comes from a `LinearOrder e` instance.
94+
95+ We use a `try catch` block to make sure there are no surprising errors during delaboration.
96+ -/
97+ private def hasLinearOrder (u : Level) (α : Q(Type u)) (cls : Q(Type u → Type u))
98+ (toCls : Q((α : Type u) → $(linearOrderExpr u) α → $cls α)) (inst : Q($cls $α)) :
99+ MetaM Bool := do
100+ try
101+ withNewMCtxDepth do
102+ -- `isDefEq` may call type class search to instantiate `mvar`, so we need the local instances
103+ -- In Lean 4.19 the pretty printer clears local instances, so we re-add them here.
104+ -- TODO(Jovan): remove
105+ withLocalInstances (← getLCtx).decls.toList.reduceOption do
106+ let mvar ← mkFreshExprMVarQ q($(linearOrderExpr u) $α) (kind := .synthetic)
107+ let inst' : Q($cls $α) := q($toCls $α $mvar)
108+ isDefEq inst inst'
109+ catch _ =>
110+ -- For instance, if `LinearOrder` is not yet imported.
111+ return false
112+
113+ /-- Delaborate `max x y` into `x ⊔ y` if the type is not a linear order. -/
114+ @[delab app.Max.max]
115+ def delabSup : Delab := do
116+ let_expr f@Max.max α inst _ _ := ← getExpr | failure
117+ have u := f.constLevels![0 ]!
118+ if ← hasLinearOrder u α q(Max) q($(linearOrderToMax u)) inst then
119+ failure -- use the default delaborator
120+ let x ← withNaryArg 2 delab
121+ let y ← withNaryArg 3 delab
122+ let stx ← `($x ⊔ $y)
123+ annotateGoToSyntaxDef stx
124+
125+ /-- Delaborate `min x y` into `x ⊓ y` if the type is not a linear order. -/
126+ @[delab app.Min.min]
127+ def delabInf : Delab := do
128+ let_expr f@Min.min α inst _ _ := ← getExpr | failure
129+ have u := f.constLevels![0 ]!
130+ if ← hasLinearOrder u α q(Min) q($(linearOrderToMin u)) inst then
131+ failure -- use the default delaborator
132+ let x ← withNaryArg 2 delab
133+ let y ← withNaryArg 3 delab
134+ let stx ← `($x ⊓ $y)
135+ annotateGoToSyntaxDef stx
136+
137+ end Mathlib.Meta
62138
63139/-- Syntax typeclass for Heyting implication `⇨`. -/
64140@[notation_class]
0 commit comments