* Reducible hints Lean automation can be configured using different commands and annotations. The =reducible= hint/annotation instructs automation which declarations can be freely unfolded. One of the main components of the Lean elaborator is a procedure for solving simultaneous higher-order unification constraints. Higher-order unification is a undecidable problem. Thus, the procedure implemented in Lean is clearly incomplete, that is, it may fail to find a solution for a set of constraints. One way to guide/help the procedure is to indicate which declarations can be unfolded. We should not confuse the =reducible= hint with whether a declaration is opaque or not. We say _opaqueness_ is part of the Lean logic, and is implemented inside of its trusted kernel. The =reducible= hint is just a way to control/guide Lean automation to fill missing gaps in our proofs and definitions. The Lean kernel ignores this annotation. The higher-order unification procedure has to perform case-analysis. The procedure is essentially implementing a backtracking search. This procedure has to decide whether a definition =C= should be unfolded or not. Here, we roughly divide this decision in two groups: _simple_ and _complex_. We say an unfolding decision is _simple_ if the procedure does not have to consider an extra case (aka case-split). That is, it does not increase the search space. We say an unfolding decision is _complex_ if it produces at least one extra case, and consequently increases the search space. Users can mark whether a definition is =reducible= or =irreducible=. We write =reducible(C)= to denote that =C= was marked as reducible by the user, and =irreducible(C)= to denote that =C= was marked as irreducible by the user. Theorems are never unfolded. For a transparent definition =C=, the higher-order unification procedure uses the following decision tree. #+BEGIN_SRC if simple unfolding decision then if irreducible(C) then do not unfold else unfold end else -- complex unfolding decision if reducible(C) then unfold else if irreducible(C) then do not unfold else if C was defined in the current module then unfold else do not unfold end end #+END_SRC For an opaque definition =D=, the higher-order unification procedure uses the same decision tree if =D= was declared in the current module. Otherwise, it does not unfold =D=. #+END_SRC The following command declares a transparent definition =pr= and mark it as reducible. #+BEGIN_SRC lean definition pr1 [reducible] (A : Type) (a b : A) : A := a #+END_SRC The =reducible= mark is saved in the compiled .olean files. The user can temporarily change the =reducible= and =irreducible= marks using the following commands. The temporary modification is effective only in the current file, and is not saved in the produced .olean file. #+BEGIN_SRC lean definition id (A : Type) (a : A) : A := a definition pr2 (A : Type) (a b : A) : A := b -- mark pr2 as reducible reducible pr2 -- ... -- mark id and pr2 as irreducible irreducible id pr2 #+END_SRC The annotation =[persistent]= can be used to instruct Lean to make the modification permanent, and save it in the .olean file. #+BEGIN_SRC lean definition pr2 (A : Type) (a b : A) : A := b -- Mark pr2 as irreducible. -- The modification will affect modules that import this one. irreducible [persistent] pr2 #+END_SRC The reducible and irreducible annotations can be removed using the modifier =[none]=. #+BEGIN_SRC lean definition pr2 (A : Type) (a b : A) : A := b -- temporarily remove any reducible and irreducible annotation from pr2 reducible [none] pr2 -- permanently remove any reducible and irreducible annotation from pr2 reducible [persistent] [none] pr2 #+END_SRC Finally, the command =irreducible= is syntax sugar for =reducible [off]=. The commands =reducible= and =reducible [on]= are equivalent.