Applications have implicit arguments. Thus, two terms that may look identical when pretty-printed can be structurally different.
For example, @id (Id Nat) x
and @id Nat x
are structurally different but are both pretty-printed as id x
.
Moreover, these two terms are definitionally equal since Id Nat
reduces to Nat
. This may create situations
that are counterintuitive to our users. Furthermore, several tactics (e.g., omega
) need to collect unique atoms in a goal.
One simple approach is to maintain a list of atoms found so far, and whenever a new atom is discovered, perform a
linear scan to test whether it is definitionally equal to a previously found one. However, this method is too costly,
even if the definitional equality test were inexpensive.
This module aims to efficiently identify terms that are structurally different, definitionally equal, and structurally equal
when we disregard implicit arguments like @id (Id Nat) x
and @id Nat x
. The procedure is straightforward. For each atom,
we create a new abstracted atom by erasing all implicit information. We refer to this abstracted atom as a 'key.' For the two
terms mentioned, the key would be @id _ x
, where _
denotes a placeholder for a dummy term. To preserve any
pre-existing directed acyclic graph (DAG) structure and prevent exponential blowups while constructing the key, we employ
unsafe techniques, such as pointer equality. Additionally, we maintain a mapping from keys to lists of terms, where each
list contains terms sharing the same key but not definitionally equal. We posit that these lists will be small in practice.
Equations
- Lean.Meta.Canonicalizer.instInhabitedExprVisited = { default := { e := default } }
Equations
- Lean.Meta.Canonicalizer.instBEqExprVisited = { beq := fun (a b : Lean.Meta.Canonicalizer.ExprVisited) => ptrAddrUnsafe a == ptrAddrUnsafe b }
Equations
- Lean.Meta.Canonicalizer.instHashableExprVisited = { hash := fun (a : Lean.Meta.Canonicalizer.ExprVisited) => (ptrAddrUnsafe a).toUInt64 }
Instances For
State for the CanonM
monad.
"Set" of all keys created so far. This is a hash-consing helper structure available in Lean.
Mapping from
Expr
toKey
. See comment atExprVisited
.- keyToExprs : Lean.HashMapImp Lean.Meta.Canonicalizer.Key (List Lean.Expr)
Given a key
k
andkeyToExprs.find? k = some es
, we have that alles
share keyk
, and are not definitionally equal modulo the transparency setting used.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Equations
Instances For
The definitionally equality tests are performed using the given transparency mode.
We claim TransparencyMode.instances
is a good setting for most applications.
Equations
- x.run transparency = (x transparency).run' { keys := ShareCommon.State.mk Lean.ShareCommon.objectFactory, cache := Lean.mkHashMapImp, keyToExprs := Lean.mkHashMapImp }
Instances For
"Canonicalize" the given expression.
Equations
- One or more equations did not get rendered due to their size.