diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 091947ea..52e30fa4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,7 +73,7 @@ In addition to what Verso provides, there are a number of additional roles, code Please use the following roles where they make sense: * `` {lean}`TERM` `` - `TERM` is a Lean term, to be elaborated as such and included it in the rendered document with appropriate highlighting. - The optional named argument `type` specifies an expected type, e.g. `` {lean type:="Nat"}`.succ .zero` `` + The optional named argument `type` specifies an expected type, e.g. `` {lean (type := "Nat")}`.succ .zero` `` * `` {name}`X` `` - `X` is a constant in the Lean environment. The optional positional argument can be used to override name resolution; if it is provided, then the positional argument is used to resolve the name but the contents of the directive are rendered. diff --git a/Manual.lean b/Manual.lean index 8ce2c024..3b8ae542 100644 --- a/Manual.lean +++ b/Manual.lean @@ -111,7 +111,7 @@ draft := true {docstring Dynamic} -{docstring Dynamic.mk (allowMissing := true)} +{docstring Dynamic.mk +allowMissing} {docstring Dynamic.get?} diff --git a/Manual/Attributes.lean b/Manual/Attributes.lean index 1bcd1daf..d8edb135 100644 --- a/Manual/Attributes.lean +++ b/Manual/Attributes.lean @@ -59,7 +59,7 @@ Each attribute determines how to store its own metadata and what the appropriate Attributes can be added to declarations as a {ref "declaration-modifiers"}[declaration modifier]. They are placed between the documentation comment and the visibility modifiers. -:::syntax Lean.Parser.Term.attributes (open := false) (title := "Attributes") +:::syntax Lean.Parser.Term.attributes -open (title := "Attributes") ```grammar @[$_:attrInstance,*] ``` @@ -104,7 +104,7 @@ This determines whether the attribute's effect is visible only in the current se These scope indications are also used to control {ref "syntax-rules"}[syntax extensions] and {ref "instance-attribute"}[type class instances]. Each attribute is responsible for defining precisely what these terms mean for its particular effect. -:::syntax attrKind (open := false) (title := "Attribute Scopes") (alias := Lean.Parser.Term.attrKind) +:::syntax attrKind -open (title := "Attribute Scopes") (alias := Lean.Parser.Term.attrKind) Globally-scoped declarations (the default) are in effect whenever the {tech}[module] in which they're established is transitively imported. They are indicated by the absence of another scope modifier. ```grammar @@ -115,7 +115,7 @@ Locally-scoped declarations are in effect only for the extent of the {tech}[sect local ``` -Scoped declarations are in effect whenever the {tech key:="current namespace"}[namespace] in which they are established is opened. +Scoped declarations are in effect whenever the {tech (key := "current namespace")}[namespace] in which they are established is opened. ```grammar scoped ``` diff --git a/Manual/Axioms.lean b/Manual/Axioms.lean index 730f2742..a3727e40 100644 --- a/Manual/Axioms.lean +++ b/Manual/Axioms.lean @@ -19,13 +19,13 @@ htmlSplit := .never %%% :::leanSection -```lean (show := false) +```lean -show universe u ``` {deftech}_Axioms_ are postulated constants. While the axiom's type must itself be a type (that is, it must have type {lean}`Sort u`), there are no further requirements. -Axioms do not {tech key:="reduction"}[reduce] to other terms. +Axioms do not {tech (key := "reduction")}[reduce] to other terms. ::: Axioms can be used to experiment with the consequences of an idea before investing the time required to construct a model or prove a theorem. @@ -138,7 +138,7 @@ Definitions that contain non-proof code that relies on axioms must be marked {ke :::example "Axioms and Compilation" Adding an additional `0` to {lean}`Nat` with an axiom makes it so functions that use it can't be compiled. In particular, {name}`List.length'` returns the axiom {name}`Nat.otherZero` instead of {name}`Nat.zero` as the length of the empty list. -```lean (name := otherZero2) (error := true) +```lean (name := otherZero2) +error axiom Nat.otherZero : Nat def List.length' : List α → Nat @@ -224,9 +224,9 @@ However, they allow the use of compiled code in proofs to be carefully controlle ``` :::keepEnv -```lean (show := false) +```lean -show axiom Anything : Type ``` -Finally, the axiom {name}`sorryAx` is used as part of the implementation of the {tactic}`sorry` tactic and {lean type:="Anything"}`sorry` term. +Finally, the axiom {name}`sorryAx` is used as part of the implementation of the {tactic}`sorry` tactic and {lean (type := "Anything")}`sorry` term. Uses of this axiom are not intended to occur in finished proofs, and this can be confirmed using {keywordOf Lean.Parser.Command.printAxioms}`#print axioms`. ::: diff --git a/Manual/BasicProps.lean b/Manual/BasicProps.lean index 40d593f8..1ab21d99 100644 --- a/Manual/BasicProps.lean +++ b/Manual/BasicProps.lean @@ -99,7 +99,7 @@ However, it should not be confused with {name}`PProd`: using non-computable reas In a {ref "tactics"}[tactic] proof, conjunctions can be proved using {name}`And.intro` explicitly via {tactic}`apply`, but {tactic}`constructor` is more common. When multiple conjunctions are nested in a proof goal, {tactic}`and_intros` can be used to apply {name}`And.intro` in each relevant location. -Assumptions of conjunctions in the context can be simplified using {tactic}`cases`, pattern matching with {tactic}`let` or {tactic show:="match"}`Lean.Parser.Tactic.match`, or {tactic}`rcases`. +Assumptions of conjunctions in the context can be simplified using {tactic}`cases`, pattern matching with {tactic}`let` or {tactic (show := "match")}`Lean.Parser.Tactic.match`, or {tactic}`rcases`. {docstring And} @@ -113,7 +113,7 @@ Because {lean}`Sum` is a type, it is possible to check _which_ constructor was u In other words, because {lean}`Or` is not a {tech}[subsingleton], its proofs cannot be used as part of a computation. In a {ref "tactics"}[tactic] proof, disjunctions can be proved using either constructor ({name}`Or.inl` or {name}`Or.inr`) explicitly via {tactic}`apply`. -Assumptions of disjunctions in the context can be simplified using {tactic}`cases`, pattern matching with {tactic show:="match"}`Lean.Parser.Tactic.match`, or {tactic}`rcases`. +Assumptions of disjunctions in the context can be simplified using {tactic}`cases`, pattern matching with {tactic (show := "match")}`Lean.Parser.Tactic.match`, or {tactic}`rcases`. {docstring Or} @@ -125,14 +125,14 @@ This is because the decision procedure's result provides a suitable branch condi {docstring Or.by_cases'} -```lean (show := false) +```lean -show section variable {P : Prop} ``` Rather than encoding negation as an inductive type, {lean}`¬P` is defined to mean {lean}`P → False`. In other words, to prove a negation, it suffices to assume the negated statement and derive a contradiction. This also means that {lean}`False` can be derived immediately from a proof of a proposition and its negation, and then used to prove any proposition or inhabit any type. -```lean (show := false) +```lean -show end ``` @@ -146,7 +146,7 @@ end -```lean (show := false) +```lean -show section variable {A B : Prop} ``` @@ -171,7 +171,7 @@ theorem truth_functional_imp {A B : Prop} : ``` ::: -```lean (show := false) +```lean -show end ``` @@ -239,7 +239,7 @@ Unlike both {name}`Subtype` and {name}`Sigma`, it is a {tech}[proposition]; this When writing a proof, the {tactic}`exists` tactic allows one (or more) witness(es) to be specified for a (potentially nested) existential statement. The {tactic}`constructor` tactic, on the other hand, creates a {tech}[metavariable] for the witness; providing a proof of the predicate may solve the metavariable as well. -The components of an existential assumption can be made available individually by pattern matching with {tactic}`let` or {tactic show:="match"}`Lean.Parser.Tactic.match`, as well as by using {tactic}`cases` or {tactic}`rcases`. +The components of an existential assumption can be made available individually by pattern matching with {tactic}`let` or {tactic (show := "match")}`Lean.Parser.Tactic.match`, as well as by using {tactic}`cases` or {tactic}`rcases`. :::example "Proving Existential Statements" @@ -402,12 +402,12 @@ In these cases, the built-in automation has no choice but to use heterogeneous e $_ ≍ $_ ``` -```lean (show := false) +```lean -show section variable (x : α) (y : β) ``` Heterogeneous equality {lean}`HEq x y` can be written {lean}`x ≍ y`. -```lean (show := false) +```lean -show end ``` @@ -418,7 +418,7 @@ end :::::leanSection ::::example "Heterogeneous Equality" -```lean (show := false) +```lean -show variable {α : Type u} {n k l₁ l₂ l₃ : Nat} ``` @@ -429,7 +429,7 @@ variable {xs : Vector α l₁} {ys : Vector α l₂} {zs : Vector α l₃} set_option linter.unusedVariables false ``` -```lean (name := assocFail) (error := true) (keep := false) +```lean (name := assocFail) +error -keep theorem Vector.append_associative : xs ++ (ys ++ zs) = (xs ++ ys) ++ zs := by sorry ``` @@ -456,7 +456,7 @@ However, such proof statements can be difficult to work with in certain circumst :::paragraph Another is to use heterogeneous equality: -```lean (keep := false) +```lean -keep theorem Vector.append_associative : HEq (xs ++ (ys ++ zs)) ((xs ++ ys) ++ zs) := by sorry ``` @@ -464,7 +464,7 @@ theorem Vector.append_associative : In this case, {ref "the-simplifier"}[the simplifier] can rewrite both sides of the equation without having to preserve their types. However, proving the theorem does require eventually proving that the lengths nonetheless match. -```lean (keep := false) +```lean -keep theorem Vector.append_associative : HEq (xs ++ (ys ++ zs)) ((xs ++ ys) ++ zs) := by cases xs; cases ys; cases zs diff --git a/Manual/BasicTypes.lean b/Manual/BasicTypes.lean index 093b98cd..bf75867b 100644 --- a/Manual/BasicTypes.lean +++ b/Manual/BasicTypes.lean @@ -69,7 +69,7 @@ In functional programming, {lean}`Unit` is the return type of things that "retur Mathematically, this is represented by a single completely uninformative value, as opposed to an empty type such as {lean}`Empty`, which represents unreachable code. :::leanSection -```lean (show := false) +```lean -show variable {m : Type → Type} [Monad m] {α : Type} ``` @@ -85,7 +85,7 @@ There are two variants of the unit type: * {lean}`Unit` is a {lean}`Type` that exists in the smallest non-propositional {tech}[universe]. - * {lean}`PUnit` is {tech key:="universe polymorphism"}[universe polymorphic] and can be used in any non-propositional {tech}[universe]. + * {lean}`PUnit` is {tech (key := "universe polymorphism")}[universe polymorphic] and can be used in any non-propositional {tech}[universe]. Behind the scenes, {lean}`Unit` is actually defined as {lean}`PUnit.{1}`. {lean}`Unit` should be preferred over {name}`PUnit` when possible to avoid unnecessary universe parameters. @@ -101,7 +101,7 @@ If in doubt, use {lean}`Unit` until universe errors occur. {deftech}_Unit-like types_ are inductive types that have a single constructor which takes no non-proof parameters. {lean}`PUnit` is one such type. -All elements of unit-like types are {tech key:="definitional equality"}[definitionally equal] to all other elements. +All elements of unit-like types are {tech (key := "definitional equality")}[definitionally equal] to all other elements. :::example "Definitional Equality of {lean}`Unit`" Every term with type {lean}`Unit` is definitionally equal to every other term with type {lean}`Unit`: @@ -143,7 +143,7 @@ inductive NotUnitLike where | mk (u : Unit) ``` -```lean (error:=true) (name := NotUnitLike) +```lean +error (name := NotUnitLike) example (e1 e2 : NotUnitLike) : e1 = e2 := rfl ``` ```leanOutput NotUnitLike @@ -186,7 +186,7 @@ However, there is an important pragmatic difference: {lean}`Bool` classifies _va In other words, {lean}`Bool` is the notion of truth and falsehood that's appropriate for programs, while {lean}`Prop` is the notion that's appropriate for mathematics. Because proofs are erased from compiled programs, keeping {lean}`Bool` and {lean}`Prop` distinct makes it clear which parts of a Lean file are intended for computation. -```lean (show := false) +```lean -show section BoolProp axiom b : Bool @@ -211,7 +211,7 @@ These propositions are called {tech}_decidable_ propositions, and have instances The function {name}`Decidable.decide` converts a proof-carrying {lean}`Decidable` result into a {lean}`Bool`. This function is also a coercion from decidable propositions to {lean}`Bool`, so {lean}`(2 = 2 : Bool)` evaluates to {lean}`true`. -```lean (show := false) +```lean -show /-- info: true -/ #check_msgs in #eval (2 = 2 : Bool) @@ -246,7 +246,7 @@ The prefix operator `!` is notation for {lean}`Bool.not`. ### Logical Operations -```lean (show := false) +```lean -show section ShortCircuit axiom BIG_EXPENSIVE_COMPUTATION : Bool @@ -256,7 +256,7 @@ The functions {name}`cond`, {name Bool.and}`and`, and {name Bool.or}`or` are sho In other words, {lean}`false && BIG_EXPENSIVE_COMPUTATION` does not need to execute {lean}`BIG_EXPENSIVE_COMPUTATION` before returning `false`. These functions are defined using the {attr}`macro_inline` attribute, which causes the compiler to replace calls to them with their definitions while generating code, and the definitions use nested pattern matching to achieve the short-circuiting behavior. -```lean (show := false) +```lean -show end ShortCircuit ``` diff --git a/Manual/BasicTypes/Array/FFI.lean b/Manual/BasicTypes/Array/FFI.lean index 9eb39f88..50c4fc23 100644 --- a/Manual/BasicTypes/Array/FFI.lean +++ b/Manual/BasicTypes/Array/FFI.lean @@ -20,7 +20,7 @@ set_option pp.rawOnError true tag := "array-ffi" %%% -:::ffi "lean_string_object" kind := type +:::ffi "lean_string_object" (kind := type) ``` typedef struct { lean_object m_header; diff --git a/Manual/BasicTypes/BitVec.lean b/Manual/BasicTypes/BitVec.lean index be0ff55b..3aae9b17 100644 --- a/Manual/BasicTypes/BitVec.lean +++ b/Manual/BasicTypes/BitVec.lean @@ -40,7 +40,7 @@ Because {name}`BitVec` is a {ref "inductive-types-trivial-wrappers"}[trivial wra # Syntax :::leanSection -```lean (show := false) +```lean -show variable {w n : Nat} ``` There is an {inst}`OfNat (BitVec w) n` instance for all widths {lean}`w` and natural numbers {lean}`n`. @@ -55,7 +55,7 @@ example : BitVec 8 := 0xff example : BitVec 8 := 255 example : BitVec 8 := 0b1111_1111 ``` -```lean (show := false) +```lean -show -- Inline test example : (0xff : BitVec 8) = 255 := by rfl example : (0b1111_1111 : BitVec 8) = 255 := by rfl @@ -147,7 +147,7 @@ example : BitVec 8 := 1#'(by decide) ``` Literals that are not in bounds are not allowed: -```lean (error := true) (name := oob) +```lean +error (name := oob) example : BitVec 8 := 256#'(by decide) ``` ```leanOutput oob diff --git a/Manual/BasicTypes/Fin.lean b/Manual/BasicTypes/Fin.lean index 469c9b87..2fa8e9b1 100644 --- a/Manual/BasicTypes/Fin.lean +++ b/Manual/BasicTypes/Fin.lean @@ -18,7 +18,7 @@ open Verso.Genre.Manual.InlineLean tag := "Fin" %%% -```lean (show := false) +```lean -show section variable (n : Nat) ``` @@ -92,7 +92,7 @@ When the literal is greater than or equal to {lean}`n`, the remainder when divid ``` If Lean can't synthesize an instance of {lean}`NeZero n`, then there is no {lean}`OfNat (Fin n)` instance: -```lean (error := true) (name := fin0) +```lean +error (name := fin0) example : Fin 0 := 0 ``` ```leanOutput fin0 @@ -105,7 +105,7 @@ due to the absence of the instance above Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command. ``` -```lean (error := true) (name := finK) +```lean +error (name := finK) example (k : Nat) : Fin k := 0 ``` ```leanOutput finK diff --git a/Manual/BasicTypes/Float.lean b/Manual/BasicTypes/Float.lean index c612e864..d3d94dca 100644 --- a/Manual/BasicTypes/Float.lean +++ b/Manual/BasicTypes/Float.lean @@ -38,19 +38,19 @@ Lean provides two floating-point types: {name}`Float` represents 64-bit floating The precision of {name}`Float` does not vary based on the platform that Lean is running on. -{docstring Float (label := "type") (hideStructureConstructor := true) (hideFields := true)} +{docstring Float (label := "type") +hideStructureConstructor +hideFields} -{docstring Float32 (label := "type") (hideStructureConstructor := true) (hideFields := true)} +{docstring Float32 (label := "type") +hideStructureConstructor +hideFields} :::example "No Kernel Reasoning About Floating-Point Numbers" -The Lean kernel can compare expressions of type {lean}`Float` for syntactic equality, so {lean type:="Float"}`0.0` is definitionally equal to itself. +The Lean kernel can compare expressions of type {lean}`Float` for syntactic equality, so {lean (type := "Float")}`0.0` is definitionally equal to itself. ```lean example : (0.0 : Float) = (0.0 : Float) := by rfl ``` Terms that require reduction to become syntactically equal cannot be checked by the kernel: -```lean (error := true) (name := zeroPlusZero) +```lean +error (name := zeroPlusZero) example : (0.0 : Float) = (0.0 + 0.0 : Float) := by rfl ``` ```leanOutput zeroPlusZero @@ -63,7 +63,7 @@ is not definitionally equal to the right-hand side ``` Similarly, the kernel cannot evaluate {lean}`Bool`-valued comparisons of floating-point numbers while checking definitional equality: -```lean (error := true) (name := zeroPlusZero') (keep := false) +```lean +error (name := zeroPlusZero') -keep theorem Float.zero_eq_zero_plus_zero : ((0.0 : Float) == (0.0 + 0.0 : Float)) = true := by rfl @@ -141,7 +141,7 @@ is syntactic sugar for (OfScientific.ofScientific 41352 true 2 : Float32) ``` -```lean (show := false) +```lean -show example : (-2.2523 : Float) = (Neg.neg (OfScientific.ofScientific 22523 true 4) : Float) := by simp [OfScientific.ofScientific] example : (413.52 : Float32) = (OfScientific.ofScientific 41352 true 2 : Float32) := by simp [OfScientific.ofScientific] ``` diff --git a/Manual/BasicTypes/Int.lean b/Manual/BasicTypes/Int.lean index ef7141dc..11c4345f 100644 --- a/Manual/BasicTypes/Int.lean +++ b/Manual/BasicTypes/Int.lean @@ -54,7 +54,7 @@ If an integer is too large to fit in the remaining bits, it is instead allocated tag := "int-syntax" %%% -```lean (show := false) +```lean -show section variable (n : Nat) ``` @@ -63,7 +63,7 @@ The {lean}`OfNat Int` instance allows numerals to be used as literals, both in e {lean}`(OfNat.ofNat n : Int)` reduces to the constructor application {lean}`Int.ofNat n`. The {inst}`Neg Int` instance allows negation to be used as well. -```lean (show := false) +```lean -show open Int ``` @@ -79,7 +79,7 @@ The notation {lean}`-[ n +1]` is suggestive of $`-(n + 1)`, which is the meaning ``` ::: -```lean (show := false) +```lean -show end ``` @@ -143,7 +143,7 @@ This is not, however, the only sensible convention for rounding and remainders i Four pairs of division and modulus functions are available, implementing various conventions. :::example "Division by 0" -In all integer division conventions, division by {lean type:="Int"}`0` is defined to be {lean type:="Int"}`0`: +In all integer division conventions, division by {lean (type := "Int")}`0` is defined to be {lean (type := "Int")}`0`: ```lean (name := div0) #eval Int.ediv 5 0 @@ -193,7 +193,7 @@ Bitwise operators on {name}`Int` can be understood as bitwise operators on an in Equality and inequality tests on {lean}`Int` are typically performed using the decidability of its equality and ordering relations or using the {inst}`BEq Int` and {inst}`Ord Int` instances. -```lean (show := false) +```lean -show example (i j : Int) : Decidable (i ≤ j) := inferInstance example (i j : Int) : Decidable (i < j) := inferInstance example (i j : Int) : Decidable (i = j) := inferInstance diff --git a/Manual/BasicTypes/List.lean b/Manual/BasicTypes/List.lean index 9cc093a5..cbd6c387 100644 --- a/Manual/BasicTypes/List.lean +++ b/Manual/BasicTypes/List.lean @@ -99,7 +99,7 @@ def split'' : List α → List α × List α let (ys, zs) := split xs (.cons x ys, .cons x' zs) ``` -```lean (show := false) +```lean -show -- Test claim example : @split = @split' := by funext α xs diff --git a/Manual/BasicTypes/Maps.lean b/Manual/BasicTypes/Maps.lean index 08de6a80..aeaea82c 100644 --- a/Manual/BasicTypes/Maps.lean +++ b/Manual/BasicTypes/Maps.lean @@ -56,13 +56,13 @@ In Lean, maps may have the following properties: : Extensionality Maps can be viewed as partial functions from keys to values. - {deftech}_Extensional maps_{index subterm:="extensional"}[map] are maps for which propositional equality matches this interpretation. + {deftech}_Extensional maps_{index (subterm := "extensional")}[map] are maps for which propositional equality matches this interpretation. This can be convenient for reasoning, but it also rules out some useful operations that would be able to distinguish between them. In general, extensional maps should be used only when needed for verification. : Dependent or Not - A {deftech}_dependent map_{index subterm:="dependent"}[map] is one in which the type of each value is determined by its corresponding key, rather than being constant. + A {deftech}_dependent map_{index (subterm := "dependent")}[map] is one in which the type of each value is determined by its corresponding key, rather than being constant. Dependent maps have more expressive power, but are also more difficult to use. They impose more requirements on their users. For example, many operations on {name Std.DHashMap}`DHashMap` require {name}`LawfulBEq` instances rather than {name}`BEq`. @@ -71,12 +71,12 @@ In Lean, maps may have the following properties: ::::: leanSection -```lean (show := false) +```lean -show open Std ``` -:::table (header := true) +:::table +header * - Map - Representation @@ -186,7 +186,7 @@ The map of an adventure game may consist of a series of rooms, connected by pass Each room has a description, and each passage faces in a particular direction. This can be represented as a recursive structure. -```lean (error:=true) (name:=badNesting) (keep := false) +```lean +error (name:=badNesting) -keep structure Maze where description : String passages : HashMap String Maze @@ -355,7 +355,7 @@ tag := "HashMap" The declarations in this section should be imported using `import Std.HashMap`. -{docstring Std.HashMap (hideFields:=true) (hideStructureConstructor := true)} +{docstring Std.HashMap +hideFields +hideStructureConstructor} ## Creation @@ -479,7 +479,7 @@ tag := "DHashMap" The declarations in this section should be imported using `import Std.DHashMap`. -{docstring Std.DHashMap (hideFields:=true) (hideStructureConstructor := true)} +{docstring Std.DHashMap +hideFields +hideStructureConstructor} ## Creation @@ -597,7 +597,7 @@ tag := "ExtHashMap" The declarations in this section should be imported using `import Std.ExtHashMap`. -{docstring Std.ExtHashMap (hideFields:=true) (hideStructureConstructor := true)} +{docstring Std.ExtHashMap +hideFields +hideStructureConstructor} ## Creation @@ -674,7 +674,7 @@ tag := "ExtDHashMap" The declarations in this section should be imported using `import Std.ExtDHashMap`. -{docstring Std.ExtDHashMap (hideFields:=true) (hideStructureConstructor := true)} +{docstring Std.ExtDHashMap +hideFields +hideStructureConstructor} ## Creation @@ -895,7 +895,7 @@ tag := "DTreeMap" The declarations in this section should be imported using `import Std.DTreeMap`. -{docstring Std.DTreeMap (hideFields:=true) (hideStructureConstructor := true)} +{docstring Std.DTreeMap +hideFields +hideStructureConstructor} ## Creation diff --git a/Manual/BasicTypes/Maps/TreeMap.lean b/Manual/BasicTypes/Maps/TreeMap.lean index 18b2689d..e67af232 100644 --- a/Manual/BasicTypes/Maps/TreeMap.lean +++ b/Manual/BasicTypes/Maps/TreeMap.lean @@ -26,7 +26,7 @@ tag := "TreeMap" The declarations in this section should be imported using `import Std.TreeMap`. -{docstring Std.TreeMap (hideFields:=true) (hideStructureConstructor := true)} +{docstring Std.TreeMap +hideFields +hideStructureConstructor} # Creation diff --git a/Manual/BasicTypes/Maps/TreeSet.lean b/Manual/BasicTypes/Maps/TreeSet.lean index 83ceab1c..7e70c018 100644 --- a/Manual/BasicTypes/Maps/TreeSet.lean +++ b/Manual/BasicTypes/Maps/TreeSet.lean @@ -22,7 +22,7 @@ set_option pp.rawOnError true tag := "TreeSet" %%% -{docstring Std.TreeSet (hideStructureConstructor := true) (hideFields := true)} +{docstring Std.TreeSet +hideStructureConstructor +hideFields} # Creation diff --git a/Manual/BasicTypes/Nat.lean b/Manual/BasicTypes/Nat.lean index 60126ecc..218079df 100644 --- a/Manual/BasicTypes/Nat.lean +++ b/Manual/BasicTypes/Nat.lean @@ -33,7 +33,7 @@ tag := "nat-model" {docstring Nat} ::::leanSection -```lean (show := false) +```lean -show variable (i : Nat) ``` :::example "Proofs by Induction" diff --git a/Manual/BasicTypes/Option.lean b/Manual/BasicTypes/Option.lean index 4b0fb42b..1fa8e4da 100644 --- a/Manual/BasicTypes/Option.lean +++ b/Manual/BasicTypes/Option.lean @@ -21,13 +21,13 @@ tag := "option" :::::leanSection -```lean (show := false) +```lean -show variable {α : Type u} (v : α) {β : Type v} ``` -{lean}`Option α` is the type of values which are either {lean}`some v` for some {lean}`v`` : `{lean}`α`, or {lean type:="Option α"}`none`. -In functional programming, this type is used similarly to nullable types: {lean type:="Option α"}`none` represents the absence of a value. -Additionally, partial functions from {lean}`α` to {lean}`β` can be represented by the type {lean}`α → Option β`, where {lean type:="Option β"}`none` results when the function is undefined for some input. +{lean}`Option α` is the type of values which are either {lean}`some v` for some {lean}`v`` : `{lean}`α`, or {lean (type := "Option α")}`none`. +In functional programming, this type is used similarly to nullable types: {lean (type := "Option α")}`none` represents the absence of a value. +Additionally, partial functions from {lean}`α` to {lean}`β` can be represented by the type {lean}`α → Option β`, where {lean (type := "Option β")}`none` results when the function is undefined for some input. Computationally, these partial functions represent the possibility of failure or errors, and they correspond to a program that can terminate early but not throw an informative exception. {lean}`Option` can also be thought of as being similar to a list that contains at most one element. @@ -38,7 +38,7 @@ The {lean}`Option` API makes frequent use of this perspective. :::example "Options as Nullability" -```lean (show := false) +```lean -show open Std (HashMap) variable {Coll} [BEq α] [Hashable α] (a : α) (b : β) {xs : Coll} [GetElem Coll α β fun _ _ => True] {i : α} {m : HashMap α β} ``` @@ -51,7 +51,7 @@ Std.HashMap.get?.{u, v} {α : Type u} {β : Type v} (m : HashMap α β) (a : α) : Option β ``` -Because there is no way to know in advance whether the key is actually in the map, the return type is {lean}`Option β`, where {lean type:="Option β"}`none` means the key was not in the map, and {lean}`some b` means that the key was found and `b` is the value retrieved. +Because there is no way to know in advance whether the key is actually in the map, the return type is {lean}`Option β`, where {lean (type := "Option β")}`none` means the key was not in the map, and {lean}`some b` means that the key was found and `b` is the value retrieved. The {lean}`xs[i]` syntax, which is used to index into collections when there is an available proof that {lean}`i` is a valid index into {lean}`xs`, has a variant {lean}`xs[i]?` that returns an optional value depending on whether the given index is valid. If {lean}`m`` : `{lean}`HashMap α β` and {lean}`a`` : `{lean}`α`, then {lean}`m[a]?` is equivalent to {lean}`HashMap.get? m a`. @@ -61,7 +61,7 @@ If {lean}`m`` : `{lean}`HashMap α β` and {lean}`a`` : `{lean}`α`, :::example "Options as Safe Nullability" In many programming languages, it is important to remember to check for the null value. -When using {name}`Option`, the type system requires these checks in the right places: {lean}`Option α` and {lean}`α` are not the same type, and converting from one to the other requires handling the case of {lean type:="Option α"}`none`. +When using {name}`Option`, the type system requires these checks in the right places: {lean}`Option α` and {lean}`α` are not the same type, and converting from one to the other requires handling the case of {lean (type := "Option α")}`none`. This can be done via helpers such as {name}`Option.getD`, or with pattern matching. ```lean @@ -69,14 +69,14 @@ def postalCodes : Std.HashMap Nat String := .empty |>.insert 12345 "Schenectady" ``` -```lean name:=getD +```lean (name := getD) #eval postalCodes[12346]?.getD "not found" ``` ```leanOutput getD "not found" ``` -```lean name := m +```lean (name := m) #eval match postalCodes[12346]? with | none => "not found" @@ -106,7 +106,7 @@ def postalCodes : Std.HashMap Nat String := # Coercions -```lean (show := false) +```lean -show section variable {α : Type u} (line : String) ``` @@ -132,7 +132,7 @@ The {name}`some` is automatically inserted by the coercion. ::: -```lean (show := false) +```lean -show end ``` @@ -167,7 +167,7 @@ end {docstring Option.isEqSome} :::leanSection -```lean (show := false) +```lean -show variable {α} [DecidableEq α] [LT α] [Min α] [Max α] ``` Ordering of optional values typically uses the {inst}`DecidableEq (Option α)`, {inst}`LT (Option α)`, {inst}`Min (Option α)`, and {inst}`Max (Option α)` instances. diff --git a/Manual/BasicTypes/Products.lean b/Manual/BasicTypes/Products.lean index 93faffda..50a3f1b3 100644 --- a/Manual/BasicTypes/Products.lean +++ b/Manual/BasicTypes/Products.lean @@ -29,37 +29,37 @@ In practice, they differ in four ways: * whether the type as a whole is a proposition or type ::: -:::table (header := true) +:::table +header * + Type + First Projection + Second Projection + Dependent? + Universe * + {name}`Prod` - + {lean universes:="u"}`Type u` - + {lean universes:="v"}`Type v` + + {lean (universes := "u")}`Type u` + + {lean (universes := "v")}`Type v` + ❌️ - + {lean universes:="u v"}`Type (max u v)` + + {lean (universes := "u v")}`Type (max u v)` * + {name}`And` - + {lean universes:="u v"}`Prop` - + {lean universes:="u v"}`Prop` + + {lean (universes := "u v")}`Prop` + + {lean (universes := "u v")}`Prop` + ❌️ - + {lean universes:="u v"}`Prop` + + {lean (universes := "u v")}`Prop` * + {name}`Sigma` - + {lean universes:="u"}`Type u` - + {lean universes:="v"}`Type v` + + {lean (universes := "u")}`Type u` + + {lean (universes := "v")}`Type v` + ✔ - + {lean universes:="u v"}`Type (max u v)` + + {lean (universes := "u v")}`Type (max u v)` * + {name}`Subtype` - + {lean universes:="u"}`Type u` - + {lean universes:="v"}`Prop` + + {lean (universes := "u")}`Type u` + + {lean (universes := "v")}`Prop` + ✔ - + {lean universes:="u v"}`Type u` + + {lean (universes := "u v")}`Type u` * + {name}`Exists` - + {lean universes:="u"}`Type u` - + {lean universes:="v"}`Prop` + + {lean (universes := "u")}`Type u` + + {lean (universes := "v")}`Prop` + ✔ - + {lean universes:="u v"}`Prop` + + {lean (universes := "u v")}`Prop` ::: :::paragraph @@ -83,7 +83,7 @@ This chapter documents the tuple-like pairs, namely {name}`Prod` and {name}`Sigm tag := "pairs" %%% -```lean (show:=false) +```lean -show section variable {α : Type u} {β : Type v} {γ : Type w} {x : α} {y : β} {z : γ} ``` @@ -92,14 +92,14 @@ The type {lean}`α × β`, which is a {tech}[notation] for {lean}`Prod α β`, c These pairs are written in parentheses, separated by commas. Larger tuples are represented as nested tuples, so {lean}`α × β × γ` is equivalent to {lean}`α × (β × γ)` and {lean}`(x, y, z)` is equivalent to {lean}`(x, (y, z))`. -:::syntax term title:="Product Types" +:::syntax term (title := "Product Types") ```grammar $_ × $_ ``` The product {lean}`Prod α β` is written {lean}`α × β`. ::: -:::syntax term title:="Pairs" +:::syntax term (title := "Pairs") ```grammar ($_, $_) ``` @@ -107,7 +107,7 @@ The product {lean}`Prod α β` is written {lean}`α × β`. {docstring Prod} -```lean (show:=false) +```lean -show section variable {α : Sort u} {β : Sort v} {γ : Type w} ``` @@ -116,11 +116,11 @@ There are also the variants {lean}`α ×' β` (which is notation for {lean}`PPro Generally speaking, {name}`PProd` is primarily used in the implementation of proof automation and the elaborator, as it tends to give rise to universe level unification problems that can't be solved. {lean}`MProd`, on the other hand, can simplify universe level issues in certain advanced use cases. -```lean (show:=false) +```lean -show end ``` -:::syntax term title:="Products of Arbitrary Sorts" +:::syntax term (title := "Products of Arbitrary Sorts") ```grammar $_ ×' $_ ``` @@ -232,7 +232,7 @@ The two styles of annotation cannot be mixed in a single {keywordOf «termΣ_,_ ``` :::: -```lean (show := false) +```lean -show section variable {α : Type} (x : α) ``` @@ -252,12 +252,12 @@ Dependent pairs are typically used in one of two ways: Σ (b : Bool), if b then Unit else α ``` - is equivalent to {lean}`Option α`, where {lean type:="Option α"}`none` is {lean type:="Σ (b : Bool), if b then Unit else α"}`⟨true, ()⟩` and {lean type:="Option α"}`some x` is {lean type:="Σ (b : Bool), if b then Unit else α"}`⟨false, x⟩`. + is equivalent to {lean}`Option α`, where {lean (type := "Option α")}`none` is {lean (type := "Σ (b : Bool), if b then Unit else α")}`⟨true, ()⟩` and {lean (type := "Option α")}`some x` is {lean (type := "Σ (b : Bool), if b then Unit else α")}`⟨false, x⟩`. Using dependent pairs this way is uncommon, because it's typically much easier to define a special-purpose {tech}[inductive type] directly. ::: :::: -```lean (show := false) +```lean -show end ``` diff --git a/Manual/BasicTypes/String/FFI.lean b/Manual/BasicTypes/String/FFI.lean index 54e99dc7..6a731441 100644 --- a/Manual/BasicTypes/String/FFI.lean +++ b/Manual/BasicTypes/String/FFI.lean @@ -21,7 +21,7 @@ tag := "string-ffi" %%% -:::ffi "lean_string_object" kind := type +:::ffi "lean_string_object" (kind := type) ``` typedef struct { lean_object m_header; diff --git a/Manual/BasicTypes/String/Literals.lean b/Manual/BasicTypes/String/Literals.lean index 92780307..08c49da4 100644 --- a/Manual/BasicTypes/String/Literals.lean +++ b/Manual/BasicTypes/String/Literals.lean @@ -27,7 +27,7 @@ Lean has three kinds of string literals: ordinary string literals, interpolated tag := "string-literals" %%% -String literals begin and end with a double-quote character `"`. {index subterm:="string"}[literal] +String literals begin and end with a double-quote character `"`. {index (subterm := "string")}[literal] Between these characters, they may contain any other character, including newlines, which are included literally (with the caveat that all newlines in a Lean source file are interpreted as `'\n'`, regardless of file encoding and platform). Special characters that cannot otherwise be written in string literals may be escaped with a backslash, so `"\"Quotes\""` is a string literal that begins and ends with double quotes. The following forms of escape sequences are accepted: @@ -94,7 +94,7 @@ Preceding a literal with `m!` causes the interpolation to result in an instance tag := "raw-string-literals" %%% -In {deftech}[raw string literals], {index subterm:="raw string"}[literal] there are no escape sequences or gaps, and each character denotes itself exactly. +In {deftech}[raw string literals], {index (subterm := "raw string")}[literal] there are no escape sequences or gaps, and each character denotes itself exactly. Raw string literals are preceded by `r`, followed by zero or more hash characters (`#`) and a double quote `"`. The string literal is completed at a double quote that is followed by _the same number_ of hash characters. For example, they can be used to avoid the need to double-escape certain characters: diff --git a/Manual/BasicTypes/String/Substrings.lean b/Manual/BasicTypes/String/Substrings.lean index af0d0fe1..cd8b1a18 100644 --- a/Manual/BasicTypes/String/Substrings.lean +++ b/Manual/BasicTypes/String/Substrings.lean @@ -118,7 +118,7 @@ tag := "string-api-substring" {docstring Substring.isNat} -{docstring Substring.toNat? (allowMissing := true)} +{docstring Substring.toNat? +allowMissing} {docstring Substring.toIterator} diff --git a/Manual/BasicTypes/Subtype.lean b/Manual/BasicTypes/Subtype.lean index 604f137e..3a153a83 100644 --- a/Manual/BasicTypes/Subtype.lean +++ b/Manual/BasicTypes/Subtype.lean @@ -38,7 +38,7 @@ They are thus represented identically to the base type in compiled code. {docstring Subtype} ::::leanSection -```lean (show := false) +```lean -show variable {α : Type u} {p : Prop} ``` :::syntax term (title := "Subtypes") @@ -58,7 +58,7 @@ The type ascription may be omitted: ::: :::: -Due to {tech}[proof irrelevance] and {tech key:="η-equivalence"}[η-equality], two elements of a subtype are definitionally equal when the elements of the base type are definitionally equal. +Due to {tech}[proof irrelevance] and {tech (key := "η-equivalence")}[η-equality], two elements of a subtype are definitionally equal when the elements of the base type are definitionally equal. In a proof, the {tactic}`ext` tactic can be used to transform a goal of equality of elements of a subtype into equality of their values. :::example "Definitional Equality of Subtypes" @@ -112,7 +112,7 @@ This allows subtypes to be used in positions where the base type is expected, es :::example "Subtype Coercions" Elements of subtypes can be coerced to their base type. -Here, {name}`nine` is coerced from a subtype of `Nat` that contains multiples of {lean type:="Nat"}`3` to {lean}`Nat`. +Here, {name}`nine` is coerced from a subtype of `Nat` that contains multiples of {lean (type := "Nat")}`3` to {lean}`Nat`. ```lean (name := subtype_coe) abbrev DivBy3 := { x : Nat // x % 3 = 0 } diff --git a/Manual/BasicTypes/Sum.lean b/Manual/BasicTypes/Sum.lean index 99a655d3..5b20c2d6 100644 --- a/Manual/BasicTypes/Sum.lean +++ b/Manual/BasicTypes/Sum.lean @@ -24,14 +24,14 @@ Sums are also known as disjoint unions, discriminated unions, or tagged unions. The constructors of a sum are also called {deftech}_injections_; mathematically, they can be considered as injective functions from each summand to the sum. ::::leanSection -```lean (show := false) +```lean -show universe u v ``` :::paragraph There are two varieties of the sum type: - * {lean}`Sum` is {tech key:="universe polymorphism"}[polymorphic] over all {lean}`Type` {tech}[universes], and is never a {tech}[proposition]. + * {lean}`Sum` is {tech (key := "universe polymorphism")}[polymorphic] over all {lean}`Type` {tech}[universes], and is never a {tech}[proposition]. * {lean}`PSum` is allows the summands to be propositions or types. Unlike {name}`Or`, the {name}`PSum` of two propositions is still a type, and non-propositional code can check which injection was used to construct a given value. @@ -56,12 +56,12 @@ tag := "sum-syntax" The names {name}`Sum` and {name}`PSum` are rarely written explicitly. Most code uses the corresponding infix operators. -```lean (show := false) +```lean -show section variable {α : Type u} {β : Type v} ``` -:::syntax term title:="Sum Types" +:::syntax term (title := "Sum Types") ```grammar $_ ⊕ $_ ``` @@ -70,16 +70,16 @@ $_ ⊕ $_ ::: -```lean (show := false) +```lean -show end ``` -```lean (show := false) +```lean -show section variable {α : Sort u} {β : Sort v} ``` -:::syntax term title:="Potentially-Propositional Sum Types" +:::syntax term (title := "Potentially-Propositional Sum Types") ```grammar $_ ⊕' $_ ``` @@ -88,7 +88,7 @@ $_ ⊕' $_ ::: -```lean (show := false) +```lean -show end ``` @@ -128,7 +128,7 @@ As such, their primary API is the constructors {name Sum.inl}`inl` and {name Sum The {name}`Inhabited` definitions for {name}`Sum` and {name}`PSum` are not registered as instances. This is because there are two separate ways to construct a default value (via {name Sum.inl}`inl` or {name Sum.inr}`inr`), and instance synthesis might result in either choice. -The result could be situations where two identically-written terms elaborate differently and are not {tech key:="definitional equality"}[definitionally equal]. +The result could be situations where two identically-written terms elaborate differently and are not {tech (key := "definitional equality")}[definitionally equal]. Both types have {name}`Nonempty` instances, for which {tech}[proof irrelevance] makes the choice of {name Sum.inl}`inl` or {name Sum.inr}`inr` not matter. This is enough to enable {keyword}`partial` functions. @@ -145,7 +145,7 @@ example : Nat × String := panic! "Cant' find it" ``` Sums do not, by default: -```lean (error := true) (name := panic) +```lean +error (name := panic) example : Nat ⊕ String := panic! "Cant' find it" ``` ```leanOutput panic diff --git a/Manual/BasicTypes/Thunk.lean b/Manual/BasicTypes/Thunk.lean index c7d20d2b..a221404a 100644 --- a/Manual/BasicTypes/Thunk.lean +++ b/Manual/BasicTypes/Thunk.lean @@ -19,7 +19,7 @@ tag := "Thunk" %%% A {deftech}_thunk_ delays the computation of a value. -In particular, the {name}`Thunk` type is used to delay the computation of a value in compiled code until it is explicitly requested—this request is called {deftech key:="force"}_forcing_ the thunk. +In particular, the {name}`Thunk` type is used to delay the computation of a value in compiled code until it is explicitly requested—this request is called {deftech (key := "force")}_forcing_ the thunk. The computed value is saved, so subsequent requests do not result in recomputation. Computing values at most once, when explicitly requested, is called {deftech}_lazy evaluation_.{index}[call-by-need] This caching is invisible to Lean's logic, in which {name}`Thunk` is equivalent to a function from {name}`Unit`. @@ -58,7 +58,7 @@ The runtime system maintains the invariant that either the closure or the saved If both are null pointers, then the thunk is being forced on another thread. ::: -When a thunk is {tech key:="force"}[forced], the runtime system first checks whether the saved value has already been computed, returning it if so. +When a thunk is {tech (key := "force")}[forced], the runtime system first checks whether the saved value has already been computed, returning it if so. Otherwise, it attempts to acquire a lock on the closure by atomically swapping it with a null pointer. If the lock is acquired, it is invoked to compute the value; the computed value is stored in the saved value field and the reference to the closure is dropped. If not, then another thread is already computing the value; the system waits until it is computed. @@ -69,7 +69,7 @@ tag := "Thunk-coercions" %%% :::leanSection -```lean (show := false) +```lean -show variable {α : Type u} {e : α} ``` There is a coercion from any type {lean}`α` to {lean}`Thunk α` that converts a term {lean}`e` into {lean}`Thunk.mk fun () => e`. diff --git a/Manual/BasicTypes/UInt.lean b/Manual/BasicTypes/UInt.lean index 70b6db73..2b51801f 100644 --- a/Manual/BasicTypes/UInt.lean +++ b/Manual/BasicTypes/UInt.lean @@ -98,7 +98,7 @@ def Permissions.decode (i : UInt8) : Permissions := ⟨i &&& 0x01 ≠ 0, i &&& 0x02 ≠ 0, i &&& 0x04 ≠ 0⟩ ``` -```lean (show := false) +```lean -show -- Check the above theorem Permissions.decode_encode (p : Permissions) : p = .decode (p.encode) := by let ⟨r, w, x⟩ := p @@ -491,7 +491,7 @@ This predicate is part of the {name}`UInt32` API. Typically, bitwise operations on fixed-width integers should be accessed using Lean's overloaded operators, particularly their instances of {name}`ShiftLeft`, {name}`ShiftRight`, {name}`AndOp`, {name}`OrOp`, and {name}`Xor`. -```lean (show := false) +```lean -show -- Check that all those instances really exist open Lean Elab Command in #eval show CommandElabM Unit from do diff --git a/Manual/BasicTypes/UInt/Arith.lean b/Manual/BasicTypes/UInt/Arith.lean index 3c2668b6..d016efe5 100644 --- a/Manual/BasicTypes/UInt/Arith.lean +++ b/Manual/BasicTypes/UInt/Arith.lean @@ -20,7 +20,7 @@ tag := "fixed-int-arithmetic" Typically, arithmetic operations on fixed-width integers should be accessed using Lean's overloaded arithmetic notation, particularly their instances of {name}`Add`, {name}`Sub`, {name}`Mul`, {name}`Div`, and {name}`Mod`, as well as {name}`Neg` for signed types. -```lean (show := false) +```lean -show -- Check that all those instances really exist open Lean Elab Command in #eval show CommandElabM Unit from do diff --git a/Manual/BasicTypes/UInt/Comparisons.lean b/Manual/BasicTypes/UInt/Comparisons.lean index 72dabc0b..5553d6ac 100644 --- a/Manual/BasicTypes/UInt/Comparisons.lean +++ b/Manual/BasicTypes/UInt/Comparisons.lean @@ -24,7 +24,7 @@ tag := "fixed-int-comparisons" The operators in this section are rarely invoked by name. Typically, comparisons operations on fixed-width integers should use the decidability of the corresponding relations, which consist of the equality type {name}`Eq` and those implemented in instances of {name}`LE` and {name}`LT`. -```lean (show := false) +```lean -show -- Check that all those instances really exist open Lean Elab Command in #eval show CommandElabM Unit from do @@ -34,7 +34,7 @@ open Lean Elab Command in elabCommand <| ← `(example : LT $(mkIdent t) := inferInstance) ``` -```lean (show := false) +```lean -show -- Check that all those instances really exist open Lean Elab Command in #eval show CommandElabM Unit from do diff --git a/Manual/BuildTools/Elan.lean b/Manual/BuildTools/Elan.lean index 45b50294..e8e4453f 100644 --- a/Manual/BuildTools/Elan.lean +++ b/Manual/BuildTools/Elan.lean @@ -108,7 +108,7 @@ tag := "elan-dir" %%% By default, Elan stores installed toolchains in `.elan/toolchains` in the user's home directory, and its proxies are kept in `.elan/bin`, which is added to the path when Elan is installed. -The environment variable {envVar def:=true}`ELAN_HOME` can be used to change this location. +The environment variable {envVar +def}`ELAN_HOME` can be used to change this location. It should be set both prior to installing Elan and in all sessions that use Lean in order to ensure that Elan's files are found. # Command-Line Interface diff --git a/Manual/BuildTools/Lake.lean b/Manual/BuildTools/Lake.lean index 16346436..0fe12c42 100644 --- a/Manual/BuildTools/Lake.lean +++ b/Manual/BuildTools/Lake.lean @@ -135,7 +135,7 @@ Producing a desired {tech}[artifact], such as a {tech}[`.olean` file] or an exec Builds are triggered by the {lake}`build` command or by other commands that require an artifact to be present, such as {lake}`exe`. A build consists of the following steps: -: {deftech key:="configure package"}[Configuring] the package +: {deftech (key := "configure package")}[Configuring] the package If {tech}[package configuration] file is newer than the cached configuration file `lakefile.olean`, then the package configuration is re-elaborated. This also occurs when the cached file is missing or when the {lakeOpt}`--reconfigure` or {lakeOpt}`-R` flag is provided. @@ -250,7 +250,7 @@ Package dependencies are not updated during a build. The facets available for packages are: -```lean (show := false) +```lean -show -- Always keep this in sync with the description below. It ensures that the list is complete. /-- info: #[`package.barrel, `package.cache, `package.deps, `package.extraDep, `package.optBarrel, `package.optCache, @@ -305,7 +305,7 @@ info: #[`package.barrel, `package.cache, `package.deps, `package.extraDep, `pack :::: -```lean (show := false) +```lean -show -- Always keep this in sync with the description below. It ensures that the list is complete. /-- info: [`lean_lib.extraDep, `lean_lib.leanArts, `lean_lib.static.export, `lean_lib.shared, `lean_lib.modules, `lean_lib.static, @@ -321,7 +321,7 @@ The facets available for libraries are: : `leanArts` - The artifacts that the Lean compiler produces for the library or executable ({tech key:=".olean files"}`*.olean`, `*.ilean`, and `*.c` files). + The artifacts that the Lean compiler produces for the library or executable ({tech (key := ".olean files")}`*.olean`, `*.ilean`, and `*.c` files). : `static` @@ -347,7 +347,7 @@ Executables have a single `exe` facet that consists of the executable binary. ::: -```lean (show := false) +```lean -show -- Always keep this in sync with the description below. It ensures that the list is complete. /-- info: module.bc @@ -489,7 +489,7 @@ Because they are Lean definitions, Lake scripts can only be defined in the Lean Restore the following once we can import enough of Lake to elaborate it ```` -```lean (show := false) +```lean -show section open Lake DSL ``` @@ -513,7 +513,7 @@ script "list-deps" := do ``` ::: -```lean (show := false) +```lean -show end ``` ```` @@ -654,7 +654,7 @@ This is true for all of the monads in the Lake API, including {name Lake.ScriptM Monads that provide access to information about the current Lake workspace have {name Lake.MonadWorkspace}`MonadWorkspace` instances. In particular, there are instances for {name Lake.ScriptM}`ScriptM` and {name Lake.LakeM}`LakeM`. -```lean (show := false) +```lean -show section open Lake #synth MonadWorkspace ScriptM diff --git a/Manual/BuildTools/Lake/CLI.lean b/Manual/BuildTools/Lake/CLI.lean index d847c2c2..e7527806 100644 --- a/Manual/BuildTools/Lake/CLI.lean +++ b/Manual/BuildTools/Lake/CLI.lean @@ -142,9 +142,9 @@ Otherwise, the provided command is invoked in Lake's environment. ::::paragraph The following variables are set, overriding previous values: -:::table align:=left +:::table (align := left) * - * {envVar def:=true}`LAKE` + * {envVar +def}`LAKE` * The detected Lake executable * * {envVar}`LAKE_HOME` @@ -163,7 +163,7 @@ The following variables are set, overriding previous values: ::::paragraph The following variables are augmented with additional information: -:::table align:=left +:::table (align := left) * * {envVar}`LEAN_PATH` * Lake's and the {tech}[workspace]'s Lean {tech}[library directories] are added. @@ -185,35 +185,35 @@ The following variables are augmented with additional information: ::::paragraph Lake itself can be configured with the following environment variables: -:::table align:=left +:::table (align := left) * - * {envVar def:=true}`ELAN_HOME` + * {envVar +def}`ELAN_HOME` * The location of the {ref "elan"}[Elan] installation, which is used for {ref "automatic-toolchain-updates"}[automatic toolchain updates]. * - * {envVar def:=true}`ELAN` + * {envVar +def}`ELAN` * The location of the `elan` binary, which is used for {ref "automatic-toolchain-updates"}[automatic toolchain updates]. If it is not set, an occurrence of `elan` must exist on the {envVar}`PATH`. * - * {envVar def:=true}`LAKE_HOME` + * {envVar +def}`LAKE_HOME` * The location of the Lake installation. This environment variable is only consulted when Lake is unable to determine its installation path from the location of the `lake` executable that's currently running. * - * {envVar def:=true}`LEAN_SYSROOT` + * {envVar +def}`LEAN_SYSROOT` * The location of the Lean installation, used to find the Lean compiler, the standard library, and other bundled tools. Lake first checks whether its binary is colocated with a Lean install, using that installation if so. - If not, or if {envVar def:=true}`LAKE_OVERRIDE_LEAN` is true, then Lake consults {envVar}`LEAN_SYSROOT`. - If this is not set, Lake consults the {envVar def:=true}`LEAN` environment variable to find the Lean compiler, and attempts to find the Lean installation relative to the compiler. + If not, or if {envVar +def}`LAKE_OVERRIDE_LEAN` is true, then Lake consults {envVar}`LEAN_SYSROOT`. + If this is not set, Lake consults the {envVar +def}`LEAN` environment variable to find the Lean compiler, and attempts to find the Lean installation relative to the compiler. If {envVar}`LEAN` is set but empty, Lake considers Lean to be disabled. If {envVar}`LEAN_SYSROOT` and {envVar}`LEAN` are unset, the first occurrence of `lean` on the {envVar}`PATH` is used to find the installation. * - * {envVar def:=true}`LEAN_CC` and {envVar def:=true}`LEAN_AR` + * {envVar +def}`LEAN_CC` and {envVar +def}`LEAN_AR` * If {envVar}`LEAN_CC` and/or {envVar}`LEAN_AR` is set, its value is used as the C compiler or `ar` command when building libraries. If not, Lake will fall back to the bundled tool in the Lean installation. - If the bundled tool is not found, the value of {envVar def:=true}`CC` or {envVar def:=true}`AR`, followed by a `cc` or `ar` on the {envVar}`PATH`, are used. + If the bundled tool is not found, the value of {envVar +def}`CC` or {envVar +def}`AR`, followed by a `cc` or `ar` on the {envVar}`PATH`, are used. * - * {envVar def:=true}`LAKE_NO_CACHE` + * {envVar +def}`LAKE_NO_CACHE` * If true, Lake does not use cached builds from [Reservoir](https://reservoir.lean-lang.org/) or {ref "lake-github"}[GitHub]. This environment variable can be overridden using the {lakeOpt}`--try-cache` command-line option. @@ -224,7 +224,7 @@ Lake considers an environment variable to be true when its value is `y`, `yes`, It considers a variable to be false when its value is `n`, `no`, `f`, `false`, `off`, or `0`, compared case-insensitively. If the variable is unset, or its value is neither true nor false, a default value is used. -```lean (show := false) +```lean -show -- Test the claim above /-- info: def Lake.envToBool? : String → Option Bool := @@ -285,7 +285,7 @@ Single-character flags cannot be combined; `-HR` is not equivalent to `-H -R`. : {lakeOptDef flag}`--reconfigure` or {lakeOptDef flag}`-R` - Normally, the {tech}[package configuration] file is {tech key:="elaborator"}[elaborated] when a package is first configured, with the result cached to a {tech}[`.olean` file] that is used for future invocations until the package configuration + Normally, the {tech}[package configuration] file is {tech (key := "elaborator")}[elaborated] when a package is first configured, with the result cached to a {tech}[`.olean` file] that is used for future invocations until the package configuration Providing this flag causes the configuration file to be re-elaborated. : {lakeOptDef flag}`--keep-toolchain` diff --git a/Manual/BuildTools/Lake/Config.lean b/Manual/BuildTools/Lake/Config.lean index 574ffd2f..1ab3591d 100644 --- a/Manual/BuildTools/Lake/Config.lean +++ b/Manual/BuildTools/Lake/Config.lean @@ -49,7 +49,7 @@ The command {lake}`translate-config` can be used to automatically convert betwee ::: Both formats are processed similarly by Lake, which extracts the {tech}[package configuration] from the configuration file in the form of internal structure types. -When the package is {tech key:="configure package"}[configured], the resulting data structures are written to `lakefile.olean` in the {tech}[build directory]. +When the package is {tech (key := "configure package")}[configured], the resulting data structures are written to `lakefile.olean` in the {tech}[build directory]. # Declarative TOML Format @@ -79,7 +79,7 @@ Field names not used by Lake should not be used to store metadata to be processe The top-level contents of `lakefile.toml` specify the options that apply to the package itself, including metadata such as the name and version, the locations of the files in the {tech}[workspace], compiler flags to be used for all {tech}[targets], and The only mandatory field is `name`, which declares the package's name. -:::::tomlTableDocs root "Package Configuration" Lake.PackageConfig skip:=backend skip:=releaseRepo? skip:=buildArchive? skip:=manifestFile skip:=moreServerArgs skip:=dynlibs skip:=plugins +:::::tomlTableDocs root "Package Configuration" Lake.PackageConfig (skip := backend) (skip := releaseRepo?) (skip := buildArchive?) (skip := manifestFile) (skip := moreServerArgs) (skip := dynlibs) (skip := plugins) ::::tomlFieldCategory "Metadata" name version versionTags description keywords homepage license licenseFiles readmeFile reservoir These options describe the package. @@ -121,7 +121,7 @@ These options define a cloud release for the package, as described in the sectio :::tomlField Lake.PackageConfig defaultTargets "default targets' names (array)" "default targets' names (array)" String (sort := 2) -{includeDocstring Lake.Package.defaultTargets (elab:=false)} +{includeDocstring Lake.Package.defaultTargets -elab} ::: @@ -366,7 +366,7 @@ There are three kinds of sources: * Git repositories, which may be local paths or URLs * Local paths -::::tomlTableDocs "require" "Requiring Packages" Lake.Dependency skip:=src? skip := opts skip:=subdir skip:=version? +::::tomlTableDocs "require" "Requiring Packages" Lake.Dependency (skip := src?) (skip := opts) (skip := subdir) (skip := version?) The {tomlField Lake.Dependency}`path` and {tomlField Lake.Dependency}`git` fields specify an explicit source for a dependency. If neither are provided, then the dependency is fetched from [Reservoir](https://reservoir.lean-lang.org/), or an alternative registry if one has been configured. @@ -439,7 +439,7 @@ version = "2.12" ``` :::: -In particular, the package will be checked out from the `main` branch, and the version number specified in the package's {tech key:="package configuration"}[configuration] should match `2.12`. +In particular, the package will be checked out from the `main` branch, and the version number specified in the package's {tech (key := "package configuration")}[configuration] should match `2.12`. ::::: :::::example "Requiring Packages from a Git tag" @@ -459,7 +459,7 @@ rev = "v2.12" opts := {}}] ``` :::: -The version number specified in the package's {tech key:="package configuration"}[configuration] is not used. +The version number specified in the package's {tech (key := "package configuration")}[configuration] is not used. ::::: :::::example "Requiring Reservoir Packages from a Git tag" @@ -475,7 +475,7 @@ scope = "exampleDev" #[{name := `example, scope := "exampleDev", version? := some "git#v2.12", src? := none, opts := {}}] ``` :::: -The version number specified in the package's {tech key:="package configuration"}[configuration] is not used. +The version number specified in the package's {tech (key := "package configuration")}[configuration] is not used. ::::: :::::example "Requiring Packages from Paths" @@ -519,7 +519,7 @@ source = {type = "git", url = "https://example.com/example.git"} Library targets are expected in the `lean_lib` array of tables. -::::tomlTableDocs "lean_lib" "Library Targets" Lake.LeanLibConfig skip := backend skip:=globs skip:=nativeFacets +::::tomlTableDocs "lean_lib" "Library Targets" Lake.LeanLibConfig (skip := backend) (skip := globs) (skip := nativeFacets) :::tomlField Lake.LeanLibConfig name "The library name" "Library names" String The library's name, which is typically the same as its single module root. ::: @@ -611,7 +611,7 @@ If its modules are accessed at elaboration time, they will be compiled to native ## Executable Targets -:::: tomlTableDocs "lean_exe" "Executable Targets" Lake.LeanExeConfig skip := backend skip:=globs skip:=nativeFacets +:::: tomlTableDocs "lean_exe" "Executable Targets" Lake.LeanExeConfig (skip := backend) (skip := globs) (skip := nativeFacets) :::tomlField Lake.LeanExeConfig name "The executable's name" "Executable names" String The executable's name. ::: @@ -653,7 +653,7 @@ name = "trustworthytool" ``` :::: -```lean (show := false) +```lean -show def main : List String → IO UInt32 := fun _ => pure 0 ``` @@ -701,7 +701,7 @@ exeName = "tt" ``` :::: -```lean (show := false) +```lean -show def main : List String → IO UInt32 := fun _ => pure 0 ``` @@ -721,7 +721,7 @@ Because the Lean format is a Lean source file, it can be edited using all the fe Additionally, Lean's metaprogramming framework allows elaboration-time side effects to be used to implement features such as configuration steps that are conditional on the current platform. However, a consequence of the Lean configuration format being a Lean file is that it is not feasible to process such files using tools that are not themselves written in Lean. -```lean (show := false) +```lean -show section open Lake DSL open Lean (NameMap) @@ -731,7 +731,7 @@ open Lean (NameMap) The declarative subset of the Lean configuration format uses sequences of declaration fields to specify configuration options. -:::syntax Lake.DSL.declField (title := "Declarative Fields") (open := false) +:::syntax Lake.DSL.declField (title := "Declarative Fields") -open {includeDocstring Lake.DSL.declField} @@ -741,7 +741,7 @@ $_ := $_ ::: ## Packages -::::syntax command title:="Package Configuration" +::::syntax command (title := "Package Configuration") ```grammar $[$_:docComment]? $[@[ $_,* ]]? @@ -800,7 +800,7 @@ The {keywordOf Lake.DSL.requireDecl}`with` clause specifies a {lean}`NameMap Str This is equivalent to passing {lakeOpt}`-K` options to {lake}`build` when building the dependency on the command line. ::: -:::syntax fromClause (open := false) (title := "Package Sources") +:::syntax fromClause -open (title := "Package Sources") {includeDocstring Lake.DSL.fromClause} @@ -999,7 +999,7 @@ $[where $_*]? In Lake's DSL, {deftech}_globs_ are patterns that match sets of module names. There is a coercion from names to globs that match the name in question, and there are two postfix operators for constructing further globs. -```lean (show := false) +```lean -show section example : Lake.Glob := `n @@ -1048,12 +1048,12 @@ Whitespace is not permitted between the name and `.*` or `.+`. ## Scripts Lake scripts are used to automate tasks that require access to a package configuration but do not participate in incremental builds of artifacts from code. -Scripts run in the {name Lake.ScriptM}`ScriptM` monad, which is {name}`IO` with an additional {tech}[reader monad] {tech key:="monad transformer"}[transformer] that provides access to the package configuration. +Scripts run in the {name Lake.ScriptM}`ScriptM` monad, which is {name}`IO` with an additional {tech}[reader monad] {tech (key := "monad transformer")}[transformer] that provides access to the package configuration. In particular, a script should have the type {lean}`List String → ScriptM UInt32`. Workspace information in scripts is primarily accessed via the {inst}`MonadWorkspace ScriptM` instance. -```lean (show := false) +```lean -show example : ScriptFn = (List String → ScriptM UInt32) := rfl ``` diff --git a/Manual/Classes.lean b/Manual/Classes.lean index 125a3bc6..4b439893 100644 --- a/Manual/Classes.lean +++ b/Manual/Classes.lean @@ -66,7 +66,7 @@ All of these possibilities are used in practice: While ordinary polymorphic definitions simply expect instantiation with arbitrary parameters, the operators overloaded with type classes are to be instantiated with {deftech}_instances_ that define the overloaded operation for some specific set of parameters. These {deftech}[instance-implicit] parameters are indicated in square brackets. -At invocation sites, Lean either {deftech key:="synthesis"}_synthesizes_ {index}[instance synthesis] {index subterm:="of type class instances"}[synthesis] a suitable instance from the available candidates or signals an error. +At invocation sites, Lean either {deftech (key := "synthesis")}_synthesizes_ {index}[instance synthesis] {index (subterm := "of type class instances")}[synthesis] a suitable instance from the available candidates or signals an error. Because instances may themselves have instance parameters, this search process may be recursive and result in a final composite instance value that combines code from a variety of instances. Thus, type class instance synthesis is also a means of constructing programs in a type-directed manner. @@ -101,7 +101,7 @@ Declares a new type class. ::: :::keepEnv -```lean (show := false) +```lean -show -- Just make sure that the `deriving` clause is legit class A (n : Nat) where k : Nat @@ -144,7 +144,7 @@ While {keywordOf Lean.Parser.Command.declaration}`deriving` clauses are allowed :::example "No Instances of Non-Classes" Lean rejects instance-implicit parameters of types that are not classes: -```lean (error := true) (name := notClass) +```lean +error (name := notClass) def f [n : Nat] : n = n := rfl ``` @@ -363,7 +363,7 @@ Because {name}`AddMul` is a {keywordOf Lean.Parser.Command.classAbbrev}`class ab ``` However, {name}`plusTimes2` fails, because there is no {lean}`AddMul' Nat` instance—no instances whatsoever have yet been declared: -```lean (name := plusTimes2a) (error := true) +```lean (name := plusTimes2a) +error #eval plusTimes2 2 5 7 ``` ```leanOutput plusTimes2a @@ -396,7 +396,7 @@ tag := "deriving-instances" Lean can automatically generate instances for many classes, a process known as {deftech}_deriving_ instances. Instance deriving can be invoked either when defining a type or as a stand-alone command. -:::syntax Lean.Parser.Command.optDeriving (open := false) (title := "Instance Deriving (Optional)") +:::syntax Lean.Parser.Command.optDeriving -open (title := "Instance Deriving (Optional)") As part of a command that creates a new inductive type, a {keywordOf Lean.Parser.Command.declaration}`deriving` clause specifies a comma-separated list of class names for which instances should be generated: ```grammar $[deriving $[$_],*]? diff --git a/Manual/Classes/BasicClasses.lean b/Manual/Classes/BasicClasses.lean index 735a5d16..4385c781 100644 --- a/Manual/Classes/BasicClasses.lean +++ b/Manual/Classes/BasicClasses.lean @@ -198,7 +198,7 @@ These should be in agreement with `Ord`, `LT`, and `LE` instances, if they exist :::leanSection -```lean (show := false) +```lean -show variable {α : Type u} [LE α] ``` @@ -216,7 +216,7 @@ They can be used as the right-hand side of an {keywordOf Lean.Parser.Command.dec tag := "decidable-propositions" %%% -A proposition is {deftech}_decidable_ if it can be checked algorithmically.{index}[decidable]{index subterm:="decidable"}[proposition] +A proposition is {deftech}_decidable_ if it can be checked algorithmically.{index}[decidable]{index (subterm := "decidable")}[proposition] The Law of the Excluded Middle means that every proposition is true or false, but it provides no way to check which of the two cases holds, which can often be useful. By default, only algorithmic {lean}`Decidable` instances for which code can be generated are in scope; opening the `Classical` namespace makes every proposition decidable. @@ -239,7 +239,7 @@ By default, only algorithmic {lean}`Decidable` instances for which code can be g ::::keepEnv :::example "Excluded Middle and {lean}`Decidable`" The equality of functions from {lean}`Nat` to {lean}`Nat` is not decidable: -```lean (error:=true) (name := NatFunNotDecEq) +```lean +error (name := NatFunNotDecEq) example (f g : Nat → Nat) : Decidable (f = g) := inferInstance ``` ```leanOutput NatFunNotDecEq @@ -285,7 +285,7 @@ draft := true ::: -{docstring ToString (allowMissing := true)} +{docstring ToString +allowMissing} # Arithmetic and Bitwise Operators diff --git a/Manual/Classes/InstanceDecls.lean b/Manual/Classes/InstanceDecls.lean index 20f31659..1f2ddac2 100644 --- a/Manual/Classes/InstanceDecls.lean +++ b/Manual/Classes/InstanceDecls.lean @@ -130,7 +130,7 @@ inductive NatTree where | branch (left : NatTree) (val : Nat) (right : NatTree) ``` the following {name}`BEq` instance fails: -```lean (error := true) (name := beqNatTreeFail) +```lean +error (name := beqNatTreeFail) instance : BEq NatTree where beq | .leaf, .leaf => true @@ -177,7 +177,7 @@ inductive NatRoseTree where ``` Checking the equality of rose trees requires checking equality of arrays. However, instances are not typically available for instance synthesis during their own definitions, so the following definition fails, even though {lean}`NatRoseTree.beq` is a recursive function and is in scope in its own definition. -```lean (error := true) (name := natRoseTreeBEqFail) (keep := false) +```lean +error (name := natRoseTreeBEqFail) -keep def NatRoseTree.beq : (tree1 tree2 : NatRoseTree) → Bool | .node val1 children1, .node val2 children2 => val1 == val2 && @@ -213,7 +213,7 @@ This is done using ordinary Lean function syntax. Just as with other instances, the function in question is not available for instance synthesis in its own definition. ::::keepEnv :::example "An instance for a sum class" -```lean (show := false) +```lean -show axiom α : Type ``` Because {lean}`DecidableEq α` is an abbreviation for {lean}`(a b : α) → Decidable (Eq a b)`, its arguments can be used directly, as in this example: @@ -248,7 +248,7 @@ inductive StringList where | cons (hd : String) (tl : StringList) ``` In the following attempt at defining a {name}`DecidableEq` instance, instance synthesis invoked while elaborating the inner {keywordOf termIfThenElse}`if` fails because the instance is not available for instance synthesis in its own definition: -```lean (error := true) (name := stringListNoRec) (keep := false) +```lean +error (name := stringListNoRec) -keep instance : DecidableEq StringList | .nil, .nil => .isTrue rfl | .cons h1 t1, .cons h2 t2 => @@ -295,7 +295,7 @@ tag := "instance-priorities" Instances may be assigned {deftech}_priorities_. During instance synthesis, higher-priority instances are preferred; see {ref "instance-synth"}[the section on instance synthesis] for details of instance synthesis. -:::syntax prio open:=false (title := "Instance Priorities") +:::syntax prio -open (title := "Instance Priorities") Priorities may be numeric: ```grammar $n:num diff --git a/Manual/Classes/InstanceSynth.lean b/Manual/Classes/InstanceSynth.lean index c0ddcdd2..67586fd4 100644 --- a/Manual/Classes/InstanceSynth.lean +++ b/Manual/Classes/InstanceSynth.lean @@ -180,7 +180,7 @@ In some cases, however, the choice of one parameter should cause an automatic ch For example, the overloaded membership predicate type class {name}`Membership` treats the type of elements of a data structure as an output, so that the type of element can be determined by the type of data structure at a use site, instead of requiring that there be sufficient type annotations to determine _both_ types prior to starting instance synthesis. An element of a {lean}`List Nat` can be concluded to be a {lean}`Nat` simply on the basis of its membership in the list. -```signature (show := false) +```signature -show -- Test the above claim Membership.{u, v} (α : outParam (Type u)) (γ : Type v) : Type (max u v) ``` @@ -210,7 +210,7 @@ instance [Serialize α γ] [Serialize β γ] [Append γ] : ``` In this example, the output type is unknown. -```lean (error := true) (name := noOutputType) +```lean +error (name := noOutputType) example := ser (2, 3) ``` Instance synthesis can't select the {lean}`Serialize Nat String` instance, and thus the {lean}`Append String` instance, because that would require instantiating the output type as {lean}`String`, so the search gets stuck: @@ -271,7 +271,7 @@ instance : OneSmaller Bool Unit where | false, _ => () ``` Because instance synthesis selects the most recently defined instance, the following code is an error: -```lean (error := true) (name := nosmaller) +```lean +error (name := nosmaller) #check OneSmaller.shrink (β := Bool) (some false) sorry ``` ```leanOutput nosmaller diff --git a/Manual/Coercions.lean b/Manual/Coercions.lean index a05713fd..2ca31866 100644 --- a/Manual/Coercions.lean +++ b/Manual/Coercions.lean @@ -21,7 +21,7 @@ open Lean (Syntax SourceInfo) tag := "coercions" %%% -```lean (show := false) +```lean -show section open Lean (TSyntax Name) variable {c1 c2 : Name} {α : Type u} @@ -47,7 +47,7 @@ Coercions are found using type class {tech}[synthesis]. The set of coercions can be extended by adding further instances of the appropriate type classes. ::: -```lean (show := false) +```lean -show end ``` @@ -77,7 +77,7 @@ fun f x => { fn := fun x_1 => f ↑x } ::: -```lean (show := false) +```lean -show section variable {α : Type u} ``` @@ -86,11 +86,11 @@ Coercions are not used to resolve {tech}[generalized field notation]: only the i However, a {tech}[type ascription] can be used to trigger a coercion to the type that has the desired generalized field. Coercions are also not used to resolve {name}`OfNat` instances: even though there is a default instance for {lean}`OfNat Nat`, a coercion from {lean}`Nat` to {lean}`α` does not allow natural number literals to be used for {lean}`α`. -```lean (show := false) +```lean -show end ``` -```lean (show := false) +```lean -show -- Test comment about field notation /-- error: Unknown constant `Nat.bdiv` -/ #check_msgs in @@ -115,10 +115,10 @@ example (n : Nat) := (n : Int).bdiv 2 :::example "Coercions and Generalized Field Notation" -The name {lean (error := true)}`Nat.bdiv` is not defined, but {lean}`Int.bdiv` exists. +The name {lean +error}`Nat.bdiv` is not defined, but {lean}`Int.bdiv` exists. The coercion from {lean}`Nat` to {lean}`Int` is not considered when looking up the field `bdiv`: -```lean (error := true) (name := natBdiv) +```lean +error (name := natBdiv) example (n : Nat) := n.bdiv 2 ``` ```leanOutput natBdiv @@ -168,7 +168,7 @@ def Bin.ofNat (n : Nat) : Bin := | n + 1 => (Bin.ofNat n).succ ``` -```lean (show := false) +```lean -show --- Internal tests /-- info: [0, 1, 10, 11, 100, 101, 110, 111, 1000] -/ #check_msgs in @@ -206,7 +206,7 @@ theorem Bin.ofNat_toNat_eq {n : Nat} : (Bin.ofNat n).toNat = n := by Even if {lean}`Bin.ofNat` is registered as a coercion, natural number literals cannot be used for {lean}`Bin`: -```lean (name := nineFail) (error := true) +```lean (name := nineFail) +error attribute [coe] Bin.ofNat instance : Coe Nat Bin where @@ -299,7 +299,7 @@ Coercions are also inserted when they are explicitly requested. Each situation in which coercions may be inserted has a corresponding prefix operator that triggers the appropriate insertion. ::: -```lean (show := false) +```lean -show section variable {α : Type u} {α' : Type u'} {β : Type u} [Coe α α'] [Coe α' β] (e : α) ``` @@ -307,7 +307,7 @@ variable {α : Type u} {α' : Type u'} {β : Type u} [Coe α α'] [Coe α' β] ( Because coercions are inserted automatically, nested {tech}[type ascriptions] provide a way to precisely control the types involved in a coercion. If {lean}`α` and {lean}`β` are not the same type, {lean}`((e : α) : β)` arranges for {lean}`e` to have type {lean}`α` and then inserts a coercion from {lean}`α` to {lean}`β`. -```lean (show := false) +```lean -show end ``` @@ -350,7 +350,7 @@ def tomorrow : Later String := ``` ::: -```lean (show := false) +```lean -show section variable {α : Type u} ``` @@ -411,7 +411,7 @@ hello ``` :::: -```lean (show := false) +```lean -show end ``` @@ -464,7 +464,7 @@ def four : Even := ⟨4, by omega⟩ ``` Due to coercion chaining, there is also a coercion from {name}`Even` to {name}`Int` formed by chaining the {inst}`Coe Even Nat` instance with the existing coercion from {name}`Nat` to {name}`Int`: -```lean name := four' +```lean (name := four') #eval (four : Int) - 5 ``` ```leanOutput four' @@ -476,7 +476,7 @@ Due to coercion chaining, there is also a coercion from {name}`Even` to {name}`I Non-dependent coercions are used whenever all values of the inferred type can be coerced to the target type. :::example "Defining Dependent Coercions" -The string "four" can be coerced into the natural number {lean type:="Nat"}`4` with this instance declaration: +The string "four" can be coerced into the natural number {lean (type := "Nat")}`4` with this instance declaration: ```lean (name := fourCoe) instance : CoeDep String "four" Nat where coe := 4 @@ -488,7 +488,7 @@ instance : CoeDep String "four" Nat where ``` Ordinary type errors are produced for other strings: -```lean (error := true) (name := threeCoe) +```lean +error (name := threeCoe) #eval ("three" : Nat) ``` ```leanOutput threeCoe @@ -503,7 +503,7 @@ but is expected to have type ::: -```lean (show := false) +```lean -show section variable {α α' α'' β β' «…» γ: Sort _} @@ -516,7 +516,7 @@ variable [CoeHead α α'] [CoeOut α' …] [CoeOut … α''] [Coe α'' …] [Coe :::paragraph Non-dependent coercions may be chained: if there is a coercion from {lean}`α` to {lean}`β` and from {lean}`β` to {lean}`γ`, then there is also a coercion from {lean}`α` to {lean}`γ`. -{index subterm:="of coercions"}[chain] +{index (subterm:="of coercions")}[chain] The chain should be in the form {name}`CoeHead`$`?`{name}`CoeOut`$`*`{name}`Coe`$`*`{name}`CoeTail`$`?`, which is to say it may consist of: * An optional instance of {inst}`CoeHead α α'`, followed by @@ -578,7 +578,7 @@ instance : Coe Bool (Decision α) := ⟨Decision.ofBool⟩ ``` With these instances, coercion chaining works: -```lean name := chainTruthiness +```lean (name := chainTruthiness) #eval ({ val := 1, isTrue := true : Truthy Nat } : Decision String) ``` ```leanOutput chainTruthiness @@ -586,7 +586,7 @@ Decision.yes ``` Attempting to use the wrong class leads to an error: -```lean name:=coeOutErr error:=true +```lean (name := coeOutErr) +error instance : Coe (Truthy α) Bool := ⟨Truthy.isTrue⟩ ``` ```leanOutput coeOutErr @@ -597,7 +597,7 @@ instance does not provide concrete values for (semi-)out-params ::: -```lean (show := false) +```lean -show end ``` @@ -612,7 +612,7 @@ If both exist, then the {name}`CoeDep` instance takes priority. {docstring CoeT} -```lean (show := false) +```lean -show section variable {α β : Sort _} {e : α} [CoeDep α e β] ``` @@ -622,14 +622,14 @@ As an alternative to a chain of coercions, a term {lean}`e` of type {lean}`α` c Dependent coercions are useful in situations where only some of the values can be coerced; this mechanism is used to coerce only decidable propositions to {lean}`Bool`. They are also useful when the value itself occurs in the coercion's target type. -```lean (show := false) +```lean -show end ``` {docstring CoeDep} :::example "Dependent Coercion" -```lean (show := false) +```lean -show universe u ``` @@ -654,7 +654,7 @@ def oneTwoThree : NonEmptyList Nat := ⟨[1, 2, 3], by simp⟩ Arbitrary lists cannot, however, be coerced to non-empty lists, because some arbitrarily-chosen lists may indeed be empty: -```lean (error := true) (name := coeFail) (keep := false) +```lean +error (name := coeFail) -keep instance : Coe (List α) (NonEmptyList α) where coe xs := ⟨xs, _⟩ ``` @@ -679,8 +679,8 @@ instance : CoeDep (List α) (x :: xs) (NonEmptyList α) where Dependent coercion insertion requires that the term to be coerced syntactically matches the term in the instance header. -Lists that are known to be non-empty, but which are not syntactically instances of {lean type:= "{α : Type u} → α → List α → List α"}`(· :: ·)`, cannot be coerced with this instance. -```lean (error := true) (name := coeFailDep) +Lists that are known to be non-empty, but which are not syntactically instances of {lean (type := "{α : Type u} → α → List α → List α")}`(· :: ·)`, cannot be coerced with this instance. +```lean +error (name := coeFailDep) #check fun (xs : List Nat) => let ys : List Nat := xs ++ [4] @@ -803,7 +803,7 @@ def Weekday.fromFin : Fin 7 → Weekday | 6 => su ``` -```lean (show := false) +```lean -show theorem Weekday.toFin_fromFin_id : Weekday.toFin (Weekday.fromFin n) = n := by repeat (cases ‹Fin (_ + 1)› using Fin.cases; case zero => rfl) apply Fin.elim0; assumption @@ -859,10 +859,10 @@ The type classes {name}`NatCast` and {name}`IntCast` are special cases of {name} They exist to enable better integration with large libraries of mathematics, such as [Mathlib](https://github.com/leanprover-community/mathlib4), that make heavy use of coercions to map from the natural numbers or integers to other structures (typically rings). Ideally, the coercion of a natural number or integer into these structures is a {tech}[simp normal form], because it is a convenient way to denote them. -When the coercion application is expected to be the {tech}[simp normal form] for a type, it is important that _all_ such coercions are {tech key:="definitional equality"}[definitionally equal] in practice. +When the coercion application is expected to be the {tech}[simp normal form] for a type, it is important that _all_ such coercions are {tech (key := "definitional equality")}[definitionally equal] in practice. Otherwise, the {tech}[simp normal form] would need to choose a single chained coercion path, but lemmas could accidentally be stated using a different path. Because {tactic}`simp`'s internal index is based on the underlying structure of the term, rather than its presentation in the surface syntax, these differences would cause the lemmas to not be applied where expected. -{lean}`NatCast` and {lean}`IntCast` instances, on the other hand, should be defined such that they are always {tech key:="definitional equality"}[definitionally equal], avoiding the problem. +{lean}`NatCast` and {lean}`IntCast` instances, on the other hand, should be defined such that they are always {tech (key := "definitional equality")}[definitionally equal], avoiding the problem. The Lean standard library's instances are arranged such that {name}`NatCast` or {name}`IntCast` instances are chosen preferentially over chains of coercion instances during coercion insertion. They can also be used as {name}`CoeOut` instances, allowing a graceful fallback to coercion chaining when needed. @@ -919,7 +919,7 @@ structure Monoid where op_id_identity : ∀ (x : Carrier), op x id = x ``` -The type {lean type := "Type 1"}`Monoid` does not indicate the carrier: +The type {lean (type := "Type 1")}`Monoid` does not indicate the carrier: ```lean def StringMonoid : Monoid where Carrier := String @@ -993,7 +993,7 @@ Unlike {name}`CoeDep`, the term itself is not taken into account during instance ``` ::: -```lean (show := false) +```lean -show section variable {α : Type u} {β : Type v} ``` @@ -1056,7 +1056,7 @@ instance : CoeFun (NamedFun α α'') (fun _ => α → α'') where [1, 2, 3, 4, 5, 6] ``` ::: -```lean (show := false) +```lean -show end ``` diff --git a/Manual/Defs.lean b/Manual/Defs.lean index 9e214452..1b4e45c7 100644 --- a/Manual/Defs.lean +++ b/Manual/Defs.lean @@ -30,7 +30,7 @@ The following commands in Lean are definition-like: {TODO}[Render commands as th * {keyword}`theorem` * {keyword}`opaque` -All of these commands cause Lean to {tech key:="elaborator"}[elaborate] a term based on a {tech}[signature]. +All of these commands cause Lean to {tech (key := "elaborator")}[elaborate] a term based on a {tech}[signature]. With the exception of {keywordOf Lean.Parser.Command.example}`example`, which discards the result, the resulting expression in Lean's core language is saved for future use in the environment. The {keywordOf Lean.Parser.Command.declaration}`instance` command is described in the {ref "instance-declarations"}[section on instance declarations]. @@ -44,7 +44,7 @@ Declarations accept a consistent set of {deftech}_modifiers_, all of which are o Modifiers change some aspect of the declaration's interpretation; for example, they can add documentation or change its scope. The order of modifiers is fixed, but not every kind of declaration accepts every kind of modifier. -:::syntax declModifiers (open := false) (alias:=Lean.Parser.Command.declModifiers) (title := "Declaration Modifiers") +:::syntax declModifiers -open (alias:=Lean.Parser.Command.declModifiers) (title := "Declaration Modifiers") Modifiers consist of the following, in order, all of which are optional: 1. a documentation comment, 2. a list of {tech}[attributes], @@ -66,7 +66,7 @@ $[$_]? Documentation comments are not, in fact comments: it is a syntax error to put a documentation comment in a position where it is not processed as documentation. They also occur in positions where some kind of text is required, but string escaping would be onerous, such as the desired messages on the {keywordOf Lean.guardMsgsCmd}`#guard_msgs` command. -:::syntax docComment (open:=false) (title := "Documentation Comments") +:::syntax docComment -open (title := "Documentation Comments") Documentation comments are like ordinary block comments, but they begin with the sequence `/--` rather than `/-`; just like ordinary comments, they are terminated with `-/`. @@ -80,7 +80,7 @@ Documentation comments are like ordinary block comments, but they begin with the Attributes are an extensible collection of modifiers that associate additional information with declarations. They are described in a {ref "attributes"}[dedicated section]. -If a declaration is marked {deftech key:="private"}[{keyword}`private`], then it is not accessible outside the module in which it is defined. +If a declaration is marked {deftech (key := "private")}[{keyword}`private`], then it is not accessible outside the module in which it is defined. If it is {keyword}`protected`, then opening its namespace does not bring it into scope. Functions marked {keyword}`noncomputable` are not compiled and cannot be executed. @@ -98,7 +98,7 @@ tag := "signature-syntax" The {deftech}[_header_] of a definition or declaration consists of the constant being declared or defined, if relevant, together with its signature. The {deftech}_signature_ of a constant specifies how it can be used. -The information present in the signature is more than just the type, including information such as {tech key:="universe parameter"}[universe level parameters] and the default values of its optional parameters. +The information present in the signature is more than just the type, including information such as {tech (key := "universe parameter")}[universe level parameters] and the default values of its optional parameters. In Lean, signatures are written in a consistent format in different kinds of declarations. ## Declaration Names @@ -106,7 +106,7 @@ In Lean, signatures are written in a consistent format in different kinds of dec Most headers begin with a {deftech}_declaration name_, which is followed by the signature proper: its parameters and the resulting type. A declaration name is a name that may optionally include universe parameters. -:::syntax declId (open := false) (title := "Declaration Names") +:::syntax declId -open (title := "Declaration Names") Declaration names without universe parameters consist of an identifier: ```grammar $_:ident @@ -129,7 +129,7 @@ tag := "parameter-syntax" After the name, if present, is the header's signature. The signature specifies the declaration's parameters and type. -:::syntax declSig (open := false) (title := "Declaration Signatures") +:::syntax declSig -open (title := "Declaration Signatures") A signature consists of zero or more parameters, followed by a colon and a type. ```grammar @@ -137,7 +137,7 @@ $_* : $_ ``` ::: -:::syntax optDeclSig (open := false) (title := "Optional Signatures") +:::syntax optDeclSig -open (title := "Optional Signatures") Signatures are often optional. In these cases, parameters may be supplied even if the type is omitted. ```grammar @@ -165,7 +165,7 @@ The name is optional for instance implicit parameters. Using an underscore (`_`) instead of a parameter name indicates an anonymous parameter. -:::syntax bracketedBinder (open := false) (title := "Explicit Parameters") +:::syntax bracketedBinder -open (title := "Explicit Parameters") Parenthesized parameters indicate explicit parameters. If more than one identifier or underscore is provided, then all of them become parameters with the same type. ```grammar @@ -210,7 +210,7 @@ Strict implicit parameters are only synthesized at call sites when subsequent pa ::: :::syntax bracketedBinder (title := "Instance Implicit Parameters") -Parameters in square brackets indicate {tech}[instance implicit] parameters, which are synthesized at call sites using {tech key:="synthesis"}[instance synthesis]. +Parameters in square brackets indicate {tech}[instance implicit] parameters, which are synthesized at call sites using {tech (key := "synthesis")}[instance synthesis]. ```grammar [$[$x :]? $t] ``` @@ -219,7 +219,7 @@ Parameters in square brackets indicate {tech}[instance implicit] parameters, whi The parameters are always in scope in the signature's type, which occurs after the colon. They are also in scope in the declaration's body, while names bound in the type itself are only in scope in the type. Thus, parameter names are used twice: - * As names in the declaration's function type, bound as part of a {tech key:="dependent"}[dependent function type]. + * As names in the declaration's function type, bound as part of a {tech (key := "dependent")}[dependent function type]. * As names in the declaration's body. In function definitions, they are bound by a {keywordOf Lean.Parser.Term.fun}`fun`. @@ -245,7 +245,7 @@ def mustBeEqual (n : Nat) : (k : Nat) → n = k → String := ``` ::: -The section on {ref "function-application"}[function application] describes the interpretation of {tech key:="optional parameter"}[optional], {tech key:="automatic parameter"}[automatic], {tech}[implicit], and {tech}[instance implicit] parameters in detail. +The section on {ref "function-application"}[function application] describes the interpretation of {tech (key := "optional parameter")}[optional], {tech (key := "automatic parameter")}[automatic], {tech}[implicit], and {tech}[instance implicit] parameters in detail. ## Automatic Implicit Parameters %%% @@ -263,7 +263,7 @@ They show up in signatures with a trailing dagger (`'✝'`). This prevents an arbitrary choice of name by Lean from becoming part of the API by being usable as a {tech}[named argument]. ::::leanSection -```lean show:=false +```lean -show variable {α : Type u} {β : Type v} ``` :::example "Automatic Implicit Parameters" @@ -289,7 +289,7 @@ map.{u, v} {α : Type u} {β : Type v} ::::example "No Automatic Implicit Parameters" :::leanSection -```lean show:=false +```lean -show universe u v variable {α : Type u} {β : Type v} ``` @@ -299,7 +299,7 @@ Because {option}`autoImplicit` is disabled, this is an error: ::: :::keepEnv -```lean (error := true) (name := noAuto) +```lean +error (name := noAuto) set_option autoImplicit false def map (f : α → β) : (xs : List α) → List β @@ -317,7 +317,7 @@ Unknown identifier `β` The full signature allows the definition to be accepted: -```lean (keep := false) +```lean -keep set_option autoImplicit false def map.{u, v} {α : Type u} {β : Type v} @@ -329,7 +329,7 @@ def map.{u, v} {α : Type u} {β : Type v} Universe parameters are inserted automatically for parameters without explicit type annotations. The type parameters' universes can be inferred, and the appropriate universe parameters inserted, even when {option}`autoImplicit` is disabled: -```lean (keep := false) +```lean -keep set_option autoImplicit false def map {α β} (f : α → β) : @@ -345,7 +345,7 @@ def map {α β} (f : α → β) : :::::example "Iterated Automatic Implicit Parameters" :::leanSection -```lean (show := false) +```lean -show variable (i : Fin n) ``` Given a number bounded by {lean}`n`, represented by the type `Fin n`, an {lean}`AtLeast i` is a natural number paired with a proof that it is at least as large as `i`. @@ -368,7 +368,7 @@ def AtLeast.add (x y : AtLeast i) : AtLeast i := ::::paragraph :::leanSection -```lean (show := false) +```lean -show variable (i : Fin n) ``` The signature of {lean}`AtLeast.add` requires multiple rounds of automatic implicit parameter insertion. @@ -410,7 +410,7 @@ inductive Answer where | no ``` :::keepEnv -```lean (name := asnwer) (error := true) +```lean (name := asnwer) +error def select (choices : α × α × α) : Asnwer → α | .yes => choices.1 | .maybe => choices.2.1 @@ -434,7 +434,7 @@ select.{u_1, u_2} Disabling relaxed automatic implicit parameters makes the error more clear, while still allowing the type to be inserted automatically: :::keepEnv -```lean (name := asnwer2) (error := true) +```lean (name := asnwer2) +error set_option relaxedAutoImplicit false def select (choices : α × α × α) : Asnwer → α @@ -461,7 +461,7 @@ def select (choices : α × α × α) : Answer → α Turning off automatic implicit parameters entirely leads to the definition being rejected: :::keepEnv -```lean (error := true) (name := noauto) +```lean +error (name := noauto) set_option autoImplicit false def select (choices : α × α × α) : Answer → α @@ -478,9 +478,9 @@ Unknown identifier `α` # Definitions Definitions add a new constant to the global environment as a name that stands for a term. -As part of the kernel's definitional equality, this new constant may be replaced via {tech key:="δ"}[δ-reduction] with the term that it stands for. +As part of the kernel's definitional equality, this new constant may be replaced via {tech (key := "δ")}[δ-reduction] with the term that it stands for. In the elaborator, this replacement is governed by the constant's {tech}[reducibility]. -The new constant may be {tech key:="universe polymorphism"}[universe polymorphic], in which case occurrences may instantiate it with different universe level parameters. +The new constant may be {tech (key := "universe polymorphism")}[universe polymorphic], in which case occurrences may instantiate it with different universe level parameters. Function definitions may be recursive. To preserve the consistency of Lean's type theory as a logic, recursive functions must either be opaque to the kernel (e.g. by {ref "partial-functions"}[declaring them {keyword}`partial`]) or proven to terminate with one of the strategies described in {ref "recursive-definitions"}[the section on recursive definitions]. @@ -539,7 +539,7 @@ abbrev $_ $_ where ::: -{deftech}_Opaque constants_ are defined constants that are not subject to {tech key:="δ"}[δ-reduction] in the kernel. +{deftech}_Opaque constants_ are defined constants that are not subject to {tech (key := "δ")}[δ-reduction] in the kernel. They are useful for specifying the existence of some function. Unlike {tech}[axioms], opaque declarations can only be used for types that are inhabited, so they do not risk introducing inconsistency. Also unlike axioms, the inhabitant of the type is used in compiled code. @@ -573,7 +573,7 @@ However, because their use cases are quite different, they differ in many detail Section variables only become parameters to the theorem if they (or their dependents) are mentioned in the header. This prevents changes to a proof from unintentionally changing the theorem statement. * Theorems are {tech}[irreducible] by default. - Because all proofs of the same proposition are {tech key:="definitional equality"}[definitionally equal], there few reasons to unfold a theorem. + Because all proofs of the same proposition are {tech (key := "definitional equality")}[definitionally equal], there few reasons to unfold a theorem. ::: Theorems may be recursive, subject to the same conditions as {ref "recursive-definitions"}[recursive function definitions]. diff --git a/Manual/Elaboration.lean b/Manual/Elaboration.lean index ece4be0e..754cc373 100644 --- a/Manual/Elaboration.lean +++ b/Manual/Elaboration.lean @@ -37,7 +37,7 @@ Roughly speaking, Lean's processing of a source file can be divided into the fol : Elaboration - {deftech key:="elaborator"}[Elaboration] is the process of transforming Lean's user-facing syntax into its core type theory. + {deftech (key := "elaborator")}[Elaboration] is the process of transforming Lean's user-facing syntax into its core type theory. This core theory is much simpler, enabling the trusted kernel to be very small. Elaboration additionally produces metadata, such as proof states or the types of expressions, used for Lean's interactive features, storing them in a side table. @@ -139,7 +139,7 @@ When interacting with Lean code, much more information is needed than when simpl For example, Lean's interactive environment can be used to view the types of selected expressions, to step through all the intermediate states of a proof, to view documentation, and highlight all occurrences of a bound variable. The information necessary to use Lean interactively is stored in a side table called the {deftech}_info trees_ during elaboration. -```lean (show := false) +```lean -show open Lean.Elab (Info) ``` @@ -166,11 +166,11 @@ The language implemented by the kernel is a version of the Calculus of Construct * A {tech}[predicative], non-cumulative hierarchy of universes of data * {ref "quotients"}[Quotient types] with a definitional computation rule * Propositional function extensionality{margin}[Function extensionality is a theorem that can be proved using quotient types, but it is such an important consequence that it's worth listing separately.] - * Definitional {tech key:="η-equivalence"}[η-equality] for functions and products + * Definitional {tech (key := "η-equivalence")}[η-equality] for functions and products * Universe-polymorphic definitions * Consistency: there is no axiom-free closed term of type {lean}`False` -```lean (show := false) (keep := false) +```lean -show -keep -- Test definitional eta for structures structure A where x : Nat @@ -221,7 +221,7 @@ To see auxiliary pattern matching functions in Lean's output, set the option {op {optionDocs pp.match} -```lean (show := false) (keep := false) +```lean -show -keep def third_of_five : List α → Option α | [_, _, x, _, _] => some x | _ => none diff --git a/Manual/Grind.lean b/Manual/Grind.lean index 01ea97ca..1c3a242e 100644 --- a/Manual/Grind.lean +++ b/Manual/Grind.lean @@ -51,7 +51,7 @@ open Manual (comment) tag := "grind-tactic" %%% -```lean (show := false) +```lean -show -- Open some namespaces for the examples. open Lean Lean.Grind Lean.Meta.Grind ``` @@ -115,7 +115,7 @@ example [CommRing α] [NoNatZeroDivisors α] (a b c : α) : ::: :::example "Finite-Field Reasoning" (open := true) -Arithmetic operations on {name}`Fin` overflow, wrapping around to {lean type:="Fin 11"}`0` when the result would be outside the bound. +Arithmetic operations on {name}`Fin` overflow, wrapping around to {lean (type := "Fin 11")}`0` when the result would be outside the bound. {tactic}`grind` can use this fact to prove theorems such as this: ```lean diff --git a/Manual/Grind/Algebra.lean b/Manual/Grind/Algebra.lean index 96ae7785..8b2fbcb3 100644 --- a/Manual/Grind/Algebra.lean +++ b/Manual/Grind/Algebra.lean @@ -108,7 +108,7 @@ tag := "grind-ring-classes" %%% :::paragraph -Users can enable the `ring` solver for their own types by providing instances of the following {tech key:="type class"}[type classes], all in the `Lean.Grind` namespace: +Users can enable the `ring` solver for their own types by providing instances of the following {tech (key := "type class")}[type classes], all in the `Lean.Grind` namespace: * {name Lean.Grind.Semiring}`Semiring` @@ -154,7 +154,7 @@ tag := "grind-ring-field" %%% :::leanSection -```lean (show := false) +```lean -show variable {a b p : α} [Field α] ``` The `ring` solver also has support for {name}`Field`s. @@ -206,7 +206,7 @@ example [CommRing α] [NoNatZeroDivisors α] (a b : α) : grind ``` Without it, the proof fails: -```lean (name := NoNatZero) (error := true) +```lean (name := NoNatZero) +error example [CommRing α] (a b : α) : 2 * a + 2 * b = 0 → b ≠ -a → False := by @@ -262,7 +262,7 @@ example [Field α] {x y z w : α} : You can disable the `ring` solver using the option `grind -ring`. -```lean (error := true) (name := noRing) +```lean +error (name := noRing) example [CommRing α] (x y : α) : x ^ 2 * y = 1 → x * y ^ 2 = y → @@ -313,7 +313,7 @@ Gröbner basis computation can be very expensive. You can limit the number of st :::example "Limiting `ring` Steps" This example cannot be solved by performing at most 100 steps: -```lean (error := true) (name := ring100) +```lean +error (name := ring100) example [CommRing α] [IsCharP α 0] (d t c : α) (d_inv PSO3_inv : α) : d ^ 2 * (d + t - d * t - 2) * (d + t + d * t) = 0 → -d ^ 4 * (d + t - d * t - 2) * diff --git a/Manual/Grind/CaseAnalysis.lean b/Manual/Grind/CaseAnalysis.lean index b1bc61af..e01fcae3 100644 --- a/Manual/Grind/CaseAnalysis.lean +++ b/Manual/Grind/CaseAnalysis.lean @@ -46,7 +46,7 @@ This case analysis is not exhaustive: {tactic}`grind` only recursively splits ca : `splitImp` (default {lean}`false`) :::leanSection - ```lean (show := false) + ```lean -show variable {A : Prop} {B : Sort u} ``` Hypotheses of the form {lean}`A → B` whose antecedent {lean}`A` is *propositional* are split by considering all possibilities for {lean}`A`. @@ -82,7 +82,7 @@ example (c : Bool) (x y : Nat) ``` Disabling `splitIte` causes the proof to fail: -```lean (error := true) (name := noSplitIte) +```lean +error (name := noSplitIte) example (c : Bool) (x y : Nat) (h : (if c then x else y) = 0) : x = 0 ∨ y = 0 := by @@ -109,7 +109,7 @@ right : ¬y = 0 ``` Forbidding all case splitting causes the proof to fail for the same reason: -```lean (error := true) (name := noSplitsAtAll) +```lean +error (name := noSplitsAtAll) example (c : Bool) (x y : Nat) (h : (if c then x else y) = 0) : x = 0 ∨ y = 0 := by @@ -146,7 +146,7 @@ example (c : Bool) (x y : Nat) :::example "Splitting Pattern Matching" Disabling case splitting on pattern matches causes {tactic}`grind` to fail in this example: -```lean (error := true) (name := noSplitMatch) +```lean +error (name := noSplitMatch) example (h : y = match x with | 0 => 1 | _ => 2) : y > 0 := by grind -splitMatch @@ -198,7 +198,7 @@ inductive Not30 : Nat → Prop where ``` By default, {tactic}`grind` cannot show that {lean}`Not30` implies that a number is, in fact, not {lean}`30`: -```lean (error := true) (name := not30fail) +```lean +error (name := not30fail) example : Not30 n → n ≠ 30 := by grind ``` This is because {tactic}`grind` does not consider both cases for {lean}`Not30` diff --git a/Manual/Grind/CongrClosure.lean b/Manual/Grind/CongrClosure.lean index a20d8c27..5bba40ad 100644 --- a/Manual/Grind/CongrClosure.lean +++ b/Manual/Grind/CongrClosure.lean @@ -23,7 +23,7 @@ tag := "congruence-closure" %%% :::leanSection -```lean (show := false) +```lean -show variable {a a' : α} {b b' : β} {f : α → β → γ} ``` {deftech}_Congruence closure_ maintains equivalence classes of terms under the reflexive, symmetric, and transitive closure of “is equal to” _and_ the rule that equal arguments yield equal function results. @@ -33,7 +33,7 @@ If a contradiction is discovered, then the goal can be closed immediately. ::: ::::leanSection -```lean (show := false) +```lean -show variable {t₁ t₂ : α} {h : t₁ = t₂} {a : α} {f : α → β} {g : β → β} ``` :::paragraph @@ -45,7 +45,7 @@ Using the analogy of the shared whiteboard: Soon, whole constellations ({lean}`f a`, {lean}`g (f a)`, …) are connected. 3. If two different constructors of the same inductive type are connected by one or more lines, then a contradiction is discovered and the goal is closed. - For example, equating {lean}`True` and {lean}`False` or {lean type:="Option Nat"}`none` and {lean}`some 1` would be a contradiction. + For example, equating {lean}`True` and {lean}`False` or {lean (type := "Option Nat")}`none` and {lean}`some 1` would be a contradiction. ::: :::: @@ -75,7 +75,7 @@ Because the pair constructor {name}`Prod.mk` obeys congruence, the tuples become # Congruence Closure vs. Simplification ::::leanSection -```lean (show := false) +```lean -show variable {t₁ t₂ : α} {h : t₁ = t₂} {a : α} {f : α → β} {g : β → β} ``` :::paragraph @@ -83,7 +83,7 @@ Congruence closure is a fundamentally different operation from simplification: * {tactic}`simp` _rewrites_ a goal, replacing occurrences of {lean}`t₁` with {lean}`t₂` as soon as it sees {typed}`h : t₁ = t₂`. The rewrite is directional and destructive. -* {tactic}`grind` _accumulates_ equalities bidirectionally. No term is rewritten; instead, both representatives live in the same class. All other engines ({TODO}[techterm] E‑matching, theory solvers, {tech key:="constraint propagation"}[propagation]) can query these classes and add new facts, then the closure updates incrementally. +* {tactic}`grind` _accumulates_ equalities bidirectionally. No term is rewritten; instead, both representatives live in the same class. All other engines ({TODO}[techterm] E‑matching, theory solvers, {tech (key := "constraint propagation")}[propagation]) can query these classes and add new facts, then the closure updates incrementally. This makes congruence closure especially robust in the presence of symmetrical reasoning, mutual recursion, and large nestings of constructors where rewriting would duplicate work. ::: diff --git a/Manual/Grind/ConstraintPropagation.lean b/Manual/Grind/ConstraintPropagation.lean index 54f7bc12..00fa5704 100644 --- a/Manual/Grind/ConstraintPropagation.lean +++ b/Manual/Grind/ConstraintPropagation.lean @@ -31,7 +31,7 @@ Whenever a term is added to one of those buckets, {tactic}`grind` fires dozens o : Boolean connectives ::::leanSection - ```lean (show := false) + ```lean -show variable {A B : Prop} ``` :::paragraph @@ -50,7 +50,7 @@ Whenever a term is added to one of those buckets, {tactic}`grind` fires dozens o : Projections :::leanSection - ```lean (show := false) + ```lean -show variable {x x' : α} {y y' : β} {h : (x, y) = (x', y')} {a : α} ``` @@ -60,7 +60,7 @@ Whenever a term is added to one of those buckets, {tactic}`grind` fires dozens o : Casts :::leanSection - ```lean (show := false) + ```lean -show variable {h : α = β} {a : α} ``` Any term {typed}`cast h a : β` is equated with {typed}`a : α` immediately (using {tech}[heterogeneous equality]). @@ -70,7 +70,7 @@ Whenever a term is added to one of those buckets, {tactic}`grind` fires dozens o ::::keepEnv :::leanSection - ```lean (show := false) + ```lean -show variable {α : Type u} {β : Type v} {a : α} {b : β} structure S α β where x : α @@ -105,7 +105,7 @@ Whenever a term is added to one of those buckets, {tactic}`grind` fires dozens o example : p = ⟨p.1, p.2⟩ := by grind ``` Definitional reduction is propagated, so {lean}`(a, b).1` is equated with {lean}`a`. - The {tech key:="η-equivalence"}[η-equality] rule for structures is not automatically used, so if {lean}`p` is an instance of a {tech}[structure] {lean}`S` with two fields, then {lean}`p` is not equated with {lean type:="S α β"}`⟨p.1, p.2⟩`. + The {tech (key := "η-equivalence")}[η-equality] rule for structures is not automatically used, so if {lean}`p` is an instance of a {tech}[structure] {lean}`S` with two fields, then {lean}`p` is not equated with {lean (type := "S α β")}`⟨p.1, p.2⟩`. However, tagging {name}`S` with {attrs}`@[grind ext]` causes the {tech}[E-matching] engine to prove these goals. ::: :::: @@ -124,10 +124,10 @@ Each follows the same skeleton. {deftech}_Upward propagation_ derives facts about a term from facts about sub-terms, while {deftech}_downward propagation_ derives facts about sub-terms from facts about a term. ::: -```lean (show := false) +```lean -show namespace ExamplePropagators ``` -```lean (keep := false) +```lean -keep /-- Propagate equalities *upwards* for conjunctions. -/ builtin_grind_propagator propagateAndUp ↑And := fun e => do @@ -168,7 +168,7 @@ builtin_grind_propagator propagateAndDown ↓And := pushEqTrue b <| mkApp3 (mkConst ``Grind.eq_true_of_and_eq_true_right) a b h ``` -```lean (show := false) +```lean -show end ExamplePropagators ``` @@ -177,11 +177,11 @@ end ExamplePropagators Other frequently‑triggered propagators follow the same pattern: ::::leanSection -```lean (show := false) +```lean -show variable {A B : Prop} {a b : α} ``` -:::table (header := true) +:::table +header * * Propagator * Handles @@ -243,7 +243,7 @@ Setting the option {option}`trace.grind.eqc` to {lean}`true` causes {tactic}`gri This section should be uncommented when the command is implemented: -```lean (show := false) +```lean -show -- Test to ensure that this section is uncommented when the command is implemented /-- error: elaboration function for 'Lean.Parser.«command_Grind_propagator___(_):=_»' has not been implemented @@ -265,7 +265,7 @@ The full equivalence classes are displayed automatically _only when {tactic}`gri :::example "Identifying Missing Facts" In this example, {tactic}`grind` fails: -```lean (error := true) (name := missing) +```lean +error (name := missing) example : x = y ∧ y = z → w = x ∨ w = v → diff --git a/Manual/Grind/Cutsat.lean b/Manual/Grind/Cutsat.lean index da1f9563..062c8184 100644 --- a/Manual/Grind/Cutsat.lean +++ b/Manual/Grind/Cutsat.lean @@ -81,7 +81,7 @@ example (a b : Int) : Without `cutsat`, {tactic}`grind` cannot prove the statement: -```lean (error := true) (name := noCutsat) +```lean +error (name := noCutsat) example (a b : Int) : 2 ∣ a + 1 → 2 ∣ b + a → @@ -125,7 +125,7 @@ example {x y : Int} : ``` Because it uses the rational solution, {tactic}`grind` fails to refute the negation of the goal when `+qlia` is specified: -```lean (error := true) (name := withqlia) +```lean +error (name := withqlia) example {x y : Int} : 27 ≤ 13 * x + 11 * y → 13 * x + 11 * y ≤ 30 → @@ -160,7 +160,7 @@ The solver currently does support nonlinear constraints, and treats nonlinear te ::::example "Nonlinear Terms" (open := true) `cutsat` fails to prove this theorem: -```lean (error := true) (name := nonlinear) +```lean +error (name := nonlinear) example (x : Int) : x * x ≥ 0 := by grind ``` @@ -178,7 +178,7 @@ h : x * x + 1 ≤ 0 From the perspective of `cutsat`, it is equivalent to: -```lean (error := true) (name := nonlinear2) +```lean +error (name := nonlinear2) example {y : Int} (x : Int) : y ≥ 0 := by grind ``` @@ -197,7 +197,7 @@ h : x * x + 1 ≤ 0 :::paragraph This can be seen by setting the option {option}`trace.grind.cutsat.assert` to {lean}`true`, which traces all constraints processed by `cutsat`. -```lean (error := true) (name := cutsatDiag) +```lean +error (name := cutsatDiag) example (x : Int) : x*x ≥ 0 := by set_option trace.grind.cutsat.assert true in grind @@ -257,9 +257,9 @@ example (f : Int → Int) (x y : Int) : f (x + y) = 0 := by grind ``` -Consequently `x = x + y`, so `f x = f (x + y)` by {tech key:="congruence closure"}[congruence]. +Consequently `x = x + y`, so `f x = f (x + y)` by {tech (key := "congruence closure")}[congruence]. Without model-based theory combination, the proof gets stuck: -```lean (error := true) (name := noMbtc) +```lean +error (name := noMbtc) example (f : Int → Int) (x y : Int) : f x = 0 → 0 ≤ y → y ≤ 1 → y ≠ 1 → @@ -326,7 +326,7 @@ example (a b c : UInt64) : a ≤ 2 → b ≤ 3 → c - a - b = 0 → c ≤ 5 := # Implementation Notes ::::leanSection -```lean (show := false) +```lean -show variable {x y : Int} ``` diff --git a/Manual/Grind/EMatching.lean b/Manual/Grind/EMatching.lean index 03362d8d..39b6d9ac 100644 --- a/Manual/Grind/EMatching.lean +++ b/Manual/Grind/EMatching.lean @@ -27,7 +27,7 @@ It is especially effective when combined with {tech}[congruence closure], enabli E-matching adds new facts to the metaphorical whiteboard, based on an index of theorems. When the whiteboard contains terms that match the index, the E-matching engine instantiates the corresponding theorems, and the resulting terms can feed further rounds of {tech}[congruence closure], {tech}[constraint propagation], and theory-specific solvers. -Each fact added to the whiteboard by E-matching is referred to as an {deftech key:="e-matching instance"}_instance_. +Each fact added to the whiteboard by E-matching is referred to as an {deftech (key := "e-matching instance")}_instance_. Annotating theorems for E-matching, thus adding them to the index, is essential for enabling {tactic}`grind` to make effective use of a library. In addition to user-specified theorems, {tactic}`grind` uses automatically generated equations for {keywordOf Lean.Parser.Term.match}`match`-expressions as E-matching theorems. @@ -59,7 +59,7 @@ theorem gf (x : Nat) : g (f x) = x := by simp [f, g] ``` -```lean (show := false) +```lean -show variable {x a b : Nat} ``` The theorem {lean}`gf` asserts that {lean}`g (f x) = x` for all natural numbers {lean}`x`. @@ -108,7 +108,7 @@ the theorem `gf` will not be instantiated because the goal does not even contain the function symbol `g`. In this example, {tactic}`grind` fails because the pattern is too restrictive: the goal does not contain the function symbol {lean}`g`. -```lean (error := true) (name := restrictivePattern) +```lean +error (name := restrictivePattern) example (h₁ : f b = a) (h₂ : f c = a) : b = c := by grind ``` @@ -175,7 +175,7 @@ example {a b c d} : R a b → R b c → R c d → R a d := by grind ``` -```lean (show := false) +```lean -show variable {x y z a b c d : Int} ``` @@ -284,7 +284,7 @@ Ordinarily, the {attr}`grind` attribute does not consider the `=` symbol when ge ::: :::example "The `@[grind ←=]` Attribute" -```lean (show := false) +```lean -show variable {α} {a b : α} [Inv α] ``` When attempting to prove that {lean}`a⁻¹ = b`, {tactic}`grind` uses {name}`inv_eq` due to the {attrs}`@[grind ←=]` annotation. @@ -304,7 +304,7 @@ ext ::: :::example "The `@[grind ext]` Attribute" -{tactic}`grind` does not automatically apply the {tech key:="η-equivalence"}[η-equality] rule for structures. +{tactic}`grind` does not automatically apply the {tech (key := "η-equivalence")}[η-equality] rule for structures. {lean}`Point` is a structure with two fields: ```lean structure Point where @@ -312,7 +312,7 @@ structure Point where y : Int ``` By default, {tactic}`grind` can't solve goals like this one: -```lean (error := true) (name := noExt) +```lean +error (name := noExt) example (p : Point) : p = ⟨p.x, p.y⟩ := by grind ``` ```leanOutput noExt @@ -330,7 +330,7 @@ This kind of goal may come up when proving theorems like the fact that swapping ```lean def Point.swap (p : Point) : Point := ⟨p.y, p.x⟩ ``` -```lean (error := true) (name := noExt') +```lean +error (name := noExt') theorem swap_swap_eq_id : Point.swap ∘ Point.swap = id := by unfold Point.swap grind @@ -427,7 +427,7 @@ Thus, `q x` is selected as the pattern. ::: :::example "Backward Pattern Generation" (open := true) -```lean (show := false) +```lean -show axiom p : Nat → Nat axiom q : Nat → Nat ``` @@ -444,7 +444,7 @@ h₂: [p (#1 + 1)] ::: :::example "Bidirectional Equality Pattern Generation" (open := true) -```lean (show := false) +```lean -show axiom p : Nat → Nat axiom q : Nat → Nat ``` @@ -464,7 +464,7 @@ h₃: [p (#1 + 1)] ::: :::example "Patterns from Conclusion and Hypotheses" (open := true) -```lean (show := false) +```lean -show axiom p : Nat → Nat axiom q : Nat → Nat ``` @@ -482,12 +482,12 @@ h₄: [p (#2 + 2), q #1] ::: :::example "Failing Backward Pattern Generation" (open := true) -```lean (show := false) +```lean -show axiom p : Nat → Nat axiom q : Nat → Nat ``` In this example, pattern generation fails because the theorem's conclusion doesn't mention the the argument `y`. -```lean (name := h5) (error := true) +```lean (name := h5) +error @[grind? ←] theorem h₅ (w : p x = q y) : p (x + 2) = 7 := sorry ``` ```leanOutput h5 @@ -496,7 +496,7 @@ In this example, pattern generation fails because the theorem's conclusion doesn ::: :::example "Left-to-Right Generation" (open := true) -```lean (show := false) +```lean -show axiom p : Nat → Nat axiom q : Nat → Nat ``` @@ -522,7 +522,7 @@ h₆: [q (#3 + 2), p (#2 + 2)] tag := "grind-limits" %%% -E-matching can generate an unbounded number of theorem {tech key:="e-matching instance"}[instances]. +E-matching can generate an unbounded number of theorem {tech (key := "e-matching instance")}[instances]. For the sake of both efficiency and termination, {tactic}`grind` limits the number of times that E-matching can run using two mechanisms: : Generations @@ -540,7 +540,7 @@ For the sake of both efficiency and termination, {tactic}`grind` limits the numb :::example "Too Many Instances" (open := true) -E-matching can generate too many theorem {tech key:="e-matching instance"}[instances]. +E-matching can generate too many theorem {tech (key := "e-matching instance")}[instances]. Some patterns may even generate an unbounded number of instances. In this example, {name}`s_eq` is added to the index with the pattern `s x`: @@ -559,7 +559,7 @@ In particular, {lean}`s_eq` is instantiated with a new {lean}`Nat` in each of th First, {tactic}`grind` instantiates {lean}`s_eq` with `x := 0`, which generates the term {lean}`s 1`. This matches the pattern `s x`, and is thus used to instantiate {lean}`s_eq` with `x := 1`, which generates the term {lean}`s 2`, and so on until the round limit is reached. -```lean (error := true) (name := ematchUnbounded) +```lean +error (name := ematchUnbounded) example : s 0 > 0 := by grind ``` @@ -588,7 +588,7 @@ h : s 0 = 0 ``` Increasing the round limit to 20 causes E-matching to terminate due to the default generation limit of 8: -```lean (error := true) (name := ematchUnbounded2) +```lean +error (name := ematchUnbounded2) example : s 0 > 0 := by grind (ematch := 20) ``` @@ -634,7 +634,7 @@ def iota : Nat → List Nat The fact that {lean}`(iota 20).length > 10` can be proven by repeatedly instantiating {lean}`iota_succ` and {lean}`List.length_cons`. However, {tactic}`grind` does not succeed: -```lean (error := true) (name := biggerGrindLimits) +```lean +error (name := biggerGrindLimits) example : (iota 20).length > 10 := by grind ``` @@ -727,7 +727,7 @@ gt1.match_1.congr_eq_2.{u_1} (motive : Nat → Sort u_1) (x✝ : Nat) (h_1 : Uni Disabling the use of matcher function equations causes the proof to fail: -```lean (error := true) (name := noMatchEqs) +```lean +error (name := noMatchEqs) example (x y : Nat) : x = y + 1 → 0 < match x with diff --git a/Manual/Grind/ExtendedExamples/IfElseNorm.lean b/Manual/Grind/ExtendedExamples/IfElseNorm.lean index c371a013..91050577 100644 --- a/Manual/Grind/ExtendedExamples/IfElseNorm.lean +++ b/Manual/Grind/ExtendedExamples/IfElseNorm.lean @@ -25,7 +25,7 @@ open Lean.Grind tag := "grind-if-then-else-norm" %%% -```lean (show := false) +```lean -show open Std ``` @@ -209,7 +209,7 @@ namespace IfExpr :::keepEnv -```lean (error := true) (name := failed_to_show_termination) +```lean +error (name := failed_to_show_termination) def normalize (assign : Std.HashMap Nat Bool) : IfExpr → IfExpr | lit b => lit b @@ -304,7 +304,7 @@ termination_by e => e.normSize Now it's time to prove some properties of this function. We're just going to package together all the properties we want: -```lean (keep := false) +```lean -keep theorem normalize_spec (assign : Std.HashMap Nat Bool) (e : IfExpr) : (normalize assign e).normalized @@ -381,7 +381,7 @@ we can simply switch that implementation detail out, without having to touch the ::: -```lean (show := false) +```lean -show -- We have to repeat these annotations because we've rolled back the environment to before we defined `normalize`. attribute [local grind] normalized hasNestedIf hasConstantIf hasRedundantIf @@ -425,6 +425,6 @@ you can find the whole file [here](https://github.com/leanprover/lean4/blob/mast or in fact [play with it with no installation](https://live.lean-lang.org/#project=lean-nightly&url=https%3A%2F%2Fraw.githubusercontent.com%2Fleanprover%2Flean4%2Frefs%2Fheads%2Fmaster%2Ftests%2Flean%2Frun%2Fgrind_ite.lean) in the Live Lean editor. -```lean (show := false) +```lean -show end IfExpr ``` diff --git a/Manual/Grind/ExtendedExamples/IndexMap.lean b/Manual/Grind/ExtendedExamples/IndexMap.lean index 1c2b120b..0e6aea8d 100644 --- a/Manual/Grind/ExtendedExamples/IndexMap.lean +++ b/Manual/Grind/ExtendedExamples/IndexMap.lean @@ -322,7 +322,7 @@ Let's add this fact: ``` ::::leanSection -```lean (show := false) +```lean -show variable {α : Type u} [BEq α] [Hashable α] ``` :::paragraph diff --git a/Manual/Grind/ExtendedExamples/Integration.lean b/Manual/Grind/ExtendedExamples/Integration.lean index a634fc59..7a8395b4 100644 --- a/Manual/Grind/ExtendedExamples/Integration.lean +++ b/Manual/Grind/ExtendedExamples/Integration.lean @@ -63,7 +63,7 @@ grind_pattern trig_identity => sin x Note here we use *two* different patterns for the same theorem, so the theorem is instantiated even if {tactic}`grind` sees just one of these functions. If we preferred to more conservatively instantiate the theorem only when both {name}`sin` and {name}`cos` are present, we could have used a multi-pattern: -```lean (keep := false) +```lean -keep grind_pattern trig_identity => cos x, sin x ``` @@ -71,7 +71,7 @@ For this example, either approach will work. ::: ::::leanSection -```lean (show := false) +```lean -show variable {x : R} ``` @@ -103,7 +103,7 @@ example (f : R → Nat) : grind ``` -```lean (show := false) +```lean -show variable (f : R → Nat) (n : Nat) ``` diff --git a/Manual/IO.lean b/Manual/IO.lean index 6a92ef5f..d542cf69 100644 --- a/Manual/IO.lean +++ b/Manual/IO.lean @@ -40,7 +40,7 @@ Finally, a basic principle of Lean's logic is that functions are _functions_ tha Including side effects such as console I/O, arbitrary mutable state, or random number generation would violate this principle. :::::keepEnv -```lean (show := false) +```lean -show /-- A type -/ axiom α : Type ``` @@ -56,7 +56,7 @@ At run time, the compiler produces ordinary code. # Logical Model :::::keepEnv -```lean (show := false) +```lean -show /-- A type -/ axiom α : Type ``` @@ -108,7 +108,7 @@ Both {lean}`IO` and {lean}`BaseIO` are instances of {lean}`EIO`, in which the ty {lean}`IO` is defined as {lean}`EIO IO.Error`, while {lean}`BaseIO` is defined as {lean}`EIO Empty`. In some circumstances, such as bindings to non-Lean libraries, it can be convenient to use {lean}`EIO` with a custom error type, which ensures that errors are handled at the boundaries between these and other {lean}`IO` actions. -```lean (show := false) +```lean -show -- Check claim in preceding paragraph example : IO = EIO IO.Error := rfl example : BaseIO = EIO Empty := rfl @@ -517,7 +517,7 @@ There are 90 four-digit palindromes. {docstring RandomGen} -{docstring StdGen (hideStructureConstructor := true) (hideFields := true)} +{docstring StdGen +hideStructureConstructor +hideFields} {docstring stdRange} diff --git a/Manual/IO/Files.lean b/Manual/IO/Files.lean index 2adadacc..80d653b1 100644 --- a/Manual/IO/Files.lean +++ b/Manual/IO/Files.lean @@ -151,7 +151,7 @@ Starting contents: 'AABAABCDAB' Count: 5 Contents: '!!B!!BCD!B' ``` -```stderr (show := false) +```stderr -show ``` Afterwards, the file contains: @@ -189,7 +189,7 @@ Avoid hard-coding these rules. There is an instance of the {lean}`Div` type class for {name System.FilePath}`FilePath` which allows the slash operator to be used to concatenate paths. -{docstring System.FilePath (allowMissing := true)} +{docstring System.FilePath +allowMissing} {docstring System.mkFilePath} @@ -245,7 +245,7 @@ Some operations on paths consult the filesystem. {docstring System.FilePath.walkDir} -{docstring IO.AccessRight (allowMissing := true)} +{docstring IO.AccessRight +allowMissing} {docstring IO.AccessRight.flags} diff --git a/Manual/IO/Ref.lean b/Manual/IO/Ref.lean index b3ae806c..f33a6010 100644 --- a/Manual/IO/Ref.lean +++ b/Manual/IO/Ref.lean @@ -59,7 +59,7 @@ Here, {lean}`ST` is analogous to {lean}`BaseIO` rather than {lean}`IO`, because {docstring runEST} -{docstring ST.Ref (hideFields := true)} +{docstring ST.Ref +hideFields} {docstring ST.mkRef} diff --git a/Manual/IO/Threads.lean b/Manual/IO/Threads.lean index e420fc49..e0429d44 100644 --- a/Manual/IO/Threads.lean +++ b/Manual/IO/Threads.lean @@ -25,7 +25,7 @@ tag := "concurrency" %%% :::leanSection -```lean (show := false) +```lean -show variable {α : Type u} ``` @@ -44,18 +44,18 @@ Similarly, {name}`BaseIO.asTask` and {name}`EIO.asTask` create tasks in other {n These tasks may have side effects, and can communicate with other tasks. ::: -When the last reference to a task is dropped it is {deftech key:="cancel"}_cancelled_. +When the last reference to a task is dropped it is {deftech (key := "cancel")}_cancelled_. Pure tasks created with {name}`Task.spawn` are terminated upon cancellation. Tasks spawned with {name}`IO.asTask`, {name}`EIO.asTask`, or {name}`BaseIO.asTask` continue executing and must explicitly check for cancellation using {name}`IO.checkCanceled`. Tasks may be explicitly cancelled using {name}`IO.cancel`. The Lean runtime maintains a thread pool for running tasks. -The size of the thread pool is determined by the environment variable {envVar (def := true)}`LEAN_NUM_THREADS` if it is set, or by the number of logical processors on the current machine otherwise. +The size of the thread pool is determined by the environment variable {envVar +def}`LEAN_NUM_THREADS` if it is set, or by the number of logical processors on the current machine otherwise. The size of the thread pool is not a hard limit; in certain situations it may be exceeded to avoid deadlocks. By default, these threads are used to run tasks; each task has a {deftech}_priority_ ({name}`Task.Priority`), and higher-priority tasks take precedence over lower-priority tasks. Tasks may also be assigned to dedicated threads by spawning them with a sufficiently high priority. -{docstring Task (label := "type") (hideStructureConstructor := true) (hideFields := true)} +{docstring Task (label := "type") +hideStructureConstructor +hideFields} # Creating Tasks @@ -162,7 +162,7 @@ Pure tasks are terminated automatically upon cancellation. # Promises Promises represent a value that will be supplied in the future. -Supplying the value is called {deftech key:="resolve"}_resolving_ the promise. +Supplying the value is called {deftech (key := "resolve")}_resolving_ the promise. Once created, a promise can be stored in a data structure or passed around like any other value, and attempts to read from it will block until it is resolved. @@ -216,7 +216,7 @@ The types and functions in this section are available after importing {module}`S :::leanSection -```lean (show := false) +```lean -show variable {m : Type → Type v} {α : Type} [MonadLiftT BaseIO m] [Inhabited α] ``` Synchronous channels can also be read using {keywordOf Lean.Parser.Term.doFor}`for` loops. @@ -226,7 +226,7 @@ In particular, there is an instance of type {inst}`ForIn m (Std.Channel.Sync α) The types and functions in this section are available after importing {module}`Std.Sync.Mutex`. -{docstring Std.Mutex (label := "type") (hideStructureConstructor := true) (hideFields := true)} +{docstring Std.Mutex (label := "type") +hideStructureConstructor +hideFields} {docstring Std.Mutex.new} diff --git a/Manual/Interaction.lean b/Manual/Interaction.lean index 28eef489..011856a9 100644 --- a/Manual/Interaction.lean +++ b/Manual/Interaction.lean @@ -30,7 +30,7 @@ By convention, commands that are intended for interactive use rather than as par Information from Lean commands is available in the {deftech}_message log_, which accumulates output from the {tech}[elaborator]. Each entry in the message log is associated with a specific source range and has a {deftech}_severity_. -There are three severities: {lean type:="Lean.MessageSeverity"}`information` is used for messages that do not indicate a problem, {lean type:="Lean.MessageSeverity"}`warning` indicates a potential problem, and {lean type:="Lean.MessageSeverity"}`error` indicates a definite problem. +There are three severities: {lean (type := "Lean.MessageSeverity")}`information` is used for messages that do not indicate a problem, {lean (type := "Lean.MessageSeverity")}`warning` indicates a potential problem, and {lean (type := "Lean.MessageSeverity")}`error` indicates a definite problem. For interactive commands, results are typically returned as informational messages that are associated with the command's leading keyword. # Evaluating Terms @@ -56,11 +56,11 @@ Use {keywordOf Lean.reduceCmd}`#reduce` to instead reduce terms using the reduct ::: -{keywordOf Lean.Parser.Command.eval}`#eval` always {tech key:="elaborator"}[elaborates] and compiles the provided term. +{keywordOf Lean.Parser.Command.eval}`#eval` always {tech (key := "elaborator")}[elaborates] and compiles the provided term. It then checks whether the term transitively depends on any uses of {lean}`sorry`, in which case evaluation is terminated unless the command was invoked as {keywordOf Lean.Parser.Command.eval}`#eval!`. This is because compiled code may rely on compile-time invariants (such as array lookups being in-bounds) that are ensured by proofs of suitable statements, and running code that contains incomplete proofs (or uses of {lean}`sorry` that “prove” incorrect statements) can cause Lean itself to crash. -```lean (show := false) +```lean -show section variable (m : Type → Type) open Lean.Elab.Command (CommandElabM) @@ -84,7 +84,7 @@ Auxiliary definitions or other environment modifications that result from elabor If the term is an action in a metaprogramming monad, then changes made to the environment by running the monadic action are preserved. ::: -```lean (show := false) +```lean -show end ``` @@ -96,7 +96,7 @@ Setting {option}`eval.pp` to {lean}`false` disables the use of {name Lean.ToExpr :::example "Displaying Output" {keywordOf Lean.Parser.Command.eval}`#eval` cannot display functions: -```lean (name := funEval) (error := true) +```lean (name := funEval) +error #eval fun x => x + 1 ``` ```leanOutput funEval @@ -119,7 +119,7 @@ Quadrant.nw The derived instance is not saved. Disabling {option}`eval.derive.repr` causes {keywordOf Lean.Parser.Command.eval}`#eval` to fail: -```lean (name := quadEval2) (error := true) +```lean (name := quadEval2) +error set_option eval.derive.repr false #eval Quadrant.nw ``` @@ -406,7 +406,7 @@ intersperse.eq_unfold.{u_1} : :::example "Scope Information" The {keywordOf Lean.Parser.Command.where}`#where` command displays all the modifications made to the current {tech}[section scope], both in the current scope and in the scopes in which it is nested. -```lean (fresh := true) (name := scopeInfo) +```lean +fresh (name := scopeInfo) section open Nat @@ -498,7 +498,7 @@ The behavior of the {keywordOf Lean.guardMsgsCmd}`#guard_msgs` command can be sp These configuration options are provided in parentheses, separated by commas. ::: -::::syntax Lean.guardMsgsSpecElt (title := "Specifying {keyword}`#guard_msgs` Behavior") (open := false) +::::syntax Lean.guardMsgsSpecElt (title := "Specifying {keyword}`#guard_msgs` Behavior") -open ```grammar $_:guardMsgsFilter @@ -513,7 +513,7 @@ ordering := $_ There are three kinds of options for {keywordOf Lean.guardMsgsCmd}`#guard_msgs`: filters, whitespace comparison strategies, and orderings. :::: -:::syntax Lean.guardMsgsFilter (title := "Output Filters for {keyword}`#guard_msgs`") (open := false) +:::syntax Lean.guardMsgsFilter (title := "Output Filters for {keyword}`#guard_msgs`") -open ```grammar $[drop]? all ``` @@ -532,7 +532,7 @@ $[drop]? error ::: -:::syntax Lean.guardMsgsWhitespaceArg (title := "Whitespace Comparison for `#guard_msgs`") (open := false) +:::syntax Lean.guardMsgsWhitespaceArg (title := "Whitespace Comparison for `#guard_msgs`") -open ```grammar exact ``` @@ -577,7 +577,7 @@ def Tree.big (n : Nat) : Tree Nat := ``` However, it can be difficult to spot where test failures come from when the output is large: -```lean (error := true) (name := bigMsg) +```lean +error (name := bigMsg) set_option guard_msgs.diff false /-- info: Tree.branches @@ -616,7 +616,7 @@ info: Tree.branches ``` Enabling {option}`guard_msgs.diff` highlights the differences instead, making the error more apparent: -```lean (error := true) (name := bigMsg') +```lean +error (name := bigMsg') set_option guard_msgs.diff true in /-- info: Tree.branches diff --git a/Manual/Interaction/FormatRepr.lean b/Manual/Interaction/FormatRepr.lean index fa5534a0..a9d9773b 100644 --- a/Manual/Interaction/FormatRepr.lean +++ b/Manual/Interaction/FormatRepr.lean @@ -48,7 +48,7 @@ tag := "Format" ::::leanSection -```lean show:=false +```lean -show open Std (Format) open Std.Format variable {str : String} {indent : String} {n : Nat} @@ -112,7 +112,7 @@ def lst : Format := parenSeq nums where nums := [1, 2, 3, 4, 5].map (text s!"{·}") ``` -```lean show := false +```lean -show -- check statement in next paragraph /-- info: 120 -/ #check_msgs in @@ -399,10 +399,10 @@ tag := "format-empty" The empty string does not have a single unique representative in {name}`Std.Format`. All of the following represent the empty string: -* {lean type:="Std.Format"}`.nil` -* {lean type:="Std.Format"}`.text ""` -* {lean type:="Std.Format"}`.text "" ++ .nil` -* {lean type:="Std.Format"}`.nil ++ .text ""` +* {lean (type := "Std.Format")}`.nil` +* {lean (type := "Std.Format")}`.text ""` +* {lean (type := "Std.Format")}`.text "" ++ .nil` +* {lean (type := "Std.Format")}`.nil ++ .text ""` Use {name}`Std.Format.isEmpty` to check whether a document contains zero characters, and {name}`Std.Format.isNil` to specifically check whether it is the constructor {lean}`Std.Format.nil`. ::: @@ -563,12 +563,12 @@ In some cases, however, it's necessary to write an instance by hand: * The derived {name}`Repr` instance for structures uses {tech}[structure instance] notation. A hand-written instance can use the constructor's name explicitly or use {tech}[anonymous constructor syntax]. -```lean (show := false) +```lean -show /-- info: Std.HashSet.ofList [0, 3, 5] -/ #check_msgs in #eval IO.println <| repr (({} : Std.HashSet Nat).insert 3 |>.insert 5 |>.insert 0) ``` -```lean (show := false) (keep := false) +```lean -show -keep structure S where x : Nat y : Nat @@ -743,7 +743,7 @@ protected def AddExpr.reprPrec : AddExpr → Nat → Std.Format instance : Repr AddExpr := ⟨AddExpr.reprPrec⟩ ``` -```lean (show := false) +```lean -show -- Test that the guidelines provided for infix operators match Lean's own pretty printer /-- info: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + @@ -788,7 +788,7 @@ The latter is defined after the former and is thus selected when possible; howev If the {name}`Repr` instance for a type never generates spaces or newlines, then it should have a {name}`ReprAtom` instance. Lean has {name}`ReprAtom` instances for types such as {name}`String`, {name}`UInt8`, {name}`Nat`, {name}`Char`, and {name}`Bool`. -```lean (show := false) +```lean -show open Lean Elab Command in #eval show CommandElabM Unit from for x in [``String, ``UInt8, ``Nat, ``Char, ``Bool] do diff --git a/Manual/Intro.lean b/Manual/Intro.lean index ebb927a4..c6f664b4 100644 --- a/Manual/Intro.lean +++ b/Manual/Intro.lean @@ -79,7 +79,7 @@ def hello : IO Unit := IO.println "Hello, world!" Compiler output (which may be errors, warnings, or just information) is shown both in the code and separately: -```lean (name := output) (error := true) +```lean (name := output) +error #eval s!"The answer is {2 + 2}" theorem bogus : False := by sorry diff --git a/Manual/Language/Functions.lean b/Manual/Language/Functions.lean index 3a8698c0..73639561 100644 --- a/Manual/Language/Functions.lean +++ b/Manual/Language/Functions.lean @@ -78,7 +78,7 @@ def AllNonZero (xs : Array Nat) : Prop := :::keepEnv This is because the elaborator for array access requires a proof that the index is in bounds. The non-dependent version of the statement does not introduce this assumption: -```lean (error := true) (name := nondepOops) +```lean +error (name := nondepOops) def AllNonZero (xs : Array Nat) : Prop := (i : Nat) → (i < xs.size) → xs[i] ≠ 0 ``` @@ -115,7 +115,7 @@ example : In Lean's type theory, functions are created using {deftech}_function abstractions_ that bind a variable. {margin}[In various communities, function abstractions are also known as _lambdas_, due to Alonzo Church's notation for them, or _anonymous functions_ because they don't need to be defined with a name in the global environment.] -When the function is applied, the result is found by {tech key:="β"}[β-reduction]: substituting the argument for the bound variable. +When the function is applied, the result is found by {tech (key := "β")}[β-reduction]: substituting the argument for the bound variable. In compiled code, this happens strictly: the argument must already be a value. When type checking, there are no such restrictions; the equational theory of definitional equality allows β-reduction with any term. @@ -157,7 +157,7 @@ Function extensionality is instead made available as a reasoning principle that ::::keepEnv -```lean (show := false) +```lean -show axiom α : Type axiom β : α → Type axiom f : (x : α) → β x diff --git a/Manual/Language/InductiveTypes.lean b/Manual/Language/InductiveTypes.lean index c5b9cf8b..b3bab19c 100644 --- a/Manual/Language/InductiveTypes.lean +++ b/Manual/Language/InductiveTypes.lean @@ -77,14 +77,14 @@ The signature may specify any parameters, modulo the well-formedness requirement If no signature is provided, then the constructor's type is inferred by inserting sufficient implicit parameters to construct a well-formed return type. The new inductive type's name is defined in the {tech}[current namespace]. -Each constructor's name is in the inductive type's namespace.{index subterm:="of inductive type"}[namespace] +Each constructor's name is in the inductive type's namespace.{index (subterm := "of inductive type")}[namespace] ## Parameters and Indices %%% tag := "inductive-datatypes-parameters-and-indices" %%% -Type constructors may take two kinds of arguments: {deftech}_parameters_ {index subterm:="of inductive type"}[parameter] and {deftech key:="index"}_indices_.{index subterm:="of inductive type"}[index] +Type constructors may take two kinds of arguments: {deftech}_parameters_ {index (subterm := "of inductive type")}[parameter] and {deftech (key := "index")}_indices_.{index (subterm := "of inductive type")}[index] Parameters must be used consistently in the entire definition; all occurrences of the type constructor in each constructor in the declaration must take precisely the same argument. Indices may vary among the occurrences of the type constructor. All parameters must precede all indices in the type constructor's signature. @@ -99,7 +99,7 @@ An index could have been a parameter if all of its type dependencies are themsel Indices can be seen as defining a _family_ of types. Each choice of indices selects a type from the family, which has its own set of available constructors. -Type constructors with indices are said to specify {deftech}_indexed families_ {index subterm:="of types"}[indexed family] of types. +Type constructors with indices are said to specify {deftech}_indexed families_ {index (subterm := "of types")}[indexed family] of types. ## Example Inductive Types %%% @@ -121,7 +121,7 @@ Empty inductive types are not useless; they can be used to indicate unreachable inductive No : Prop where ``` -```lean (show := false) (keep := false) +```lean -show -keep theorem no_is_false : No = False := by apply propext constructor <;> intro h <;> cases h @@ -175,7 +175,7 @@ The signature inferred for {lean}`Yes.intro` is: Yes.intro : Yes ``` -```lean (show := false) (keep := false) +```lean -show -keep theorem yes_is_true : Yes = True := by apply propext constructor <;> intros <;> constructor @@ -185,7 +185,7 @@ theorem yes_is_true : Yes = True := by ::::example "A type with parameter and index" (keep := true) :::keepEnv -```lean (show:=false) +```lean -show universe u axiom α : Type u axiom b : Bool @@ -207,7 +207,7 @@ example : EvenOddList String true := ``` This example is not well typed because there are three entries in the list: -```lean (error := true) (name := evenOddOops) +```lean +error (name := evenOddOops) example : EvenOddList String true := .cons "a" (.cons "b" (.cons "c" .nil)) ``` @@ -221,7 +221,7 @@ but is expected to have type ``` :::keepEnv -```lean (show:=false) +```lean -show universe u axiom α : Type u axiom b : Bool @@ -232,7 +232,7 @@ In this declaration, {lean}`α` is a {tech}[parameter], because it is used consi ::: -```lean (show:=false) (keep:=false) +```lean -show -keep def EvenOddList.length : EvenOddList α b → Nat | .nil => 0 | .cons _ xs => xs.length + 1 @@ -258,7 +258,7 @@ inductive Either (α : Type u) (β : Type v) : Type (max u v) where ``` In this version, there are two types named `α` that might not be identical: -```lean (name := Either') (error := true) +```lean (name := Either') +error inductive Either' (α : Type u) (β : Type v) : Type (max u v) where | left : {α : Type u} → {β : Type v} → α → Either' α β | right : β → Either' α β @@ -306,7 +306,7 @@ Constructors can be invoked anonymously by enclosing their explicit arguments in ::::example "Anonymous constructors" :::keepEnv -```lean (show:=false) +```lean -show axiom α : Type ``` The type {lean}`AtLeastOne α` is similar to `List α`, except there's always at least one element present: @@ -366,7 +366,7 @@ tag := "inductive-types-runtime-special-support" Not every inductive type is represented as indicated here—some inductive types have special support from the Lean compiler: :::keepEnv -```lean (show := false) +```lean -show axiom α : Prop ``` @@ -544,7 +544,7 @@ end example : EvenList String := .cons "x" (.cons "y" .nil) example : OddList String := .cons "x" (.cons "y" (.cons "z" .nil)) ``` -```lean (error := true) (name := evenOddMut) +```lean +error (name := evenOddMut) example : OddList String := .cons "x" (.cons "y" .nil) ``` ```leanOutput evenOddMut @@ -575,7 +575,7 @@ The constructors of each inductive type may mention the other type constructors :::example "Mutual inductive type constructors may not mention each other" These inductive types are not accepted by Lean: -```lean (error:=true) (name := mutualNoMention) +```lean +error (name := mutualNoMention) mutual inductive FreshList (α : Type) (r : α → α → Prop) : Type where | nil : FreshList α r @@ -606,7 +606,7 @@ Their indices may differ. ::::keepEnv ::: example "Differing numbers of parameters" Even though `Both` and `OneOf` are not mutually recursive, they are declared in the same `mutual` block and must therefore have identical parameters: -```lean (name := bothOptional) (error := true) +```lean (name := bothOptional) +error mutual inductive Both (α : Type u) (β : Type v) where | mk : α → β → Both α β @@ -627,7 +627,7 @@ Note: All inductive types declared in the same `mutual` block must have the same ::: example "Differing parameter types" Even though `Many` and `OneOf` are not mutually recursive, they are declared in the same `mutual` block and must therefore have identical parameters. They both have exactly one parameter, but `Many`'s parameter is not necessarily in the same universe as `Optional`'s: -```lean (name := manyOptional) (error := true) +```lean (name := manyOptional) +error mutual inductive Many (α : Type) : Type u where | nil : Many α @@ -686,7 +686,7 @@ Specifying {name}`PrefixRunOf` as a {lean}`Prop` would be sensible, but it canno ::: :::keepEnv -```lean (error :=true) (name := rleBad) +```lean +error (name := rleBad) mutual inductive RLE : List α → Type where | nil : RLE [] @@ -758,7 +758,7 @@ In other words, in the type of each parameter to each constructor in all the typ ::: example "Mutual strict positivity" In the following mutual group, `Tm` occurs in a negative position in the argument to `Binding.scope`: -```lean (error := true) (name := mutualHoas) +```lean +error (name := mutualHoas) mutual inductive Tm where | app : Tm → Tm → Tm diff --git a/Manual/Language/InductiveTypes/LogicalModel.lean b/Manual/Language/InductiveTypes/LogicalModel.lean index ae3a9f52..64a1c8cc 100644 --- a/Manual/Language/InductiveTypes/LogicalModel.lean +++ b/Manual/Language/InductiveTypes/LogicalModel.lean @@ -78,7 +78,7 @@ Bool.rec.{u} {motive : Bool → Sort u} {lean}`List`'s recursor {name}`List.rec` has the following parameters: :::keepEnv -```lean (show := false) +```lean -show axiom α.{u} : Type u ``` @@ -282,7 +282,7 @@ This restriction rules out unsound inductive type definitions, at the cost of al ::::keepEnv :::keepEnv The type `Bad` would make Lean inconsistent if it were not rejected: -```lean (name := Bad) (error := true) +```lean (name := Bad) +error inductive Bad where | bad : (Bad → Bad) → Bad ``` @@ -292,7 +292,7 @@ inductive Bad where ::: :::keepEnv -```lean (show := false) +```lean -show axiom Bad : Type axiom Bad.bad : (Bad → Bad) → Bad ``` @@ -302,7 +302,7 @@ This is because it would be possible to write a circular argument that proves {l :::keepEnv This declaration of a fixed point operator is rejected, because `Fix` occurs as an argument to `f`: -```lean (name := Fix) (error := true) +```lean (name := Fix) +error inductive Fix (f : Type u → Type u) where | fix : f (Fix f) → Fix f ``` @@ -313,7 +313,7 @@ inductive Fix (f : Type u → Type u) where `Fix.fix` is rejected because `f` is not a type constructor of an inductive type, but `Fix` itself occurs as an argument to it. In this case, `Fix` is also sufficient to construct a type equivalent to `Bad`: -```lean (show := false) +```lean -show axiom Fix : (Type → Type) → Type ``` ```lean @@ -343,7 +343,7 @@ To define a subsingleton that can inhabit {lean}`Prop` or a {lean}`Type`, set th ::::keepEnv :::example "Overly-universe-polymorphic {lean}`Bool`" Defining a version of {lean}`Bool` that can be in any universe is not allowed: -```lean (error := true) (name := PBool) +```lean +error (name := PBool) inductive PBool : Sort u where | true | false diff --git a/Manual/Language/InductiveTypes/Nested.lean b/Manual/Language/InductiveTypes/Nested.lean index 028fcb41..a971adec 100644 --- a/Manual/Language/InductiveTypes/Nested.lean +++ b/Manual/Language/InductiveTypes/Nested.lean @@ -52,7 +52,7 @@ inductive RTree (α : Type u) : Type u where :::::example "Invalid Nested Inductive Types" This declaration of arbitrarily-branching rose trees declares an alias for {name}`List`, rather than using {name}`List` directly: -```lean (error := true) (name := viaAlias) +```lean +error (name := viaAlias) abbrev Children := List inductive RTree (α : Type u) : Type u where @@ -65,25 +65,23 @@ inductive RTree (α : Type u) : Type u where ::::paragraph :::leanSection -```lean (show := false) +```lean -show variable {n : Nat} ``` This declaration of arbitrarily-branching rose trees tracks the depth of the tree using an index. The constructor `DRTree.node` has an {tech}[automatic implicit parameter] {lean}`n` that represents the depths of all sub-trees. However, local variables such as constructor parameters are not permitted as arguments to nested occurrences: ::: -```lean (error := true) (name := localVar) +```lean +error (name := localVar) inductive DRTree (α : Type u) : Nat → Type u where | empty : DRTree α 0 | node (val : α) (children : List (DRTree α n)) : DRTree α (n + 1) ``` -```leanOutput localVar -(kernel) invalid nested inductive datatype 'List', nested inductive datatypes parameters cannot contain local variables. -``` + :::: This declaration includes a non-strictly-positive occurrence of the inductive type, nested under an {name}`Option`: -```lean (error := true) (name := nonPos) +```lean +error (name := nonPos) inductive WithCheck where | done | check (f : Option WithCheck → Bool) @@ -94,7 +92,7 @@ inductive WithCheck where :::paragraph This rose tree has a branching factor that's limited by its parameter: -```lean (error := true) (name := brtree) +```lean +error (name := brtree) inductive BRTree (branches : Nat) (α : Type u) : Type u where | mk : (children : List (BRTree branches α)) → @@ -164,7 +162,7 @@ The translation from nested inductive types to mutual inductive types proceeds a ::::example "Translating Nested Inductive Types" This nested inductive type represents the natural numbers: -```lean (keep := false) +```lean -keep inductive ONat where | mk (pred : Option ONat) : ONat diff --git a/Manual/Language/InductiveTypes/Structures.lean b/Manual/Language/InductiveTypes/Structures.lean index 27657a81..0a44e72b 100644 --- a/Manual/Language/InductiveTypes/Structures.lean +++ b/Manual/Language/InductiveTypes/Structures.lean @@ -39,7 +39,7 @@ In exchange for these restrictions, Lean generates code for structures that offe Just like other inductive types, structures may be recursive; they are subject to the same restrictions regarding strict positivity. Structures do not add any expressive power to Lean; all of their features are implemented in terms of code generation. -```lean (show := false) +```lean -show -- Test claim about recursive above /-- @@ -331,7 +331,7 @@ When the value of a field is not specified, the first default value defined in t References to fields in the default value use the field resolution order as well; this means that child structures that override default fields of parent constructors may also change the computed default values of parent fields. Because the child structure is the first element of its own resolution order, default values in the child structure take precedence over default values from the parent structures. -```lean (show := false) (keep := false) +```lean -show -keep -- If the overlapping fields have different default values, then the default value from the first -- parent structure in the resolution order that includes the field is used. structure Q where @@ -461,7 +461,7 @@ def toAcademicWork (self : Textbook) : AcademicWork := let .mk _title author := book .mk author discipline ``` -```lean (show := false) +```lean -show -- check claim of equivalence example : toAcademicWork = Textbook.toAcademicWork := by funext b @@ -501,7 +501,7 @@ Evaluating the first field index of {name}`coords` yields the underlying {name}` The elaborator translates {lean}`coords.fst` into {lean}`coords.toPair.fst`. -```lean (show := false) (keep := false) +```lean -show -keep example (t : Triple α) : t.fst = t.toPair.fst := rfl ``` :::: @@ -529,7 +529,7 @@ def printEven (num : EvenNumber) : IO Unit := IO.print num.val ``` it is a type error to apply {name}`printEven` directly to {name}`two`: -```lean (error := true) (name := printTwo) +```lean +error (name := printTwo) #check printEven two ``` ```leanOutput printTwo @@ -547,7 +547,7 @@ because values of type {name}`EvenPrime` are not also values of type {name}`Even :::: -```lean (show := false) (keep := false) +```lean -show -keep structure A where x : Nat y : Int diff --git a/Manual/Language/Namespaces.lean b/Manual/Language/Namespaces.lean index d22d8135..61db67db 100644 --- a/Manual/Language/Namespaces.lean +++ b/Manual/Language/Namespaces.lean @@ -69,7 +69,7 @@ Every {tech}[section scope] has a {deftech}_current namespace_, which is determi Names that are declared within the section scope are added to the current namespace. If the declared name has more than one component, then its namespace is nested within the current namespace; the body of the declaration's current namespace is the nested namespace. Section scopes also include a set of {deftech}_opened namespaces_, which are namespaces whose contents are in scope without additional qualification. -{tech key:="resolve"}[Resolving] an identifier to a particular name takes the current namespace and opened namespaces into account. +{tech (key := "resolve")}[Resolving] an identifier to a particular name takes the current namespace and opened namespaces into account. However, {deftech}[protected] declarations (that is, those with the {keyword}`protected` {ref "declaration-modifiers"}[modifier]) are not brought into scope when their namespace is opened. The rules for resolving identifiers into names that take the current namespace and opened namespaces into account are described in the {ref "identifiers-and-resolution"}[section on identifiers as terms]. @@ -88,7 +88,7 @@ Outside the namespace, these names must be qualified unless the namespace is ope ```leanOutput okTea HotDrink.tea : HotDrink ``` -```lean (name := notOkTea) (error := true) +```lean (name := notOkTea) +error #check tea ``` ```leanOutput notOkTea @@ -199,7 +199,7 @@ end ``` If the initial namespace in the command is `A.B` instead, then neither `_root_.A`, `_root_.B`, nor `_root_.B.C` is opened: -```lean (error := true) (name := dotted) +```lean +error (name := dotted) section open A.B C example := [a1, a2, a3, a4, a5, a6] @@ -226,7 +226,7 @@ $_:ident hiding $x:ident $x:ident* ``` ::: -```lean (show := false) (keep := false) +```lean -show -keep namespace A namespace B def x := 5 @@ -251,7 +251,7 @@ $_:ident renaming $[$x:ident → $x:ident],* An ASCII arrow (`->`) may be used instead of the Unicode arrow (`→`). ::: -```lean (show := false) (keep := false) +```lean -show -keep namespace A namespace B def x := 5 @@ -279,7 +279,7 @@ The indicated namespace is added to each currently-opened namespace, and each na All of the listed names must be unambiguous; that is, they must exist in exactly one of the considered namespaces. ::: -```lean (show := false) (keep := false) +```lean -show -keep namespace A namespace B def y := "" @@ -328,7 +328,7 @@ def x := {!{ "pear" }!} ``` However, the name {name}`NS.three` is not in scope: -```lean (error := true) (name := nothree) +```lean +error (name := nothree) def y := three ``` ```leanOutput nothree @@ -352,7 +352,7 @@ export $_ ($_*) ``` Internally, exported names are registered as aliases of their targets. -From the perspective of the kernel, only the original name exists; the elaborator resolves aliases as part of {tech key:="resolve"}[resolving] identifiers to names. +From the perspective of the kernel, only the original name exists; the elaborator resolves aliases as part of {tech (key := "resolve")}[resolving] identifiers to names. ::: :::example "Exported Names" diff --git a/Manual/Meta/ElanOpt.lean b/Manual/Meta/ElanOpt.lean index a522b413..5e72814f 100644 --- a/Manual/Meta/ElanOpt.lean +++ b/Manual/Meta/ElanOpt.lean @@ -35,8 +35,8 @@ def ElanOptKind.ns : ElanOptKind → String open ElanOptKind in instance : Quote ElanOptKind where quote - | .flag => Syntax.mkCApp ``flag #[] - | .option => Syntax.mkCApp ``option #[] + | .flag => Syntax.mkCApp ``ElanOptKind.flag #[] + | .option => Syntax.mkCApp ``ElanOptKind.option #[] def Inline.elanOptDef (name : String) (kind : ElanOptKind) (argMeta : Option String) : Inline where name := `Manual.elanOptDef diff --git a/Manual/Meta/Env.lean b/Manual/Meta/Env.lean index 565b9029..1db40b2f 100644 --- a/Manual/Meta/Env.lean +++ b/Manual/Meta/Env.lean @@ -43,7 +43,7 @@ def envVar : RoleExpander pure #[← `(.other {Manual.Inline.envVar with data := Json.arr #[.str $(quote v), .bool $(quote isDef)] } #[Inline.code $(quote v)])] where - parseOpts : ArgParse DocElabM Bool := .named `def .bool true <&> (·.getD false) + parseOpts : ArgParse DocElabM Bool := .flag `def false "If true, this is the definition site (i.e. the link target) for the variable" def envVarDomain := `Manual.envVar diff --git a/Manual/Meta/LakeOpt.lean b/Manual/Meta/LakeOpt.lean index 04bcc2d4..a87544f6 100644 --- a/Manual/Meta/LakeOpt.lean +++ b/Manual/Meta/LakeOpt.lean @@ -33,8 +33,8 @@ def LakeOptKind.ns : LakeOptKind → String open LakeOptKind in instance : Quote LakeOptKind where quote - | .flag => Syntax.mkCApp ``flag #[] - | .option => Syntax.mkCApp ``option #[] + | .flag => Syntax.mkCApp ``LakeOptKind.flag #[] + | .option => Syntax.mkCApp ``LakeOptKind.option #[] def Inline.lakeOptDef (name : String) (kind : LakeOptKind) (argMeta : Option String) : Inline where name := `Manual.lakeOptDef diff --git a/Manual/Meta/Lean.lean b/Manual/Meta/Lean.lean index d6977e8b..09f28222 100644 --- a/Manual/Meta/Lean.lean +++ b/Manual/Meta/Lean.lean @@ -87,30 +87,24 @@ def typed : RoleExpander Hover.addCustomHover (mkNullNode #[s, e]) type Hover.addCustomHover f type - match config.error with - | none => - for msg in newMsgs.toArray do - logMessage {msg with - isSilent := msg.isSilent || msg.severity != .error - } - | some true => + if config.error then if newMsgs.hasErrors then for msg in newMsgs.errorsToWarnings.toArray do logMessage {msg with isSilent := true} else throwErrorAt term "Error expected in code block, but none occurred" - | some false => + else for msg in newMsgs.toArray do - logMessage {msg with isSilent := msg.isSilent || msg.severity != .error} - if newMsgs.hasErrors then - throwErrorAt term "No error expected in code block, one occurred" + logMessage {msg with + isSilent := msg.isSilent || msg.severity != .error + } reportMessages config.error term newMsgs let hls := (← highlight stx #[] (PersistentArray.empty.push tree)) - if config.show.getD true then + if config.show then pure #[← ``(Inline.other (Verso.Genre.Manual.InlineLean.Inline.lean $(quote hls)) #[Inline.code $(quote term.getString)])] else pure #[] diff --git a/Manual/Meta/Syntax.lean b/Manual/Meta/Syntax.lean index 6b87f3a7..e2a6e26e 100644 --- a/Manual/Meta/Syntax.lean +++ b/Manual/Meta/Syntax.lean @@ -249,7 +249,7 @@ partial def many [Inhabited (f (List α))] [Applicative f] [Alternative f] (x : def FreeSyntaxConfig.parse [Monad m] [MonadInfoTree m] [MonadLiftT CoreM m] [MonadEnv m] [MonadError m] [MonadFileMap m] : ArgParse m FreeSyntaxConfig := FreeSyntaxConfig.mk <$> .positional `name .name <*> - .namedD `open .bool true <*> + .flag `open true <*> .named `label .string true <*> .named `title .inlinesString false diff --git a/Manual/Meta/Tactics.lean b/Manual/Meta/Tactics.lean index a5a7291a..55ec3ddc 100644 --- a/Manual/Meta/Tactics.lean +++ b/Manual/Meta/Tactics.lean @@ -37,9 +37,9 @@ private partial def many (p : ArgParse m α) : ArgParse m (List α) := def TacticOutputConfig.parser [Monad m] [MonadInfoTree m] [MonadLiftT CoreM m] [MonadEnv m] [MonadError m] : ArgParse m TacticOutputConfig := TacticOutputConfig.mk <$> - ((·.getD true) <$> .named `show .bool true) <*> + .flag `show true <*> .named `severity .messageSeverity true <*> - ((·.getD false) <$> .named `summarize .bool true) <*> + .flag `summarize false <*> ((·.getD .exact) <$> .named `whitespace .whitespaceMode true) <*> (many (.named `expandTrace .name false)) @@ -333,7 +333,7 @@ structure TacticGoalConfig where «show» : Bool def TacticGoalConfig.parse [Monad m] [MonadInfoTree m] [MonadLiftT CoreM m] [MonadEnv m] [MonadError m] : ArgParse m TacticGoalConfig := - TacticGoalConfig.mk <$> ((·.getD true) <$> .named `show .bool true) + TacticGoalConfig.mk <$> (.flag `show true) @[role_expander goal] def goal : RoleExpander @@ -628,7 +628,7 @@ structure StateConfig where «show» : Bool := true def StateConfig.parse [Monad m] [MonadInfoTree m] [MonadLiftT CoreM m] [MonadEnv m] [MonadError m] : ArgParse m StateConfig := - StateConfig.mk <$> .named `tag .string true <*> ((·.getD true) <$> .named `show .bool true) + StateConfig.mk <$> .named `tag .string true <*> (.flag `show true) @[code_block_expander pre] def pre : CodeBlockExpander diff --git a/Manual/Monads.lean b/Manual/Monads.lean index ac195f28..f7ded578 100644 --- a/Manual/Monads.lean +++ b/Manual/Monads.lean @@ -62,7 +62,7 @@ The {name}`Alternative` type class describes applicative functors that additiona :::::keepEnv -```lean (show := false) +```lean -show section variable {α : Type u} {β : Type u} ``` @@ -135,7 +135,7 @@ def LenList.diagonal (square : LenList n (LenList n α)) : LenList n α := } ``` -```lean (show := false) +```lean -show end ``` :::: diff --git a/Manual/Monads/Laws.lean b/Manual/Monads/Laws.lean index 2bd53ce2..857750da 100644 --- a/Manual/Monads/Laws.lean +++ b/Manual/Monads/Laws.lean @@ -27,7 +27,7 @@ tag := "monad-laws" ::::keepEnv -```lean (show := false) +```lean -show section Laws universe u u' v axiom f : Type u → Type v @@ -42,7 +42,7 @@ axiom x : f α ``` -```lean (show := false) +```lean -show section F variable {f : Type u → Type v} [Functor f] {α β : Type u} {g : α → β} {h : β → γ} {x : f α} ``` @@ -64,7 +64,7 @@ The {name}`LawfulFunctor` class includes the necessary proofs. {docstring LawfulFunctor} -```lean (show := false) +```lean -show end F ``` diff --git a/Manual/Monads/Lift.lean b/Manual/Monads/Lift.lean index 82b85fdf..beafaa95 100644 --- a/Manual/Monads/Lift.lean +++ b/Manual/Monads/Lift.lean @@ -27,7 +27,7 @@ tag := "lifting-monads" ::::keepEnv -```lean (show := false) +```lean -show variable {m m' n : Type u → Type v} [Monad m] [Monad m'] [Monad n] [MonadLift m n] variable {α β : Type u} ``` @@ -39,7 +39,7 @@ Automatic monad lifting is attempted before the general {tech}[coercion] mechani {docstring MonadLift} -{tech key:="lift"}[Lifting] between monads is reflexive and transitive: +{tech (key := "lift")}[Lifting] between monads is reflexive and transitive: * Any monad can run its own actions. * Lifts from {lean}`m` to {lean}`m'` and from {lean}`m'` to {lean}`n` can be composed to yield a lift from {lean}`m` to {lean}`n`. The utility type class {name}`MonadLiftT` constructs lifts via the reflexive and transitive closure of {name}`MonadLift` instances. @@ -47,7 +47,7 @@ Users should not define new instances of {name}`MonadLiftT`, but it is useful as {docstring MonadLiftT} -```lean (show := false) +```lean -show section variable {m : Type → Type u} ``` @@ -64,7 +64,7 @@ Because it doesn't require its parameter to precisely be in {name}`IO`, it can b The instance implicit parameter {lean}`MonadLiftT BaseIO m` allows the reflexive transitive closure of {name}`MonadLift` to be used to assemble the lift. ::: -```lean (show := false) +```lean -show end ``` @@ -72,7 +72,7 @@ end When a term of type {lean}`n β` is expected, but the provided term has type {lean}`m α`, and the two types are not definitionally equal, Lean attempts to insert lifts and coercions before reporting an error. There are the following possibilities: 1. If {lean}`m` and {lean}`n` can be unified to the same monad, then {lean}`α` and {lean}`β` are not the same. - In this case, no monad lifts are necessary, but the value in the monad must be {tech key:="coercion"}[coerced]. + In this case, no monad lifts are necessary, but the value in the monad must be {tech (key := "coercion")}[coerced]. If the appropriate coercion is found, then a call to {name}`Lean.Internal.coeM` is inserted, which has the following signature: ```signature Lean.Internal.coeM.{u, v} {m : Type u → Type v} {α β : Type u} @@ -89,7 +89,7 @@ There are the following possibilities: [self : MonadLiftT m n] {α : Type u} : m α → n α ``` - 3. If neither {lean}`m` and {lean}`n` nor {lean}`α` and {lean}`β` can be unified, but {lean}`m` can be lifted into {lean}`n` and {lean}`α` can be {tech key:="coercion"}[coerced] to {lean}`β`, then a lift and a coercion can be combined. + 3. If neither {lean}`m` and {lean}`n` nor {lean}`α` and {lean}`β` can be unified, but {lean}`m` can be lifted into {lean}`n` and {lean}`α` can be {tech (key := "coercion")}[coerced] to {lean}`β`, then a lift and a coercion can be combined. This is done by inserting a call to {name}`Lean.Internal.liftCoeM`: ```signature Lean.Internal.liftCoeM.{u, v, w} @@ -125,7 +125,7 @@ fun {α} act => liftM act : {α : Type} → BaseIO α → EIO IO.Error α ::::example "Lifting Transformed Monads" There are also instances of {name}`MonadLift` for most of the standard library's {tech}[monad transformers], so base monad actions can be used in transformed monads without additional work. For example, state monad actions can be lifted across reader and exception transformers, allowing compatible monads to be intermixed freely: -```lean (keep := false) +```lean -keep def incrBy (n : Nat) : StateM Nat Unit := modify (· + n) def incrOrFail : ReaderT Nat (ExceptT String (StateM Nat)) Unit := do @@ -134,7 +134,7 @@ def incrOrFail : ReaderT Nat (ExceptT String (StateM Nat)) Unit := do ``` Disabling lifting causes an error: -```lean (name := noLift) (error := true) +```lean (name := noLift) +error set_option autoLift false def incrBy (n : Nat) : StateM Nat Unit := modify (. + n) @@ -162,7 +162,7 @@ Automatic lifting can be disabled by setting {option}`autoLift` to {lean}`false` # Reversing Lifts -```lean (show := false) +```lean -show variable {m n : Type u → Type v} {α ε : Type u} ``` @@ -233,7 +233,7 @@ Ideally, state updates would be performed within the {name}`tryCatch` call direc Attempting to save bytes and handled exceptions does not work, however, because the arguments to {name}`Except.tryCatch` have type {lean}`Except String Unit`: -```lean (error := true) (name := getBytesErr) (keep := false) +```lean +error (name := getBytesErr) -keep def getBytes' (input : Array Nat) : StateT (Array String) (StateT (Array UInt8) diff --git a/Manual/Monads/Syntax.lean b/Manual/Monads/Syntax.lean index 54565770..aa521b00 100644 --- a/Manual/Monads/Syntax.lean +++ b/Manual/Monads/Syntax.lean @@ -36,7 +36,7 @@ Infix operators are primarily useful in smaller expressions, or when there is no ## Functors -```lean (show := false) +```lean -show section FOps variable {f : Type u → Type v} [Functor f] {α β : Type u} {g : α → β} {x : f α} ``` @@ -54,7 +54,7 @@ $_ <&> $_ ``` ::: -```lean (show := false) +```lean -show example : g <$> x = Functor.map g x := by rfl example : x <&> g = Functor.map g x := by rfl end FOps @@ -62,7 +62,7 @@ end FOps ## Applicative Functors -```lean (show := false) +```lean -show section AOps variable {f : Type u → Type v} [Applicative f] [Alternative f] {α β : Type u} {g : f (α → β)} {x e1 e e' : f α} {e2 : f β} ``` @@ -97,7 +97,7 @@ $_ <|> $_ ::: -```lean (show := false) +```lean -show example : g <*> x = Seq.seq g (fun () => x) := by rfl example : e1 *> e2 = SeqRight.seqRight e1 (fun () => e2) := by rfl example : e1 <* e2 = SeqLeft.seqLeft e1 (fun () => e2) := by rfl @@ -165,7 +165,7 @@ What is your favorite natural number? Monads are primarily used via {tech}[{keywordOf Lean.Parser.Term.do}`do`-notation]. However, it can sometimes be convenient to describe monadic computations via operators. -```lean (show := false) +```lean -show section MOps variable {m : Type u → Type v} [Monad m] {α β : Type u} {act : m α} {f : α → m β} {g : β → m γ} ``` @@ -192,7 +192,7 @@ $_ <=< $_ ::: -```lean (show := false) +```lean -show example : act >>= f = Bind.bind act f := by rfl example : f =<< act = Bind.bind act f := rfl example : f >=> g = Bind.kleisliRight f g := by rfl @@ -219,7 +219,7 @@ do $stmt* The items in a {keywordOf Lean.Parser.Term.do}`do` may be separated by semicolons; otherwise, each should be on its own line and they should have equal indentation. ::: -```lean (show := false) +```lean -show section variable {m : Type → Type} [Monad m] {α β γ: Type} {e1 : m Unit} {e : β} {es : m α} ``` @@ -238,7 +238,7 @@ $e:term A term followed by a sequence of items is translated to a use of {name}`bind`; in particular, {lean}`do e1; es` is translated to {lean}`e1 >>= fun () => do es`. -:::table (header := true) +:::table +header * * {keywordOf Lean.Parser.Term.do}`do` Item * Desugaring @@ -253,7 +253,7 @@ A term followed by a sequence of items is translated to a use of {name}`bind`; i ``` ::: -```lean (show := false) (keep := false) +```lean -show -keep def ex1a := do e1; es def ex1b := e1 >>= fun () => do es example : @ex1a = @ex1b := by rfl @@ -262,7 +262,7 @@ example : @ex1a = @ex1b := by rfl The result of the term's computation may also be named, allowing it to be used in subsequent steps. This is done using {keywordOf Lean.Parser.Term.doLet}`let`. -```lean (show := false) +```lean -show section variable {e1 : m β} {e1? : m (Option β)} {fallback : m α} {e2 : m γ} {f : β → γ → m Unit} {g : γ → α} {h : β → m γ} ``` @@ -291,7 +291,7 @@ let $v := $e:term ::: {lean}`do let x := e; es` is translated to {lean}`let x := e; do es`. -:::table (header := true) +:::table +header * * {keywordOf Lean.Parser.Term.do}`do` Item * Desugaring @@ -330,7 +330,7 @@ let $v := $e:term ``` ::: -```lean (show := false) (keep := false) +```lean -show -keep -- Test desugarings def ex1a := do let x ← e1 @@ -369,7 +369,7 @@ This allows monadic effects to be used in positions that otherwise might expect Multiple occurrences of `←` are processed from left to right, inside to outside. ::::figure "Example Nested Action Desugarings" -:::table (header := true) +:::table +header * * Example {keywordOf Lean.Parser.Term.do}`do` Item * Desugaring @@ -402,7 +402,7 @@ Multiple occurrences of `←` are processed from left to right, inside to outsid ::: :::: -```lean (show := false) (keep := false) +```lean -show -keep -- Test desugarings def ex1a := do f (← e1) (← e2) @@ -562,7 +562,7 @@ When iterating over multiple collections, iteration stops when any of the collec :::example "Iteration over Array Indices with {keywordOf Lean.Parser.Term.doFor}`for`" When iterating over the valid indices for an array with {keywordOf Lean.Parser.Term.doFor}`for`, naming the membership proof allows the tactic that searches for proofs that array indices are in bounds to succeed. -```lean (keep := false) +```lean -keep def satisfyingIndices (p : α → Prop) [DecidablePred p] (xs : Array α) : Array Nat := Id.run do @@ -574,7 +574,7 @@ def satisfyingIndices Omitting the hypothesis name causes the array lookup to fail, because no proof is available in the context that the iteration variable is within the specified range. -```lean (keep := false) (show := false) +```lean -keep -show -- test it /-- error: failed to prove index is valid, possible solutions: @@ -624,7 +624,7 @@ When iteration is complete, {name}`ForIn.forIn` returns the final values of the The specific desugaring of a loop depends on how state and early termination are used in its body. Here are some examples: -```lean (show := false) +```lean -show axiom «» : Type u axiom «» : β variable [Monad m] (xs : Coll) [ForIn m Coll α] [instMem : Membership α Coll] [ForIn' m Coll α instMem] @@ -633,7 +633,7 @@ variable (f : α → β → m β) (f' : (x : α) → x ∈ xs → β → m β) macro "…" : term => `((«» : β)) ``` -:::table (header := true) +:::table +header * * {keywordOf Lean.Parser.Term.do}`do` Item * Desugaring @@ -804,7 +804,7 @@ The rules are as follows: * Items in the branches of an {keywordOf Lean.Parser.Term.doIf}`if`, {keywordOf Lean.Parser.Term.doMatch}`match`, or {keywordOf Lean.Parser.Term.doUnless}`unless` item belong to the same {keywordOf Lean.Parser.Term.do}`do` block as the control structure that contains them. The {keywordOf Lean.Parser.Term.doUnless}`do` keyword that is part of the syntax of {keywordOf Lean.Parser.Term.doUnless}`unless` does not introduce a new {keywordOf Lean.Parser.Term.do}`do` block. * Items in the body of {keywordOf Lean.doElemRepeat_}`repeat`, {keywordOf Lean.doElemWhile_Do_}`while`, and {keywordOf Lean.Parser.Term.doFor}`for` belong to the same {keywordOf Lean.Parser.Term.do}`do` block as the loop that contains them. The {keywordOf Lean.Parser.Term.doFor}`do` keyword that is part of the syntax of {keywordOf Lean.doElemWhile_Do_}`while` and {keywordOf Lean.Parser.Term.doFor}`for` does not introduce a new {keywordOf Lean.Parser.Term.do}`do` block. -```lean (show := false) +```lean -show -- Test nested `do` rules /-- info: ((), 6) -/ @@ -859,11 +859,11 @@ If {keywordOf Lean.Parser.Term.do}`do` blocks that occurred as items in other {k ::: :::: -```lean (show := false) +```lean -show end ``` -```lean (show := false) +```lean -show -- tests for this section set_option pp.all true diff --git a/Manual/Monads/Zoo.lean b/Manual/Monads/Zoo.lean index 0c4cb646..30adfea8 100644 --- a/Manual/Monads/Zoo.lean +++ b/Manual/Monads/Zoo.lean @@ -158,7 +158,7 @@ Except.ok 0 A single monad may support multiple version of the same effect. For example, there might be a mutable {lean}`Nat` and a mutable {lean}`String` or two separate reader parameters. As long as they have different types, it should be convenient to access both. -In typical use, some monadic operations that are overloaded in type classes have type information available for {tech key:="synthesis"}[instance synthesis], while others do not. +In typical use, some monadic operations that are overloaded in type classes have type information available for {tech (key := "synthesis")}[instance synthesis], while others do not. For example, the argument passed to {name MonadState.set}`set` determines the type of the state to be used, while {name MonadState.get}`get` takes no such argument. The type information present in applications of {name MonadState.set}`set` can be used to pick the correct instance when multiple states are available, which suggests that the type of the mutable state should be an input parameter or {tech}[semi-output parameter] so that it can be used to select instances. The lack of type information present in uses of {name MonadState.get}`get`, on the other hand, suggests that the type of the mutable state should be an {tech}[output parameter] in {lean}`MonadState`, so type class synthesis determines the state's type from the monad itself. @@ -170,7 +170,7 @@ The operations with explicit type parameters have names ending in `-The`, such a The name of the version with an output parameter is undecorated. The standard library exports a mix of operations from the `-Of` and undecorated versions of each type class, based on what has good inference behavior in typical use cases. -:::table (header := true) +:::table +header * * Operation * From Class @@ -225,7 +225,7 @@ The standard library exports a mix of operations from the `-Of` and undecorated * Semi-output parameter uses provided type to guide synthesis ::: -```lean (show := false) +```lean -show example : @get = @MonadState.get := by rfl example : @set = @MonadStateOf.set := by rfl example {inst} (f : σ → σ) : @modify σ m inst f = @MonadState.modifyGet σ m inst PUnit fun (s : σ) => (PUnit.unit, f s) := by rfl @@ -256,7 +256,7 @@ get : M Nat ``` Only the outermost may be used, because the type of the state is an output parameter. -```lean (name := getMStr) (error := true) +```lean (name := getMStr) +error #check (get : M String) ``` ```leanOutput getMStr @@ -300,7 +300,7 @@ tag := "monad-transformers" A {deftech}_monad transformer_ is a function that, when provided with a monad, gives back a new monad. Typically, this new monad has all the effects of the original monad along with some additional ones. -```lean (show := false) +```lean -show variable {α : Type u} (T : (Type u → Type v) → Type u → Type w) (m : Type u → Type v) ``` @@ -315,7 +315,7 @@ Typically, a monad transformer also provides instances of one or more type class The transformer's {name}`Monad` and {name}`MonadLift` instances make it practical to write code in the transformed monad, while the type class instances allow the transformed monad to be used with polymorphic functions. ::::keepEnv -```lean (show := false) +```lean -show universe u v variable {m : Type u → Type v} {α : Type u} ``` diff --git a/Manual/Monads/Zoo/Combined.lean b/Manual/Monads/Zoo/Combined.lean index 30e7279f..4358e674 100644 --- a/Manual/Monads/Zoo/Combined.lean +++ b/Manual/Monads/Zoo/Combined.lean @@ -22,7 +22,7 @@ set_option linter.unusedVariables false #doc (Manual) "Combined Error and State Monads" => -```lean (show := false) +```lean -show variable (ε : Type u) (σ σ' : Type u) (α : Type u) ``` @@ -32,7 +32,7 @@ While {lean}`ExceptT ε (StateM σ)` evaluates to the type {lean}`σ → Except {name}`EStateM.Result` is an inductive type that's very similar to {name}`Except`, except both constructors have an additional field for the state. In compiled code, this representation removes one level of indirection from each monadic bind. -```lean (show := false) +```lean -show /-- info: σ → Except ε α × σ -/ #check_msgs in #reduce (types := true) ExceptT ε (StateM σ) α @@ -52,7 +52,7 @@ In compiled code, this representation removes one level of indirection from each {docstring EStateM.adaptExcept} -{docstring EStateM.fromStateM (allowMissing := true)} +{docstring EStateM.fromStateM +allowMissing} # State Rollback diff --git a/Manual/Monads/Zoo/Except.lean b/Manual/Monads/Zoo/Except.lean index 533b09a5..0e929aee 100644 --- a/Manual/Monads/Zoo/Except.lean +++ b/Manual/Monads/Zoo/Except.lean @@ -98,7 +98,7 @@ The inductive type {name}`Except` captures this pattern, and is itself a monad. # Exception Monads in Continuation Passing Style -```lean (show := false) +```lean -show universe u variable (α : Type u) variable (ε : Type u) @@ -111,7 +111,7 @@ An example of such a type is {lean}`(β : Type u) → (α → β) → (ε → β {lean}`ExceptCpsT` is a transformer that can be applied to any monad, so {lean}`ExceptCpsT ε m α` is actually defined as {lean}`(β : Type u) → (α → m β) → (ε → m β) → m β`. Exception monads in continuation passing style have different performance characteristics than {name}`Except`-based state monads; for some applications, it may be worth benchmarking them. -```lean (show := false) +```lean -show /-- info: (β : Type u) → (α → m β) → (ε → m β) → m β -/ #check_msgs in #reduce (types := true) ExceptCpsT ε m α diff --git a/Manual/Monads/Zoo/Id.lean b/Manual/Monads/Zoo/Id.lean index 0b6ee00c..a1391094 100644 --- a/Manual/Monads/Zoo/Id.lean +++ b/Manual/Monads/Zoo/Id.lean @@ -28,7 +28,7 @@ The identity monad has two primary use cases: 1. It can be the type of a {keywordOf Lean.Parser.Term.do}`do` block that implements a pure function with local effects. 2. It can be placed at the bottom of a stack of monad transformers. -```lean (show := false) +```lean -show -- Verify claims example : Id = id := rfl example : Id.run (α := α) = id := rfl diff --git a/Manual/Monads/Zoo/State.lean b/Manual/Monads/Zoo/State.lean index 9b266f18..6be76f1f 100644 --- a/Manual/Monads/Zoo/State.lean +++ b/Manual/Monads/Zoo/State.lean @@ -51,7 +51,7 @@ Even those implementations that use a tuple may in fact use mutation at run-time # Tuple-Based State Monads -```lean (show := false) +```lean -show variable {α σ : Type u} ``` @@ -91,7 +91,7 @@ An example of such a type is {lean}`(δ : Type u) → σ → (α → σ → δ) State monads in continuation passing style have different performance characteristics than tuple-based state monads; for some applications, it may be worth benchmarking them. -```lean (show := false) +```lean -show /-- info: (δ : Type u) → σ → (α → σ → Id δ) → δ -/ #check_msgs in #reduce (types := true) StateCpsT σ Id α @@ -108,7 +108,7 @@ State monads in continuation passing style have different performance characteri # State Monads from Mutable References -```lean (show := false) +```lean -show variable {m : Type → Type} {σ ω : Type} [STWorld σ m] ``` diff --git a/Manual/Namespaces.lean b/Manual/Namespaces.lean index 4fe6430d..5a7a454b 100644 --- a/Manual/Namespaces.lean +++ b/Manual/Namespaces.lean @@ -104,7 +104,7 @@ def Greetings.english := "Hello" Outside its namespace, it cannot be evaluated. -```lean (error := true) (name := english1) +```lean +error (name := english1) #eval english ``` ```leanOutput english1 @@ -119,7 +119,7 @@ section Greetings Even though the section name matches the definition's namespace, the name is not in scope because section names are purely for readability and ease of refactoring. -```lean (error := true) (name := english2) +```lean +error (name := english2) #eval english ``` ```leanOutput english2 @@ -140,7 +140,7 @@ open Greetings The section's name must be used to close it. -```lean (error := true) (name := english4) (keep := false) +```lean +error (name := english4) -keep end ``` ```leanOutput english4 @@ -155,7 +155,7 @@ end Greetings ``` When the section is closed, the effects of the {keywordOf Lean.Parser.Command.open}`open` command are reverted. -```lean (error := true) (name := english5) +```lean +error (name := english5) #eval english ``` ```leanOutput english5 @@ -215,7 +215,7 @@ namespace D.E ``` At this point, the current namespace is `A.D.E`. An {keywordOf Lean.Parser.Command.end}`end` command cannot close all three due to the intervening section: -```lean (error := true) (name := endADE) (keep := false) +```lean +error (name := endADE) -keep end A.D.E ``` ```leanOutput endADE @@ -251,7 +251,7 @@ open Dessert in After the single command, the effects of {keywordOf Lean.Parser.Command.open}`open` are reverted. -```lean (error := true) (name := noCake) +```lean +error (name := noCake) #eval cupcake ``` ```leanOutput noCake @@ -297,7 +297,7 @@ variable {α : Type u} (xs : List α) [Zero α] [Add α] ``` Because automatic implicit parameters are disabled, the following definition fails: -```lean (error := true) (name := secvars) (keep := false) +```lean +error (name := secvars) -keep def addAll (lst : List β) : β := lst.foldr (init := 0) (· + ·) ``` @@ -319,7 +319,7 @@ All variables marked for inclusion are added to all theorems. The {keywordOf Lean.Parser.Command.omit}`omit` command removes the inclusion mark from a variable; it's typically a good idea to use it with {keywordOf Lean.Parser.Command.in}`in`. -```lean (show := false) +```lean -show section variable {p : Nat → Prop} variable (pFifteen : p 15) @@ -336,14 +336,14 @@ variable (pFifteen : p 15) ``` However, only {lean}`p` is added to this theorem's assumptions, so it cannot be proved. -```lean (error := true) (keep := false) +```lean +error -keep theorem p_all : ∀ n, p n := by intro n induction n ``` The {keywordOf Lean.Parser.Command.include}`include` command causes the additional assumptions to be added unconditionally: -```lean (keep := false) (name := lint) +```lean -keep (name := lint) include pZero pStep pFifteen theorem p_all : ∀ n, p n := by @@ -361,7 +361,7 @@ Note: This linter can be disabled with `set_option linter.unusedSectionVars fals ``` This can be avoided by using {keywordOf Lean.Parser.Command.omit}`omit`to remove {lean}`pFifteen`: -```lean (keep := false) +```lean -keep include pZero pStep pFifteen omit pFifteen in @@ -375,6 +375,6 @@ end ``` ::::: -```lean (show := false) +```lean -show end ``` diff --git a/Manual/NotationsMacros.lean b/Manual/NotationsMacros.lean index ccb30c11..1293159f 100644 --- a/Manual/NotationsMacros.lean +++ b/Manual/NotationsMacros.lean @@ -62,12 +62,12 @@ They can be combined flexibly to achieve the necessary results: tag := "macros" %%% -{deftech}_Macros_ are transformations from {name Lean.Syntax}`Syntax` to {name Lean.Syntax}`Syntax` that occur during {tech key:="elaborator"}[elaboration] and during {ref "tactic-macros"}[tactic execution]. +{deftech}_Macros_ are transformations from {name Lean.Syntax}`Syntax` to {name Lean.Syntax}`Syntax` that occur during {tech (key := "elaborator")}[elaboration] and during {ref "tactic-macros"}[tactic execution]. Replacing syntax with the result of transforming it with a macro is called {deftech}_macro expansion_. Multiple macros may be associated with a single {tech}[syntax kind], and they are attempted in order of definition. Macros are run in a {tech}[monad] that has access to some compile-time metadata and has the ability to either emit an error message or to delegate to subsequent macros, but the macro monad is much less powerful than the elaboration monads. -```lean (show := false) +```lean -show section open Lean (Syntax MacroM) ``` @@ -102,7 +102,7 @@ When applied to terms that are not syntactically the numeral five, elaboration s ``` When the error case is triggered, the user receives an error message: -```lean (name := notFiveFive) (error := true) +```lean (name := notFiveFive) +error #eval notFive 5 ``` ```leanOutput notFiveFive @@ -127,7 +127,7 @@ In particular, macro expansion occurs in three situations in Lean: 3. During tactic execution, macros in the outermost layer of the syntax to be elaborated are expanded {ref "tactic-macros"}[prior to executing the syntax as a tactic]. -```lean (keep := false) (show := false) +```lean -keep -show -- Test claim in preceding paragraph that it's OK for macros to give up prior to elab syntax "doubled " term:arg : term @@ -260,7 +260,7 @@ Term quotations have higher priority than command quotations, so in cases of amb ::::keepEnv :::example "Term vs Command Quotation Syntax" -```lean (show := false) +```lean -show open Lean ``` @@ -268,7 +268,7 @@ In the following example, the contents of the quotation could either be a functi Both match the same region of the file, so the {tech}[local longest-match rule] is not relevant. Term quotation has a higher priority than command quotation, so the quotation is interpreted as a term. Terms expect their {tech}[antiquotations] to have type {lean}``TSyntax `term`` rather than {lean}``TSyntax `command``. -```lean (error := true) (name := cmdQuot) +```lean +error (name := cmdQuot) example (cmd1 cmd2 : TSyntax `command) : MacroM (TSyntax `command) := `($cmd1 $cmd2) ``` The result is two type errors like the following: @@ -295,7 +295,7 @@ example (cmd1 cmd2 : TSyntax `command) : MacroM (TSyntax `command) := `($cmd1 $c ::: :::: -```lean (show := false) +```lean -show -- There is no way to extract parser priorities (they're only saved in the Pratt tables next to -- compiled Parser code), so this test of priorities checks the observable relative priorities of the -- quote parsers. @@ -363,7 +363,7 @@ info: do $(⟨.missing⟩):tactic; $(⟨.missing⟩)) : MacroM _) ``` -:::freeSyntax term (open := false) (title := "Quotations") +:::freeSyntax term -open (title := "Quotations") Lean's syntax includes quotations for terms, commands, tactics, and sequences of tactics, as well as a general quotation syntax that allows any input that Lean can parse to be quoted. Term quotations have the highest priority, followed by tactic quotations, general quotations, and finally command quotations. @@ -381,7 +381,7 @@ Term quotations have the highest priority, followed by tactic quotations, genera ``` ::: -```lean (show := false) +```lean -show section M variable {m : Type → Type} open Lean (MonadRef MonadQuotation) @@ -396,12 +396,12 @@ The specific monad to be used is an implicit parameter to the quotation, and any {name}`MonadQuotation` extends {name}`MonadRef`, which gives the quotation access to the source location of the syntax that the macro expander or elaborator is currently processing. {name}`MonadQuotation` additionally includes the ability to add {tech}[macro scopes] to identifiers and use a fresh macro scope for a sub-task. Monads that support quotation include {name}`MacroM`, {name}`TermElabM`, {name}`CommandElabM`, and {name}`TacticM`. -```lean (show := false) +```lean -show end M ``` -```lean (show := false) +```lean -show -- Verify claim about monads above open Lean in example [Monad m] [MonadQuotation m] : m Syntax := `(term|2 + 2) @@ -421,7 +421,7 @@ Basic antiquotations consist of a dollar sign (`$`) immediately followed by an i This means that the value of the corresponding variable, which should be a syntax tree, is to be substituted into this position of the quoted syntax. Entire expressions may be used as antiquotations by wrapping them in parentheses. -```lean (show := false) +```lean -show section open Lean example (e : Term) : MacroM Syntax := `(term| $e) @@ -435,7 +435,7 @@ end -```lean (show := false) +```lean -show section open Lean (TSyntax SyntaxNodeKinds) variable {c : SyntaxNodeKinds} @@ -449,7 +449,7 @@ Some syntax categories can be matched by elements of other categories. For example, numeric and string literals are valid terms in addition to being their own syntax categories. Antiquotations may be annotated with the expected category by suffixing them with a colon and the category name, which causes the parser to validate that the annotated category is acceptable in the given position and construct any intermediate layers that are required in the parse tree. -:::freeSyntax antiquot title:="Antiquotations" open := false +:::freeSyntax antiquot (title := "Antiquotations") -open ```grammar "$"ident(":"ident)? ******* @@ -473,7 +473,7 @@ example [Monad m] [MonadQuotation m] (x : Term) (n : Nat) : m Syntax := :::::keepEnv ::::example "Antiquotation Annotations" -```lean (show := false) +```lean -show open Lean ``` @@ -519,7 +519,7 @@ def ex2 (e) := show m _ from `(2 + $e :num) :::: ::::: -```lean (show := false) +```lean -show end ``` @@ -553,7 +553,7 @@ fun {m} [Monad m] [Lean.MonadQuotation m] x n => do ``` :::paragraph -```lean (show := false) +```lean -show section open Lean (Term) open Lean.Quote @@ -565,9 +565,9 @@ It begins by constructing the source information for the resulting syntax, obtai It then obtains the current macro scope and the name of the module being processed, because macro scopes are added with respect to a module to enable independent compilation and avoid the need for a global counter. It then constructs a node using helpers such as {name}`Syntax.node1` and {name}`Syntax.node2`, which create a {name}`Syntax.node` with the indicated number of children. The macro scope is added to each identifier, and {name Lean.TSyntax.raw}`TSyntax.raw` is used to extract the contents of typed syntax wrappers. -The antiquotations of {lean}`x` and {lean type:="Term"}`quote (n + 2)` occur directly in the expansion, as parameters to {name}`Syntax.node3`. +The antiquotations of {lean}`x` and {lean (type := "Term")}`quote (n + 2)` occur directly in the expansion, as parameters to {name}`Syntax.node3`. -```lean (show := false) +```lean -show end ``` ::: @@ -601,7 +601,7 @@ The syntax repetitions `+` and `*` correspond to the splice suffix `*`; the repe The optional suffix `?` in syntax and splices correspond with each other. -:::table (header := true) +:::table +header * - Syntax Repetition - Splice Suffix * - `+` `*` @@ -617,7 +617,7 @@ The optional suffix `?` in syntax and splices correspond with each other. ::::keepEnv :::example "Suffixed Splices" -```lean (show := false) +```lean -show open Lean open Lean.Elab.Command (CommandElabM) ``` @@ -693,7 +693,7 @@ macro_rules :::example "Optional Splices" The following syntax declaration optionally matches a term between two tokens. The parentheses around the nested `term` are needed because `term?` is a valid identifier. -```lean (show := false) +```lean -show open Lean ``` ```lean @@ -732,7 +732,7 @@ Supplying {name}`none` results in the optional term being absent. ::: :::: -```lean (show := false) +```lean -show section open Lean Syntax variable {k k' : SyntaxNodeKinds} {sep : String} [Coe (TSyntax k) (TSyntax k')] @@ -768,7 +768,7 @@ This is primarily useful to control the placement of error messages or other inf A token antiquotation does not allow an arbitrary atom to be inserted via evaluation. A token antiquotation consists of an atom (that is, a keyword) -:::freeSyntax antiquot (open := true) (title := "Token Antiquotations") +:::freeSyntax antiquot +open (title := "Token Antiquotations") Token antiquotations replace the source information (of type {name Lean.SourceInfo}`SourceInfo`) on a token with the source information from some other syntax. ```grammar @@ -971,7 +971,7 @@ Additionally, if an earlier rule in the macro throws the {name Lean.Macro.Except ::::example "One vs. Two Sets of Macro Rules" -```lean (show := false) +```lean -show open Lean.Macro ``` @@ -1047,7 +1047,7 @@ macro_rules ``` The case for {lean}`List Nat` fails to elaborate, because macro expansion did not translate the {keywordOf arbitrary!}`arbitrary!` syntax into something supported by the elaborator. -```lean (name := arb3) (error := true) +```lean (name := arb3) +error #eval arbitrary! (List Nat) ``` ```leanOutput arb3 @@ -1070,7 +1070,7 @@ The case for {lean}`Array Nat` succeeds, because the first set of macro rules ar tag := "macro-command" %%% -```lean (show := false) +```lean -show section open Lean ``` @@ -1088,7 +1088,7 @@ $_:attrKind macro$[:$p]? $[(name := $_)]? $[(priority := $_)]? $xs:macroArg* : $ ``` ::: -:::syntax Lean.Parser.Command.macroArg (open := false) (title := "Macro Arguments") +:::syntax Lean.Parser.Command.macroArg -open (title := "Macro Arguments") A macro's arguments are either syntax items (as used in the {keywordOf Lean.Parser.Command.syntax}`syntax` command) or syntax items with attached names. ```grammar $s:stx @@ -1101,7 +1101,7 @@ $x:ident:$stx In the expansion, the names that are attached to syntax items are bound; they have type {name Lean.TSyntax}`TSyntax` for the appropriate syntax kinds. If the syntax matched by the parser does not have a defined kind (e.g. because the name is applied to a complex specification), then the type is {lean}`TSyntax Name.anonymous`. -```lean (show := false) (keep := false) +```lean -show -keep -- Check the typing rules open Lean Elab Term Macro Meta @@ -1136,7 +1136,7 @@ The documentation comment is associated with the new syntax, and the attribute k Behind the scenes, the {keywordOf Lean.Parser.Command.macro}`macro` command is itself implemented by a macro that expands it to a {keywordOf Lean.Parser.Command.syntax}`syntax` command and a {keywordOf Lean.Parser.Command.macro_rules}`macro_rules` command. Any attributes applied to the macro command are applied to the syntax definition, but not to the {keywordOf Lean.Parser.Command.macro_rules}`macro_rules` command. -```lean (show := false) +```lean -show end ``` @@ -1157,7 +1157,7 @@ macro $_:ident ::::keepEnv :::example "The Macro Attribute" -```lean (show := false) +```lean -show open Lean Macro ``` ```lean diff --git a/Manual/NotationsMacros/Delab.lean b/Manual/NotationsMacros/Delab.lean index 149db9e1..97780996 100644 --- a/Manual/NotationsMacros/Delab.lean +++ b/Manual/NotationsMacros/Delab.lean @@ -66,7 +66,7 @@ The unexpander is passed the syntax of the application, with implicit arguments If the option {option}`pp.explicit` is {lean}`true` or {option}`pp.notation` is {lean}`false`, then unexpanders are not used. ::::::::leanSection -```lean (show := false) +```lean -show open Lean.PrettyPrinter (Unexpander UnexpandM) ``` @@ -74,7 +74,7 @@ An unexpander has type {lean}`Lean.PrettyPrinter.Unexpander`, which is an abbrev In the remainder of this section, the names {lean}`Unexpander` and {lean}`UnexpandM` are used unqualified. {lean}`UnexpandM` is a monad that supports quotation and failure via its {name Lean.MonadQuotation}`MonadQuotation` and {lean}`MonadExcept Unit` instances. -An unexpander should either return unexpanded syntax or fail using {lean type:="UnexpandM Syntax"}`throw ()`. +An unexpander should either return unexpanded syntax or fail using {lean (type := "UnexpandM Syntax")}`throw ()`. If the unexpander succeeds, then the resulting syntax is unexpanded again; if it fails, then the next unexpander is tried. When no unexpander succeeds for the syntax, its child nodes are unexpanded until all opportunities for unexpansion are exhausted. @@ -137,6 +137,7 @@ intro v v : Solo ⊢ v = ‹› -/ + ``` :::: @@ -178,7 +179,7 @@ def ListCursor.fastForward : ListCursor α → ListCursor α termination_by xs => xs.after ``` -```lean (show := false) +```lean -show def ListCursor.ofList (xs : List α) : ListCursor α where before := [] after := xs @@ -250,7 +251,7 @@ some [1 🚩 2, 3, 4, 5] tag := "delaborators" %%% ::::::::leanSection -```lean (show := false) +```lean -show open Lean.PrettyPrinter.Delaborator (DelabM Delab) open Lean (Term) ``` @@ -268,14 +269,14 @@ The {attr}`delab` attribute registers a delaborator for the indicated constructo delab $_:ident ``` -The {keyword}`app_delab ` attribute registers a delaborator for applications of the indicated constant after {tech key:="resolve"}[resolving] it in the current {tech key:="section scope"}[scope]. +The {keyword}`app_delab ` attribute registers a delaborator for applications of the indicated constant after {tech (key := "resolve")}[resolving] it in the current {tech (key := "section scope")}[scope]. ```grammar app_delab $_:ident ``` ::: ::::leanSection -```lean (show := false) +```lean -show open Lean.PrettyPrinter.Delaborator.SubExpr ``` :::paragraph diff --git a/Manual/NotationsMacros/Elab.lean b/Manual/NotationsMacros/Elab.lean index b9b788dc..d156393a 100644 --- a/Manual/NotationsMacros/Elab.lean +++ b/Manual/NotationsMacros/Elab.lean @@ -35,7 +35,7 @@ Elaborators come in two varieties: * {deftech}_Command elaborators_ are used to add new commands to Lean. Commands are implemented as side effects: they may add new constants to the global environment, extend compile-time tables such as the one that tracks {tech}[instances], they can provide feedback in the form of information, warnings, or errors, and they have full access to the {name}`IO` monad. - Command elaborators are associated with the {tech key:="kind"}[syntax kinds] that they can handle. + Command elaborators are associated with the {tech (key := "kind")}[syntax kinds] that they can handle. * {deftech}_Term elaborators_ are used to implement new terms by translating the syntax into Lean's core type theory. They can do everything that command elaborators can do, and they additionally have access to the local context in which the term is being elaborated. @@ -84,7 +84,7 @@ tactic $_ # Command Elaborators :::::leanSection -```lean (show := false) +```lean -show open Lean Elab Command ``` A command elaborator has type {name}`CommandElab`, which is an abbreviation for {lean}`Syntax → CommandElabM Unit`. @@ -129,7 +129,7 @@ Found 2 instances of 'interestingName' # Term Elaborators :::::leanSection -```lean (show := false) +```lean -show open Lean Elab Term ``` A term elaborator has type {name}`TermElab`, which is an abbreviation for {lean}`Syntax → Option Expr → TermElabM Expr`. @@ -141,7 +141,7 @@ Like command elaborators, term elaborators may be implicitly defined using {keyw This examples demonstrates an elaborator for syntax that is the opposite of a type ascription. The provided term may have any type _other_ than the one indicated, and metavariables are solved pessimistically. In this example, {name}`elabType` invokes the term elaborator and then ensures that the resulting term is a type. -{name}`Meta.inferType` infers a type for a term, and {name}`Meta.isDefEq` attempts to make two terms {tech key:="definitional equality"}[definitionally equal] by unification, returning {lean}`true` if it succeeds. +{name}`Meta.inferType` infers a type for a term, and {name}`Meta.isDefEq` attempts to make two terms {tech (key := "definitional equality")}[definitionally equal] by unification, returning {lean}`true` if it succeeds. ```lean syntax (name := notType) "(" term " !: " term ")" : term @@ -159,7 +159,7 @@ def elabNotType : TermElab := fun stx _ => do ``` If the type position does not contain a type, then `elabType` throws an error: -```lean (name := notType) (error := true) +```lean (name := notType) +error #eval ([1, 2, 3] !: "not a type") ``` ```leanOutput notType @@ -176,15 +176,15 @@ If the term's type is definitely not equal to the provided type, then elaboratio ``` If the types match, an error is thrown: -```lean (name := nope) (error := true) +```lean (name := nope) +error #eval (5 !: Nat) ``` ```leanOutput nope Got unwanted type Nat ``` -The type equality check may fill in missing information, so {lean type :="String"}`sorry` (which may have any type) is also rejected: -```lean (name := unif) (error := true) +The type equality check may fill in missing information, so {lean (type := "String")}`sorry` (which may have any type) is also rejected: +```lean (name := unif) +error #eval (sorry !: String) ``` ```leanOutput unif @@ -235,7 +235,7 @@ It chooses the most recent suitable variable, as desired: ``` When no assumption is suitable, it returns an error that describes the attempt: -```lean (name := noFun) (error := true) +```lean (name := noFun) +error #eval let x := Nat.zero let y := "hello" @@ -248,7 +248,7 @@ No assumption in [x, y, f] has type Int → Int Because it uses unification, the natural number literal is chosen here, because numeric literals may have any type with an {name}`OfNat` instance. Unfortunately, there is no {name}`OfNat` instance for functions, so instance synthesis later fails. -```lean (name := poly) (error := true) +```lean (name := poly) +error #eval let x := 5 let y := "hello" diff --git a/Manual/NotationsMacros/Notations.lean b/Manual/NotationsMacros/Notations.lean index 0c252fb4..a5cf38ee 100644 --- a/Manual/NotationsMacros/Notations.lean +++ b/Manual/NotationsMacros/Notations.lean @@ -41,7 +41,7 @@ $_:attrKind notation$[:$_:prec]? $[(name := $_:ident)]? $[(priority := $_:prio)] ``` ::: -:::syntax Lean.Parser.Command.notationItem (open := false) (title := "Notation Items") +:::syntax Lean.Parser.Command.notationItem -open (title := "Notation Items") The body of a notation definition consists of a sequence of {deftech}_notation items_, which may be either string literals or identifiers with optional precedences. ```grammar $s:str @@ -79,7 +79,7 @@ This applies both to notations that consist only of a single atom and to notatio Otherwise, the default precedence of the whole notation is `lead`. If no precedence is provided for notation items that are terms, then they default to precedence `min`. -```lean (keep := false) (show := false) +```lean -keep -show -- Test for default precedences for notations diff --git a/Manual/NotationsMacros/Operators.lean b/Manual/NotationsMacros/Operators.lean index 9159f7fb..cba17fb2 100644 --- a/Manual/NotationsMacros/Operators.lean +++ b/Manual/NotationsMacros/Operators.lean @@ -60,7 +60,7 @@ Infix operators additionally have an {deftech}_associativity_ that determines th ``` ::::keepEnv :::example "Precedence for Prefix and Infix Operators" -```lean (show := false) +```lean -show axiom A : Prop axiom B : Prop example : (¬A ∧ B = (¬A) ∧ B) = (¬A ∧ ((B = ¬A) ∧ B)) := rfl @@ -189,7 +189,7 @@ True + False : Prop ``` However, because the new operator is not associative, the {tech}[local longest-match rule] means that only {name}`HAdd.hAdd` applies to an unparenthesized three-argument version: -```lean (error := true) (name := trueOrFalseOrTrue1) +```lean +error (name := trueOrFalseOrTrue1) #check True + False + True ``` ```leanOutput trueOrFalseOrTrue1 @@ -213,7 +213,7 @@ infix:65 (priority := high) " + " => Or ```leanOutput trueOrFalse2 True + False : Prop ``` -```lean (name := twoPlusTwo2) (error := true) +```lean (name := twoPlusTwo2) +error #check 2 + 2 ``` ```leanOutput twoPlusTwo2 @@ -227,7 +227,7 @@ Hint: Additional diagnostic information may be available using the `set_option d ``` The new operator is not associative, so the {tech}[local longest-match rule] means that only {name}`HAdd.hAdd` applies to the three-argument version: -```lean (error := true) (name := trueOrFalseOrTrue2) +```lean +error (name := trueOrFalseOrTrue2) #check True + False + True ``` ```leanOutput trueOrFalseOrTrue2 @@ -257,7 +257,7 @@ Omitting them causes the operator's arguments to be displayed immediately next t :::keepEnv -```lean (show := false) +```lean -show -- Test claim about internal whitespace in preceding paragraph /-- error: invalid atom @@ -310,7 +310,7 @@ Other than its ability to accept arguments at each call site, there are no speci Operators may construct functions, so the term may expect more parameters than the operator. Implicit and {tech}[instance-implicit] parameters are resolved at each application site, which allows the operator to be defined by a {tech}[type class] {tech}[method]. -```lean (show := false) (keep := false) +```lean -show -keep -- Double-check claims about operators above prefix:max "blah" => Nat.add #check (blah 5) diff --git a/Manual/NotationsMacros/Precedence.lean b/Manual/NotationsMacros/Precedence.lean index 4870bc99..4c71bd56 100644 --- a/Manual/NotationsMacros/Precedence.lean +++ b/Manual/NotationsMacros/Precedence.lean @@ -29,7 +29,7 @@ Infix operators, notations, and other syntactic extensions to Lean make use of e While precedences in Lean can technically be any natural number, by convention they range from {evalPrec}`min` to {evalPrec}`max`, respectively denoted `min` and `max`.{TODO}[Fix the keywordOf operator and use it here] Function application has the highest precedence. -:::syntax prec (open := false) (title := "Parser Precedences") +:::syntax prec -open (title := "Parser Precedences") Most operator precedences consist of explicit numbers. The named precedence levels denote the outer edges of the range, close to the minimum or maximum, and are typically used by more involved syntax extensions. ```grammar diff --git a/Manual/NotationsMacros/SyntaxDef.lean b/Manual/NotationsMacros/SyntaxDef.lean index cf9a3494..9313d6f3 100644 --- a/Manual/NotationsMacros/SyntaxDef.lean +++ b/Manual/NotationsMacros/SyntaxDef.lean @@ -44,7 +44,7 @@ All of these are represented by a few basic building blocks: : {deftech}[Identifiers] :::keepEnv - ```lean (show := false) + ```lean -show variable {α : Type u} variable {x : α} ``` @@ -91,7 +91,7 @@ Typically, single-token syntax productions consist of a {name Lean.Syntax.node}` Atoms for literals are not interpreted by the parser: string atoms include their leading and trailing double-quote characters along with any escape sequences contained within, and hexadecimal numerals are saved as a string that begins with {lean}`"0x"`. {ref "typed-syntax-helpers"}[Helpers] such as {name}`Lean.TSyntax.getString` are provided to perform this decoding on demand. -```lean (show := false) (keep := false) +```lean -show -keep -- Verify claims about atoms and nodes open Lean in partial def noInfo : Syntax → Syntax @@ -147,7 +147,7 @@ tag := "source-info" Atoms, identifiers, and nodes optionally contain {deftech}[source information] that tracks their correspondence with the original file. The parser saves source information for all tokens, but not for nodes; position information for parsed nodes is reconstructed from their first and last tokens. -Not all {name Lean.Syntax}`Syntax` data results from the parser: it may be the result of {tech}[macro expansion], in which case it typically contains a mix of generated and parsed syntax, or it may be the result of {tech key:="delaborator"}[delaborating] an internal term to display it to a user. +Not all {name Lean.Syntax}`Syntax` data results from the parser: it may be the result of {tech}[macro expansion], in which case it typically contains a mix of generated and parsed syntax, or it may be the result of {tech (key := "delaborator")}[delaborating] an internal term to display it to a user. In these use cases, nodes may themselves contain source information. Source information comes in two varieties: @@ -169,7 +169,7 @@ Source information comes in two varieties: # Inspecting Syntax -```lean (show := false) +```lean -show section Inspecting open Lean ``` @@ -290,7 +290,7 @@ However, {name}`ppTerm` can be explicitly invoked if needed. ::::keepEnv :::example "Pretty-Printed Syntax" -```lean (show := false) +```lean -show open Lean Elab Command ``` @@ -350,7 +350,7 @@ List.length✝ :::: -```lean (show := false) +```lean -show end Inspecting ``` @@ -372,7 +372,7 @@ The list of syntax categories typically contains precisely one element, in which For many of Lean's built-in syntactic categories, there is a set of {tech}[coercions] that appropriately wrap one kind of syntax for another category, such as a coercion from the syntax of string literals to the syntax of terms. Additionally, many helper functions that are only valid on some syntactic categories are defined for the appropriate typed syntax only. -```lean (show := false) +```lean -show /-- info: instCoeHTCTOfCoeHTC -/ #check_msgs in open Lean in @@ -512,7 +512,7 @@ Identifiers in syntax rules indicate syntax categories, rather than naming subte Finally, the syntax rule specifies which syntax category it extends. It is an error to declare a syntax rule in a nonexistent category. -```lean (show := false) +```lean -show -- verify preceding para /-- error: unknown category 'nuhUh' -/ #check_msgs in @@ -520,7 +520,7 @@ syntax "blah" : nuhUh ``` -:::syntax stx (open := false) (title := "Syntax Specifiers") +:::syntax stx -open (title := "Syntax Specifiers") The syntactic category `stx` is the grammar of specifiers that may occur in the body of a {keywordOf Lean.Parser.Command.syntax}`syntax` command. String literals are parsed as {tech}[atoms] (including both keywords such as `if`, `#eval`, or `where`): @@ -760,7 +760,7 @@ syntax "note " ppLine withPosition((colEq "◦ " str ppLine)+) : term ``` There is no elaborator or macro associated with this syntax, but the following example is accepted by the parser: -```lean (error := true) (name := noteEx1) +```lean +error (name := noteEx1) #check note ◦ "One" @@ -775,7 +775,7 @@ elaboration function for '«termNote__◦__»' has not been implemented ``` The syntax does not require that the list is indented with respect to the opening token, which would require an extra `withPosition` and a `colGt`. -```lean (error := true) (name := noteEx15) +```lean +error (name := noteEx15) #check note ◦ "One" diff --git a/Manual/Quotients.lean b/Manual/Quotients.lean index 9670acd7..294fd785 100644 --- a/Manual/Quotients.lean +++ b/Manual/Quotients.lean @@ -72,11 +72,11 @@ While {name}`Quotient` is a convenient way to form quotients with reasonable com In general, a type $`Q` is said to be the quotient of $`A` by an equivalence relation $`\sim` if it respects the universal property of quotients: there is a function $`q:A\to Q` with the property that $`q(a)=q(b)` if and only if $`a\sim b` for all $`a` and $`b` in $`A`. Quotients formed with {name}`Quotient` have this property up to {tech}[propositional equality]: elements of $`A` that are related by $`\sim` are equal, so they cannot be distinguished. -However, members of the same equivalence class are not necessarily {tech key:="definitional equality"}[definitionally equal] in the quotient. +However, members of the same equivalence class are not necessarily {tech (key := "definitional equality")}[definitionally equal] in the quotient. Quotients may also be implemented by designating a single representative of each equivalence class in $`A` itself, and then defining $`Q` as pair of elements in $`A` with proofs that they are such a canonical representative. Together with a function that maps each $`a` in $`A` to its canonical representative, $`Q` is a quotient of $`A`. -Due to {tech}[proof irrelevance], representatives in $`Q` of the same equivalence class are {tech key:="definitional equality"}[definitionally equal]. +Due to {tech}[proof irrelevance], representatives in $`Q` of the same equivalence class are {tech (key := "definitional equality")}[definitionally equal]. Such a manually implemented quotient $`Q` can be easier to work with than {name}`Quotient`. In particular, because each equivalence class is represented by its single canonical representative, there's no need to prove that functions from the quotient respect the equivalence relation. @@ -216,7 +216,7 @@ $_ ≈ $_ {docstring HasEquiv} -```lean (show := false) +```lean -show section variable (r : α → α → Prop) ``` @@ -225,13 +225,13 @@ The fact that a relation {lean}`r` is actually an equivalence relation is stated {docstring Equivalence} -```lean (show := false) +```lean -show end ``` Every {name}`Setoid` instance leads to a corresponding {name}`HasEquiv` instance. -```lean (show := false) +```lean -show -- Check preceding para section variable {α : Sort u} [Setoid α] @@ -266,7 +266,7 @@ A value in the quotient is a value from the setoid's underlying type, wrapped in :::example "The Integers as a Quotient Type" The integers, defined as pairs of natural numbers where the represented integer is the difference of the two numbers, can be represented via a quotient type. -This representation is not unique: both {lean}`(4, 7)` and {lean}`(1, 4)` represent {lean type:="Int"}`-3`. +This representation is not unique: both {lean}`(4, 7)` and {lean}`(1, 4)` represent {lean (type := "Int")}`-3`. Two encoded integers should be considered equal when they are related by {name}`Z.eq`: @@ -342,7 +342,7 @@ The variants {lean}`Quotient.liftOn` and {lean}`Quotient.liftOn₂` place the qu :::example "Integer Negation and Addition" -```lean (show := false) +```lean -show def Z' : Type := Nat × Nat def Z.eq (n k : Z') : Prop := @@ -433,7 +433,7 @@ Because {name}`Quotient` is not an {tech}[inductive type], tactics such as {tact :::example "Proofs About Quotients" -```lean (show := false) +```lean -show def Z' : Type := Nat × Nat def Z.eq (n k : Z') : Prop := @@ -551,7 +551,7 @@ These are used in the same way as their {name}`Quotient`-based counterparts. tag := "quotient-reduction" %%% -```lean (show := false) +```lean -show section variable (α β : Sort u) @@ -561,13 +561,13 @@ variable (x : α) ``` In addition to the above constants, Lean's kernel contains a reduction rule for {name}`Quot.lift` that causes it to reduce when used with {name}`Quot.mk`, analogous to {tech}[ι-reduction] for inductive types. -Given a relation {lean}`r` over {lean}`α`, a function {lean}`f` from {lean}`α` to {lean}`β`, and a proof {lean}`resp` that {lean}`f` respects {lean}`r`, the term {lean}`Quot.lift f resp (Quot.mk r x)` is {tech key:="definitional equality"}[definitionally equal] to {lean}`f x`. +Given a relation {lean}`r` over {lean}`α`, a function {lean}`f` from {lean}`α` to {lean}`β`, and a proof {lean}`resp` that {lean}`f` respects {lean}`r`, the term {lean}`Quot.lift f resp (Quot.mk r x)` is {tech (key := "definitional equality")}[definitionally equal] to {lean}`f x`. -```lean (show := false) +```lean -show end ``` -```lean (show := false) +```lean -show section ``` @@ -581,7 +581,7 @@ variable example : Quot.lift f ok (Quot.mk r x) = f x := rfl ``` -```lean (show := false) +```lean -show end ``` @@ -603,7 +603,7 @@ inductive RoseTree (α : Type u) where ``` However, taking a quotient of the {name}`List` that identifies all elements in the style of {ref "squash-types"}[squash types] causes Lean to reject the declaration: -```lean (error := true) (name := nestedquot) +```lean +error (name := nestedquot) inductive SetTree (α : Type u) where | leaf : α → SetTree α | branch : @@ -664,7 +664,7 @@ def extApp exact h x ``` -```lean (show := false) +```lean -show section variable (f : (x : α) → β x) ``` @@ -680,7 +680,7 @@ fun x => (Quot.mk extEq f).lift (· x) (fun _ _ h => h x) which is definitionally equal to {lean}`fun x => f x`, which is definitionally equal (by {tech}[η-equivalence]) to {lean}`f`. A propositional version of the computation rule for {name}`Quot.lift` would not suffice, because the reducible expression occurs in the body of a function and rewriting by an equality in a function would already require function extensionality. -```lean (show := false) +```lean -show end ``` @@ -711,7 +711,7 @@ theorem funext' tag := "squash-types" %%% -```lean (show := false) +```lean -show section variable {α : Sort u} ``` @@ -720,7 +720,7 @@ In other words, if {lean}`α` is inhabited, then {lean}`Squash α` has a single Unlike {lean}`Nonempty α`, which is a proposition stating that {lean}`α` is inhabited and is thus represented by a dummy value at runtime, {lean}`Squash α` is a type that is represented identically to {lean}`α`. Because {lean}`Squash α` is in the same universe as {lean}`α`, it is not subject to the restrictions on computing data from propositions. -```lean (show := false) +```lean -show end ``` diff --git a/Manual/RecursiveDefs.lean b/Manual/RecursiveDefs.lean index c6bc25af..e7e7c29a 100644 --- a/Manual/RecursiveDefs.lean +++ b/Manual/RecursiveDefs.lean @@ -124,7 +124,7 @@ Even though the names are not in scope in signatures, they will not be inserted :::example "Mutual Block Scope" Names defined in a mutual block are not in scope in each others' signatures. -```lean (error := true) (name := mutScope) (keep := false) +```lean +error (name := mutScope) -keep mutual abbrev NaturalNum : Type := Nat def n : NaturalNum := 5 @@ -145,7 +145,7 @@ def n : NaturalNum := 5 Names defined in a mutual block are not in scope in each others' signatures. Nonetheless, they cannot be used as automatic implicit parameters: -```lean (error := true) (name := mutScopeTwo) (keep := false) +```lean +error (name := mutScopeTwo) -keep mutual abbrev α : Type := Nat def identity (x : α) : α := x @@ -276,11 +276,11 @@ Using these operators requires a thorough understanding of the Lean implementati {docstring unsafeCast} -{docstring ptrEq (allowMissing := true)} +{docstring ptrEq +allowMissing} -{docstring ptrEqList (allowMissing := true)} +{docstring ptrEqList +allowMissing} -{docstring ptrAddrUnsafe (allowMissing := true)} +{docstring ptrAddrUnsafe +allowMissing} {docstring isExclusiveUnsafe} @@ -415,7 +415,7 @@ def hello : Phrase := "Hello" def goodMorning : Clause := "Good morning" ``` The irreducible alias, on the other hand, is rejected as the type for a string, because the elaborator's definitional equality test does not unfold it: -```lean (error := true) (name := irred) +```lean +error (name := irred) def goodEvening : Utterance := "Good evening" ``` ```leanOutput irred @@ -433,7 +433,7 @@ Because {lean}`Phrase` is reducible, the {inst}`ToString String` instance can be ``` However, {lean}`Clause` is semireducible, so the {inst}`ToString String` instance cannot be used: -```lean (error := true) (name := toStringClause) +```lean +error (name := toStringClause) #synth ToString Clause ``` ```leanOutput toStringClause @@ -465,7 +465,7 @@ generalized field notation allows {name}`List.reverse` to be accessed from a ter ``` However, declaring {name}`Sequence` to be irreducible prevents the unfolding: -```lean (error := true) (name := irredSeq) +```lean +error (name := irredSeq) attribute [irreducible] Sequence #check let xs : Sequence Nat := .ofList [1,2,3]; xs.reverse @@ -516,7 +516,7 @@ theorem plus_eq_add : plus x y = x + y := by simp ``` The semireducible synonym is not, however, unfolded by {tactic}`simp`: -```lean (keep := false) (error := true) (name := simpSemi) +```lean -keep +error (name := simpSemi) theorem sum_eq_add : sum x y = x + y := by simp ``` Nonetheless, the definitional equality check induced by {tactic}`rfl` unfolds the {lean}`sum`: @@ -524,11 +524,11 @@ Nonetheless, the definitional equality check induced by {tactic}`rfl` unfolds th theorem sum_eq_add : sum x y = x + y := by rfl ``` The irreducible {lean}`tally`, however, is not reduced by definitional equality. -```lean (keep := false) (error := true) (name := reflIr) +```lean -keep +error (name := reflIr) theorem tally_eq_add : tally x y = x + y := by rfl ``` The {tactic}`simp` tactic can unfold any definition, even irreducible ones, when they are explicitly provided: -```lean (keep := false) (name := simpName) +```lean -keep (name := simpName) theorem tally_eq_add : tally x y = x + y := by simp [tally] ``` Similarly, part of a proof can be instructed to ignore irreducibility by placing it in a {tactic}`with_unfolding_all` block: diff --git a/Manual/RecursiveDefs/PartialFixpoint.lean b/Manual/RecursiveDefs/PartialFixpoint.lean index bb89745d..c94fe6a9 100644 --- a/Manual/RecursiveDefs/PartialFixpoint.lean +++ b/Manual/RecursiveDefs/PartialFixpoint.lean @@ -26,8 +26,8 @@ tag := "partial-fixpoint" %%% All definitions are fundamentally equations: the new constant being defined is equal to the right-hand side of the definition. -For functions defined by {ref "structural-recursion"}[structural recursion], this equation holds {tech key:="definitional equality"}[definitionally], and there is a unique value returned by application of the function. -For functions defined by {ref "well-founded-recursion"}[well-founded recursion], the equation may hold only {tech key:="proposition"}[propositionally], but all type-correct applications of the function to arguments are equal to the respective values prescribed by the definition. +For functions defined by {ref "structural-recursion"}[structural recursion], this equation holds {tech (key := "definitional equality")}[definitionally], and there is a unique value returned by application of the function. +For functions defined by {ref "well-founded-recursion"}[well-founded recursion], the equation may hold only {tech (key := "proposition")}[propositionally], but all type-correct applications of the function to arguments are equal to the respective values prescribed by the definition. In both cases, the fact that the function terminates for all inputs means that the value computed by applying the function is always uniquely determined. @@ -39,7 +39,7 @@ As with the other strategies for defining recursive functions, compiled code use The term {tech}_partial fixpoint_ is specific to Lean. Functions declared {keywordOf Lean.Parser.Command.declaration}`partial` do not require termination proofs, so long as the type of their return values is inhabited, but they are completely opaque from the perspective of Lean's logic. Partial fixpoints, on the other hand, can be rewritten using their defining equations while writing proofs. -Logically speaking, partial fixpoints are total functions that don't reduce {tech key:="definitional equality"}[definitionally] when applied, but for which equational rewrite rule are provided. +Logically speaking, partial fixpoints are total functions that don't reduce {tech (key := "definitional equality")}[definitionally] when applied, but for which equational rewrite rule are provided. They are _partial_ in the sense that the defining equation does not necessarily specify a value for all possible arguments. @@ -62,7 +62,7 @@ Both classes are backed by the same theory and construction: least fixpoints of Just as with structural and well-founded recursion, Lean allows {tech}[mutually recursive] functions to be defined as partial fixpoints. To use this feature, every function definition in a {tech}[mutual block] must be annotated with the {keywordOf Lean.Parser.Command.declaration}`partial_fixpoint` modifier. -```lean (show := false) +```lean -show section variable (p : Nat → Bool) ``` @@ -70,7 +70,7 @@ variable (p : Nat → Bool) :::example "Definition by Partial Fixpoint" The following function finds the least natural number for which the predicate {lean}`p` holds. -If `p` never holds, then this equation does not specify the behavior: the function {lean}`find` could return {lean type:="Nat"}`42` or any other {lean}`Nat` in that case and still satisfy the equation. +If `p` never holds, then this equation does not specify the behavior: the function {lean}`find` could return {lean (type := "Nat")}`42` or any other {lean}`Nat` in that case and still satisfy the equation. ```lean def find (p : Nat → Bool) (i : Nat := 0) : Nat := @@ -85,7 +85,7 @@ The elaborator can prove that functions satisfying the equation exist. Within Lean's logic, {lean}`find` is defined to be an arbitrary such function. ::: -```lean (show := false) +```lean -show end ``` @@ -108,11 +108,11 @@ An expression is in {deftech}_tail position_ in the function body if it is: * the branches of an {keywordOf termIfThenElse}`if` expression that is in tail position, and * the body of a {keywordOf Lean.Parser.Term.let}`let` expression that is in tail position. -In particular, the {tech key:="match discriminant"}[discriminant] of a {keywordOf Lean.Parser.Term.match}`match` expression, the condition of an {keywordOf termIfThenElse}`if` expression and the arguments of functions are not tail positions. +In particular, the {tech (key := "match discriminant")}[discriminant] of a {keywordOf Lean.Parser.Term.match}`match` expression, the condition of an {keywordOf termIfThenElse}`if` expression and the arguments of functions are not tail positions. ::: -```lean (show := false) +```lean -show -- Test that nonempty is enough inductive A : Type where | mkA @@ -159,7 +159,7 @@ partial_fixpoint If the result of the recursive call is not just returned, but passed to another function, it is not in tail position and this definition fails. -```lean (keep := false) (error := true) (name := nonTailPos) +```lean -keep +error (name := nonTailPos) def List.findIndex (xs : List α) (p : α → Bool) : Int := match xs with | [] => -1 @@ -200,7 +200,7 @@ In particular, using {tech}[{keywordOf Lean.Parser.Term.do}`do`-notation] should The following function implements the Ackermann function in the {name}`Option` monad, and is accepted without an (explicit or implicit) termination proof: -```lean (keep := false) +```lean -keep def ack : (n m : Nat) → Option Nat | 0, y => some (y+1) | x+1, 0 => ack x 1 @@ -210,7 +210,7 @@ partial_fixpoint Recursive calls may also occur within higher-order functions such as {name}`List.mapM`, if they are set up appropriately, and {tech}[{keywordOf Lean.Parser.Term.do}`do`-notation]: -```lean (keep := false) +```lean -keep structure Tree where cs : List Tree def Tree.rev (t : Tree) : Option Tree := do @@ -227,7 +227,7 @@ partial_fixpoint Pattern matching on the result of the recursive call will prevent the definition by partial fixpoint from going through: -```lean (keep := false) (error := true) (name := monoMatch) +```lean -keep +error (name := monoMatch) def List.findIndex (xs : List α) (p : α → Bool) : Option Nat := match xs with | [] => none @@ -379,11 +379,11 @@ Instead, the definitions and theorems in `Lean.Order` are only intended as imple The notion of a partial order, and that of a chain-complete partial order, are represented by the type classes {name}`Lean.Order.PartialOrder` and {name}`Lean.Order.CCPO`, respectively. -{docstring Lean.Order.PartialOrder (allowMissing := true)} +{docstring Lean.Order.PartialOrder +allowMissing} -{docstring Lean.Order.CCPO (allowMissing := true)} +{docstring Lean.Order.CCPO +allowMissing} -```lean (show := false) +```lean -show section open Lean.Order variable {α : Type u} {β : Type v} [PartialOrder α] [PartialOrder β] (f : α → β) (x y : α) @@ -405,7 +405,7 @@ The fixpoint of a monotone function can be taken using {name}`fix`, which indeed To construct the partial fixpoint, Lean first synthesizes a suitable {name}`CCPO` instance. -```lean (show := false) +```lean -show section universe u v variable (α : Type u) @@ -417,7 +417,7 @@ variable (w : α) * Otherwise, if the function's type can be shown to be inhabited by a witness {lean}`w`, then the instance {name}`FlatOrder.instCCPO` for the wrapper type {lean}`FlatOrder w` is used. In this order, {lean}`w` is a least element and all other elements are incomparable. -```lean (show := false) +```lean -show end ``` @@ -425,7 +425,7 @@ end Next, the recursive calls in the right-hand side of the function definitions are abstracted; this turns into the argument `f` of {name}`fix`. The monotonicity requirement is solved by the {tactic}`monotonicity` tactic, which applies compositional monotonicity lemmas in a syntax-driven way. -```lean (show := false) +```lean -show section set_option linter.unusedVariables false variable {α : Sort u} {β : Sort v} [PartialOrder α] [PartialOrder β] (more : (x : α) → β) (x : α) @@ -442,7 +442,7 @@ The tactic solves goals of the form {lean}`monotone (fun x => … x …)` using * Zeta-reducing a {keywordOf Lean.Parser.Term.let}`let` expression when value and type do depend on {lean}`x`. * Applying lemmas annotated with {attr}`partial_fixpoint_monotone` -```lean (show := false) +```lean -show end ``` diff --git a/Manual/RecursiveDefs/Structural.lean b/Manual/RecursiveDefs/Structural.lean index 00437f87..ee9e3973 100644 --- a/Manual/RecursiveDefs/Structural.lean +++ b/Manual/RecursiveDefs/Structural.lean @@ -33,7 +33,7 @@ The rules that govern structural recursion are fundamentally _syntactic_ in natu There are many recursive definitions that exhibit structurally recursive computational behavior, but which are not accepted by these rules; this is a fundamental consequence of the analysis being fully automatic. {tech}[Well-founded recursion] provides a semantic approach to demonstrating termination that can be used in situations where a recursive function is not structurally recursive, but it can also be used when a function that computes according to structural recursion doesn't satisfy the syntactic requirements. -```lean (show := false) +```lean -show section variable (n n' : Nat) ``` @@ -48,7 +48,7 @@ def countdown (n : Nat) : List Nat := ``` Replacing pattern matching with an equivalent Boolean test and subtraction results in an error: -```lean (error := true) (name := countdown') (keep := false) +```lean +error (name := countdown') -keep def countdown' (n : Nat) : List Nat := if n == 0 then [] else @@ -90,7 +90,7 @@ def countdown' (n : Nat) : List Nat := Here, Lean's automation automatically constructs a termination proof from facts about propositional equality and subtraction. It uses well-founded recursion rather than structural recursion behind the scenes. ::: -```lean (show := false) +```lean -show end ``` @@ -112,7 +112,7 @@ When the signature specifies a function type, the decreasing parameter may addit When the decreasing parameter is a named parameter to the function, it can be specified by referring to its name. -```lean (keep := false) +```lean -keep def half (n : Nat) : Nat := match n with | 0 | 1 => 0 @@ -122,7 +122,7 @@ termination_by structural n When the decreasing parameter is not named in the signature, a name can be introduced locally in the {keywordOf Lean.Parser.Command.declaration}`termination_by` clause. -```lean (keep := false) +```lean -keep def half : Nat → Nat | 0 | 1 => 0 | n + 2 => half n + 1 @@ -158,7 +158,7 @@ The {deftech}_fixed prefix_ is the longest prefix of the function's parameters i The decreasing parameter's type must be an inductive type. In {lean}`notInductive`, a function is specified as the decreasing parameter: -```lean (error := true) (name := badnoindct) +```lean +error (name := badnoindct) def notInductive (x : Nat → Nat) : Nat := notInductive (fun n => x (n+1)) termination_by structural x @@ -171,7 +171,7 @@ cannot use specified measure for structural recursion: If the decreasing parameter is an indexed family, all the indices must be variables. In {lean}`constantIndex`, the indexed family {lean}`Fin'` is instead applied to a constant value: -```lean (error := true) (name := badidx) +```lean +error (name := badidx) inductive Fin' : Nat → Type where | zero : Fin' (n+1) | succ : Fin' n → Fin' (n+1) @@ -188,7 +188,7 @@ cannot use specified measure for structural recursion: The parameters of the decreasing parameter's type must not depend on function parameters that come after varying parameters or indices. In {lean}`afterVarying`, the {tech}[fixed prefix] is empty, because the first parameter `n` varies, so `p` is not part of the fixed prefix: -```lean (error := true) (name := badparam) +```lean +error (name := badparam) inductive WithParam' (p : Nat) : Nat → Type where | zero : WithParam' p (n+1) | succ : WithParam' p n → WithParam' p (n+1) @@ -209,18 +209,18 @@ Furthermore, every recursive call of the functions must be on a {deftech}_strict parameter. * The decreasing parameter itself is a sub-term, but not a strict sub-term. - * If a sub-term is the {tech key:="match discriminant"}[discriminant] of a {keywordOf Lean.Parser.Term.match}`match` expression or other pattern-matching syntax, the pattern that matches the discriminant is a sub-term in the {tech}[right-hand side] of each {tech}[match alternative]. + * If a sub-term is the {tech (key := "match discriminant")}[discriminant] of a {keywordOf Lean.Parser.Term.match}`match` expression or other pattern-matching syntax, the pattern that matches the discriminant is a sub-term in the {tech}[right-hand side] of each {tech}[match alternative]. In particular, the rules of {ref "match-generalization"}[match generalization] are used to connect the discriminant to the occurrences of the pattern term in the right-hand side; thus, it respects {tech}[definitional equality]. The pattern is a _strict_ sub-term if and only if the discriminant is a strict sub-term. * If a sub-term is a constructor applied to arguments, then its recursive arguments are strict sub-terms. -```lean (show := false) +```lean -show section variable (n : Nat) ``` ::::example "Nested Patterns and Sub-Terms" -In the following example, the decreasing parameter {lean}`n` is matched against the nested pattern {lean type:="Nat"}`.succ (.succ n)`. Therefore {lean type:="Nat"}`.succ (.succ n)` is a (non-strict) sub-term of {lean type:="Nat"}`n`, and consequently both {lean type:="Nat"}`n` and {lean type:="Nat"}`.succ n` are strict sub-terms, and the definition is accepted. +In the following example, the decreasing parameter {lean}`n` is matched against the nested pattern {lean (type := "Nat")}`.succ (.succ n)`. Therefore {lean (type := "Nat")}`.succ (.succ n)` is a (non-strict) sub-term of {lean (type := "Nat")}`n`, and consequently both {lean (type := "Nat")}`n` and {lean (type := "Nat")}`.succ n` are strict sub-terms, and the definition is accepted. ```lean def fib : Nat → Nat @@ -229,27 +229,27 @@ def fib : Nat → Nat termination_by structural n => n ``` -For clarity, this example uses {lean type:="Nat"}`.succ n` and {lean type:="Nat"}`.succ (.succ n)` instead of the equivalent {lean}`Nat`-specific {lean}`n+1` and {lean}`n+2`. +For clarity, this example uses {lean (type := "Nat")}`.succ n` and {lean (type := "Nat")}`.succ (.succ n)` instead of the equivalent {lean}`Nat`-specific {lean}`n+1` and {lean}`n+2`. :::TODO Link to where this special syntax is documented. ::: :::: -```lean (show := false) +```lean -show end ``` -```lean (show := false) +```lean -show section variable {α : Type u} (n n' : Nat) (xs : List α) ``` :::example "Matching on Complex Expressions Can Prevent Elaboration" -In the following example, the decreasing parameter {lean}`n` is not directly the {tech key:="match discriminant"}[discriminant] of the {keywordOf Lean.Parser.Term.match}`match` expression. +In the following example, the decreasing parameter {lean}`n` is not directly the {tech (key := "match discriminant")}[discriminant] of the {keywordOf Lean.Parser.Term.match}`match` expression. Therefore, {lean}`n'` is not considered a sub-term of {lean}`n`. -```lean (error := true) (keep := false) (name := badtarget) +```lean +error -keep (name := badtarget) def half (n : Nat) : Nat := match Option.some n with | .some (n' + 2) => half n' + 1 @@ -275,9 +275,9 @@ decreasing_by simp_all; omega ``` Similarly, the following example fails: although {lean}`xs.tail` would reduce to a strict sub-term of {lean}`xs`, this is not visible to Lean according to the rules above. -In particular, {lean}`xs.tail` is not {tech key:="definitional equality"}[definitionally equal] to a strict sub-term of {lean}`xs`. +In particular, {lean}`xs.tail` is not {tech (key := "definitional equality")}[definitionally equal] to a strict sub-term of {lean}`xs`. -```lean (error := true) (keep := false) +```lean +error -keep def listLen : List α → Nat | [] => 0 | xs => listLen xs.tail + 1 @@ -285,19 +285,19 @@ termination_by structural xs => xs ``` ::: -```lean (show := false) +```lean -show end ``` :::example "Simultaneous Matching vs Matching Pairs for Structural Recursion" -An important consequence of the strategies that are used to prove termination is that *simultaneous matching of two {tech key:="match discriminant"}[discriminants] is not equivalent to matching a pair*. +An important consequence of the strategies that are used to prove termination is that *simultaneous matching of two {tech (key := "match discriminant")}[discriminants] is not equivalent to matching a pair*. Simultaneous matching maintains the connection between the discriminants and the patterns, allowing the pattern matching to refine the types of the assumptions in the local context as well as the expected type of the {keywordOf Lean.Parser.Term.match}`match`. Essentially, the elaboration rules for {keywordOf Lean.Parser.Term.match}`match` treat the discriminants specially, and changing discriminants in a way that preserves the run-time meaning of a program does not necessarily preserve the compile-time meaning. This function that finds the minimum of two natural numbers is defined by structural recursion on its first parameter: -```lean (keep := false) +```lean -keep def min' (n k : Nat) : Nat := match n, k with | 0, _ => 0 @@ -307,7 +307,7 @@ termination_by structural n ``` Replacing the simultaneous pattern match on both parameters with a match on a pair causes termination analysis to fail: -```lean (error := true) (name := noMin) +```lean +error (name := noMin) def min' (n k : Nat) : Nat := match (n, k) with | (0, _) => 0 @@ -329,7 +329,7 @@ Wrapping the discriminants in a pair breaks the connection. :::example "Structural Recursion Under Pairs" This function that finds the minimum of the two components of a pair can't be elaborated via structural recursion. -```lean (error := true) (name := minpair) (keep := false) +```lean +error (name := minpair) -keep def min' (nk : Nat × Nat) : Nat := match nk with | (0, _) => 0 @@ -357,7 +357,7 @@ termination_by nk ``` ::: -```lean (show := false) +```lean -show section variable (n n' : Nat) ``` @@ -372,11 +372,11 @@ def countdown (n : Nat) : List Nat := termination_by structural n ``` -This is because {lean}`n' + 0` is {tech key:="definitional equality"}[definitionally equal] to {lean}`n'`, which is a strict sub-term of {lean}`n`. -{tech key:="strict sub-term"}[Sub-terms] that result from pattern matching are connected to the {tech key:="match discriminant"}[discriminant] using the rules for {ref "match-generalization"}[match generalization], which respect definitional equality. +This is because {lean}`n' + 0` is {tech (key := "definitional equality")}[definitionally equal] to {lean}`n'`, which is a strict sub-term of {lean}`n`. +{tech (key := "strict sub-term")}[Sub-terms] that result from pattern matching are connected to the {tech (key := "match discriminant")}[discriminant] using the rules for {ref "match-generalization"}[match generalization], which respect definitional equality. In {lean}`countdown'`, the recursive occurrence is applied to {lean}`0 + n'`, which is not definitionally equal to `n'` because addition on natural numbers is structurally recursive in its second parameter: -```lean (error := true) (name := countdownNonDefEq) +```lean +error (name := countdownNonDefEq) def countdown' (n : Nat) : List Nat := match n with | 0 => [] @@ -391,7 +391,7 @@ Cannot use parameter n: ``` ::: -```lean (show := false) +```lean -show end ``` @@ -540,12 +540,12 @@ When the body of the recursive function is transformed into an invocation of `br The analysis traverses the body of the function, looking for recursive calls. If the parameter is matched against, then its occurrences in the local context are {ref "match-generalization"}[generalized] and then instantiated with the pattern; this is also true for the type of the course-of-values table. Typically, this pattern matching results in the type of the course-of-values table becoming more specific, which gives access to the recursive results for smaller values. -This generalization process implements the rule that patterns are {tech key:="strict sub-term"}[sub-terms] of match discriminants. +This generalization process implements the rule that patterns are {tech (key := "strict sub-term")}[sub-terms] of match discriminants. When an recursive occurrence of the function is detected, the course-of-values table is consulted to see whether it contains a result for the argument being checked. If so, the recursive call can be replaced with a projection from the table. If not, then the parameter in question doesn't support structural recursion. -```lean (show := false) +```lean -show section ``` @@ -553,13 +553,13 @@ section The first step in walking through the elaboration of {name}`half` is to manually desugar it to a simpler form. This doesn't match the way Lean works, but its output is much easier to read when there are fewer {name}`OfNat` instances present. This readable definition: -```lean (keep := false) +```lean -keep def half : Nat → Nat | 0 | 1 => 0 | n + 2 => half n + 1 ``` can be rewritten to this somewhat lower-level version: -```lean (keep := false) +```lean -keep def half : Nat → Nat | .zero | .succ .zero => .zero | .succ (.succ n) => half n |>.succ @@ -567,7 +567,7 @@ def half : Nat → Nat The elaborator begins by elaborating a pre-definition in which recursion is still present but the definition is otherwise in Lean's core type theory. Turning on the compiler's tracing of pre-definitions, as well as making the pretty printer more explicit, makes the resulting pre-definition visible: -```lean (keep := false) (show := false) +```lean -keep -show -- Test of next block - visually check correspondence when updating! set_option trace.Elab.definition.body true in set_option pp.all true in @@ -641,7 +641,7 @@ def half' : Nat → Nat := To elaborate it as a structurally recursive function, the first step is to establish the `bRecOn` invocation. The definition must be marked {keywordOf Lean.Parser.Command.declaration}`noncomputable` because Lean does not support code generation for recursors such as {name}`Nat.brecOn`. -```lean (error := true) (keep := false) +```lean +error -keep noncomputable def half'' : Nat → Nat := fun (x : Nat) => @@ -658,7 +658,7 @@ def half'' : Nat → Nat := The next step is to replace occurrences of `x` in the original function body with the `n` provided by {name Nat.brecOn}`brecOn`. Because `table`'s type depends on `x`, it must also be generalized when splitting cases with {name}`half.match_1`, leading to a motive with an extra parameter. -```lean (error := true) (keep := false) (name := threeCases) +```lean +error -keep (name := threeCases) noncomputable def half'' : Nat → Nat := fun (x : Nat) => @@ -706,7 +706,7 @@ table : Nat.below n The first two cases in the pre-definition are constant functions, with no recursion to check: -```lean (error := true) (keep := false) (name := oneMore) +```lean +error -keep (name := oneMore) noncomputable def half'' : Nat → Nat := fun (x : Nat) => @@ -741,7 +741,7 @@ Nat ×' (Nat ×' Nat.below (motive := fun _ => Nat) n) → Nat ``` -```lean (show := false) +```lean -show example : ((n : Nat) → Nat.below (motive := fun _ => Nat) n.succ.succ → Nat) = ((n : Nat) → @@ -749,7 +749,7 @@ Nat ×' (Nat ×' Nat.below (motive := fun _ => Nat) n) → Nat) := rfl ``` -```lean (show := false) +```lean -show variable {n : Nat} ``` @@ -757,7 +757,7 @@ variable {n : Nat} The first {lean}`Nat` in the course-of-values table is the result of recursion on {lean}`n + 1`, and the second is the result of recursion on {lean}`n`. The recursive call can thus be replaced by a lookup, and the elaboration is successful: -```lean (error := true) (keep := false) (name := oneMore) +```lean +error -keep (name := oneMore) noncomputable def half'' : Nat → Nat := fun (x : Nat) => @@ -777,7 +777,7 @@ def half'' : Nat → Nat := The actual elaborator keeps track of the relationship between the parameter being checked for structural recursion and the positions in the course-of-values tables by inserting sentinel types with fresh names into the motive. ::: -```lean (show := false) +```lean -show end ``` diff --git a/Manual/RecursiveDefs/Structural/CourseOfValuesExample.lean b/Manual/RecursiveDefs/Structural/CourseOfValuesExample.lean index d7051e36..24f30db9 100644 --- a/Manual/RecursiveDefs/Structural/CourseOfValuesExample.lean +++ b/Manual/RecursiveDefs/Structural/CourseOfValuesExample.lean @@ -26,7 +26,7 @@ def List.below' {α : Type u} {motive : List α → Sort u} : | _ :: xs => motive xs ×' xs.below' (motive := motive) ``` -```lean (show := false) +```lean -show theorem List.below_eq_below' : @List.below = @List.below' := by funext α motive xs induction xs <;> simp [below'] @@ -53,7 +53,7 @@ def Tree.below' {α : Type u} {motive : Tree α → Sort u} : (motive right ×' right.below' (motive := motive)) ``` -```lean (show := false) +```lean -show theorem Tree.below_eq_below' : @Tree.below = @Tree.below' := by funext α motive t induction t @@ -130,7 +130,7 @@ def Tree.brecOn' {α : Type u} (t.brecOnTable (motive := motive) step).1 ``` -```lean (show := false) +```lean -show -- Proving the above-claimed equivalence is too time consuming, but evaluating a few examples will at least catch silly mistakes! /-- diff --git a/Manual/RecursiveDefs/Structural/RecursorExample.lean b/Manual/RecursiveDefs/Structural/RecursorExample.lean index bbfd84c8..cc9f1cc8 100644 --- a/Manual/RecursiveDefs/Structural/RecursorExample.lean +++ b/Manual/RecursiveDefs/Structural/RecursorExample.lean @@ -18,7 +18,7 @@ open Lean.Elab.Tactic.GuardMsgs.WhitespaceMode #doc (Manual) "Recursion Example (for inclusion elsewhere)" => -```lean (show := false) +```lean -show section variable (n k : Nat) (mot : Nat → Sort u) ``` @@ -117,6 +117,6 @@ This definition still works. However, it is now far from the original definition and it has become difficult for most people to understand. Recursors are an excellent logical foundation, but not an easy way to write programs or proofs. ::: -```lean (show := false) +```lean -show end ``` diff --git a/Manual/RecursiveDefs/WF.lean b/Manual/RecursiveDefs/WF.lean index 9ae9ff43..1cb22de4 100644 --- a/Manual/RecursiveDefs/WF.lean +++ b/Manual/RecursiveDefs/WF.lean @@ -29,7 +29,7 @@ This allows a larger class of recursive definitions to be accepted. Furthermore, when Lean's automation fails to construct a termination proof, it is possible to specify one manually. All definitions are treated identically by the Lean compiler. -In Lean's logic, definitions that use well-founded recursion typically do not reduce {tech key:="definitional equality"}[definitionally]. +In Lean's logic, definitions that use well-founded recursion typically do not reduce {tech (key := "definitional equality")}[definitionally]. The reductions do hold as propositional equalities, however, and Lean automatically proves them. This does not typically make it more difficult to prove properties of definitions that use well-founded recursion, because the propositional reductions can be used to reason about the behavior of the function. It does mean, however, that using these functions in types typically does not work well. @@ -79,7 +79,7 @@ In Lean, types that are equipped with a canonical well-founded relation are inst {docstring WellFoundedRelation} -```lean (show := false) +```lean -show section variable {α : Type u} {β : Type v} (a₁ a₂ : α) (b₁ b₂ : β) [WellFoundedRelation α] [WellFoundedRelation β] variable {γ : Type u} (x₁ x₂ : γ) [SizeOf γ] @@ -88,21 +88,21 @@ local notation x " ≺ " y => WellFoundedRelation.rel x y The most important instances are: -* {name}[`Nat`], ordered by {lean type:="Nat → Nat → Prop"}`(· < ·)`. +* {name}[`Nat`], ordered by {lean (type := "Nat → Nat → Prop")}`(· < ·)`. * {name}[`Prod`], ordered lexicographically: {lean}`(a₁, b₁) ≺ (a₂, b₂)` if and only if {lean}`a₁ ≺ a₂` or {lean}`a₁ = a₂` and {lean}`b₁ ≺ b₂`. * Every type that is an instance of the {name}`SizeOf` type class, which provides a method {name}`SizeOf.sizeOf`, has a well-founded relation. For these types, {lean}`x₁ ≺ x₂` if and only if {lean}`sizeOf x₁ < sizeOf x₂`. For {tech}[inductive types], a {lean}`SizeOf` instance is automatically derived by Lean. -```lean (show := false) +```lean -show end ``` Note that there exists a low-priority instance {name}`instSizeOfDefault` that provides a {lean}`SizeOf` instance for any type, and always returns {lean}`0`. This instance cannot be used to prove that a function terminates using well-founded recursion because {lean}`0 < 0` is false. -```lean (show := false) +```lean -show -- Check claims about instSizeOfDefault @@ -120,7 +120,7 @@ Function types in general do not have a well-founded relation that's useful for {ref "instance-synth"}[Instance synthesis] thus selects {name}`instSizeOfDefault` and the corresponding well-founded relation. If the measure is a function, the default {name}`SizeOf` instance is selected and the proof cannot succeed. -```lean (keep := false) +```lean -keep def fooInst (b : Bool → Bool) : Unit := fooInst (b ∘ b) termination_by b decreasing_by @@ -138,7 +138,7 @@ decreasing_by Once a {tech}[measure] is specified and its {tech}[well-founded relation] is determined, Lean determines the termination proof obligation for every recursive call. -```lean (show := false) +```lean -show section variable {α : Type u} {β : α → Type v} {β' : Type v} (more : β') (g : (x : α) → (y : β x) → β' → γ) [WellFoundedRelation γ] (a₁ p₁ : α) (a₂ : β a₁) (p₂ : β p₁) @@ -155,9 +155,9 @@ The proof obligation for each recursive call is of the form {lean}`g a₁ a₂ The context of the proof obligation is the local context of the recursive call. In particular, local assumptions (such as those introduced by `if h : _`, `match h : _ with ` or `have`) are available. -If a function parameter is the {tech key:="match discriminant"}[discriminant] of a pattern match (e.g. by a {keywordOf Lean.Parser.Term.match}`match` expression), then this parameter is refined to the matched pattern in the proof obligation. +If a function parameter is the {tech (key := "match discriminant")}[discriminant] of a pattern match (e.g. by a {keywordOf Lean.Parser.Term.match}`match` expression), then this parameter is refined to the matched pattern in the proof obligation. -```lean (show := false) +```lean -show end ``` @@ -166,7 +166,7 @@ By default, the tactic {tactic}`decreasing_trivial` is used to prove each proof A custom tactic script can be provided using the optional {keywordOf Lean.Parser.Command.declaration}`decreasing_by` clause, which comes after the {keywordOf Lean.Parser.Command.declaration}`termination_by` clause. This tactic script is run once, with one goal for each proof obligation, rather than separately on each proof obligation. -```lean (show := false) +```lean -show section variable {n : Nat} ``` @@ -175,7 +175,7 @@ variable {n : Nat} The following recursive definition of the Fibonacci numbers has two recursive calls, which results in two goals in the termination proof. -```lean (error := true) (keep := false) (name := fibGoals) +```lean +error -keep (name := fibGoals) def fib (n : Nat) := if h : n ≤ 1 then 1 @@ -186,7 +186,7 @@ decreasing_by skip ``` -```leanOutput fibGoals (whitespace := lax) (show := false) +```leanOutput fibGoals (whitespace := lax) -show unsolved goals n : Nat h : ¬n ≤ 1 @@ -220,7 +220,7 @@ The first proof goal requires the user to prove that the argument of the first r Both termination proofs can be easily discharged using the {tactic}`omega` tactic. -```lean (keep := false) +```lean -keep def fib (n : Nat) := if h : n ≤ 1 then 1 @@ -232,15 +232,15 @@ decreasing_by · omega ``` :::: -```lean (show := false) +```lean -show end ``` :::example "Refined Parameters" -If a parameter of the function is the {tech key:="match discriminant"}[discriminant] of a pattern match, then the proof obligations mention the refined parameter. +If a parameter of the function is the {tech (key := "match discriminant")}[discriminant] of a pattern match, then the proof obligations mention the refined parameter. -```lean (error := true) (keep := false) (name := fibGoals2) +```lean +error -keep (name := fibGoals2) def fib : Nat → Nat | 0 | 1 => 1 | .succ (.succ n) => fib (n + 1) + fib n @@ -248,7 +248,7 @@ termination_by n => n decreasing_by skip ``` -```leanOutput fibGoals2 (whitespace := lax) (show := false) +```leanOutput fibGoals2 (whitespace := lax) -show unsolved goals n : Nat ⊢ n + 1 < n.succ.succ @@ -284,7 +284,7 @@ This list is not exhaustive, and the mechanism is extensible. It is described in detail in {ref "well-founded-preprocessing"}[the section on preprocessing]. ::: -```lean (show := false) +```lean -show section variable {x : Nat} {xs : List Nat} {n : Nat} ``` @@ -294,7 +294,7 @@ variable {x : Nat} {xs : List Nat} {n : Nat} Here, the {keywordOf termIfThenElse}`if` does not add a local assumption about the condition (that is, whether {lean}`n ≤ 1`) to the local contexts in the branches. -```lean (error := true) (keep := false) (name := fibGoals3) +```lean +error -keep (name := fibGoals3) def fib (n : Nat) := if n ≤ 1 then 1 @@ -305,7 +305,7 @@ decreasing_by skip ``` -```leanOutput fibGoals3 (whitespace := lax) (show := false) +```leanOutput fibGoals3 (whitespace := lax) -show unsolved goals n : Nat h✝ : ¬n ≤ 1 @@ -336,7 +336,7 @@ h✝ : ¬n ≤ 1 Termination proof obligations in body of a {keywordOf Lean.Parser.Term.doFor}`for`​`…`​{keywordOf Lean.Parser.Term.doFor}`in` loop are also enriched, in this case with a {name}`Std.Range` membership hypothesis: -```lean (error := true) (keep := false) (name := nestGoal3) +```lean +error -keep (name := nestGoal3) def f (xs : Array Nat) : Nat := Id.run do let mut s := xs.sum for i in [:xs.size] do @@ -346,7 +346,7 @@ termination_by xs decreasing_by skip ``` -```leanOutput nestGoal3 (whitespace := lax) (show := false) +```leanOutput nestGoal3 (whitespace := lax) -show unsolved goals xs : Array Nat i : Nat @@ -365,14 +365,14 @@ h✝ : i ∈ [:xs.size] Similarly, in the following (contrived) example, the termination proof contains an additional assumption showing that {lean}`x ∈ xs`. -```lean (error := true) (keep := false) (name := nestGoal1) +```lean +error -keep (name := nestGoal1) def f (n : Nat) (xs : List Nat) : Nat := List.sum (xs.map (fun x => f x [])) termination_by xs decreasing_by skip ``` -```leanOutput nestGoal1 (whitespace := lax) (show := false) +```leanOutput nestGoal1 (whitespace := lax) -show unsolved goals n : Nat xs : List Nat @@ -397,7 +397,7 @@ h✝ : x ∈ xs This feature requires special setup for the higher-order function under which the recursive call is nested, as described in {ref "well-founded-preprocessing"}[the section on preprocessing]. In the following definition, identical to the one above except using a custom, equivalent function instead of {name}`List.map`, the proof obligation context is not enriched: -```lean (error := true) (keep := false) (name := nestGoal4) +```lean +error -keep (name := nestGoal4) def List.myMap := @List.map def f (n : Nat) (xs : List Nat) : Nat := List.sum (xs.myMap (fun x => f x [])) @@ -405,7 +405,7 @@ termination_by xs decreasing_by skip ``` -```leanOutput nestGoal4 (whitespace := lax) (show := false) +```leanOutput nestGoal4 (whitespace := lax) -show unsolved goals n : Nat xs : List Nat @@ -421,12 +421,12 @@ x : Nat ::: -```lean (show := false) +```lean -show end ``` -```lean (show := false) +```lean -show section ``` @@ -475,7 +475,7 @@ This tactic is intended to be extended with further heuristics using {keywordOf A classic example of a recursive function that needs a more complex {tech}[measure] is the Ackermann function: -```lean (keep := false) +```lean -keep def ack : Nat → Nat → Nat | 0, n => n + 1 | m + 1, 0 => ack m 1 @@ -498,7 +498,7 @@ Prod.Lex.right {α β} {ra : α → α → Prop} {rb : β → β → Prop} It fails, however, with the following modified function definition, where the third recursive call's first argument is provably smaller or equal to the first parameter, but not syntactically equal: -```lean (keep := false) (error := true) (name := synack) +```lean -keep +error (name := synack) def synack : Nat → Nat → Nat | 0, n => n + 1 | m + 1, 0 => synack m 1 @@ -525,7 +525,7 @@ Prod.Lex.right' {β} (rb : β → β → Prop) Prod.Lex Nat.lt rb (a₁, b₁) (a₂, b₂) ``` -```lean (keep := false) +```lean -keep def synack : Nat → Nat → Nat | 0, n => n + 1 | m + 1, 0 => synack m 1 @@ -577,7 +577,7 @@ This table shows up in the error message when no automatic measure could be foun {spliceContents Manual.RecursiveDefs.WF.GuessLexExample} -```lean (show := false) +```lean -show section variable {e₁ e₂ i j : Nat} ``` @@ -612,7 +612,7 @@ Try this: termination_by (j, j - i) ::: -```lean (show := false) +```lean -show end ``` @@ -625,7 +625,7 @@ The tactic indicated by {keywordOf Lean.Parser.Command.declaration}`decreasing_b A consequence is that a {keywordOf Lean.Parser.Command.declaration}`decreasing_by` block that addresses goals individually and which works successfully with an explicit termination argument can cause inference of the termination measure to fail: -```lean (keep := false) (error := true) +```lean -keep +error def ack : Nat → Nat → Nat | 0, n => n + 1 | m + 1, 0 => ack m 1 @@ -649,7 +649,7 @@ Because {tactic}`decreasing_tactic` avoids the need to backtrack by being incomp In this case, the error message is the one that results from the failing tactic rather than the one that results from being unable to find a measure. This is what happens in {lean}`notAck`: -```lean (error := true) (name := badInfer) +```lean +error (name := badInfer) def notAck : Nat → Nat → Nat | 0, n => n + 1 | m + 1, 0 => notAck m 1 @@ -767,7 +767,7 @@ ite_eq_dite {P : Prop} {α : Sort u} {a b : α} [Decidable P] : ``` -```lean (show := false) +```lean -show section variable (xs : List α) (p : α → Bool) (f : α → β) (x : α) ``` @@ -800,7 +800,7 @@ By separating the introduction of {name}`List.attach` from the propagation of th ::: -```lean (show := false) +```lean -show end ``` @@ -813,7 +813,7 @@ To see the preprocessed function definition, before and after the removal of {na # Theory and Construction -```lean (show := false) +```lean -show section variable {α : Type u} ``` @@ -864,8 +864,8 @@ The definition of division should satisfy the following equations: * {lean}`∀{n k : Nat}, (k > n) → div n k = 0` * {lean}`∀{n k : Nat}, (k ≠ 0) → (¬ k > n) → div n k = div (n - k) k` -This reduction behavior does not hold {tech key:="definitional equality"}[definitionally]: -```lean (error := true) (name := nonDef) (keep := false) +This reduction behavior does not hold {tech (key := "definitional equality")}[definitionally]: +```lean +error (name := nonDef) -keep theorem div.eq0 : div n 0 = 0 := by rfl ``` ```leanOutput nonDef diff --git a/Manual/RecursiveDefs/WF/GuessLexExample.lean b/Manual/RecursiveDefs/WF/GuessLexExample.lean index 76f85d6e..56d9a8a0 100644 --- a/Manual/RecursiveDefs/WF/GuessLexExample.lean +++ b/Manual/RecursiveDefs/WF/GuessLexExample.lean @@ -26,7 +26,7 @@ If there is no {keywordOf Lean.Parser.Command.declaration}`termination_by` claus If it fails, then it prints the table mentioned above. In this example, the {keywordOf Lean.Parser.Command.declaration}`decreasing_by` clause simply prevents Lean from also attempting structural recursion; this keeps the error message specific. -```lean (error := true) (keep := false) (name := badwf) +```lean +error -keep (name := badwf) def f : (n m l : Nat) → Nat | n+1, m+1, l+1 => [ f (n+1) (m+1) (l+1), diff --git a/Manual/RecursiveDefs/WF/PreprocessExample.lean b/Manual/RecursiveDefs/WF/PreprocessExample.lean index 0deac9c8..4b3991e9 100644 --- a/Manual/RecursiveDefs/WF/PreprocessExample.lean +++ b/Manual/RecursiveDefs/WF/PreprocessExample.lean @@ -55,7 +55,7 @@ inductive Tree (α : Type u) where A straightforward definition of the {name Tree.map}`map` function fails: -```lean (error := true) (keep := false) (name := badwf) +```lean +error -keep (name := badwf) def Tree.map (f : α → β) : Tree α → Tree β | leaf x => leaf (f x) | node p => node (p.map (fun t' => t'.map f)) @@ -74,12 +74,12 @@ t' : Tree α ``` :::paragraph -```lean (show := false) +```lean -show section variable (t' : Tree α) (p : Pair (Tree α)) ``` Clearly the proof obligation is not solvable, because nothing connects {lean}`t'` to {lean}`p`. -```lean (show := false) +```lean -show end ``` ::: @@ -121,7 +121,7 @@ def Pair.unattach {P : α → Prop} : {name Tree.map}`Tree.map` can now be defined by using {name}`Pair.attach` and {name}`Pair.sizeOf_lt_of_mem` explicitly: -```lean (keep := false) +```lean -keep def Tree.map (f : α → β) : Tree α → Tree β | leaf x => leaf (f x) | node p => node (p.attach.map (fun ⟨t', _⟩ => t'.map f)) @@ -156,7 +156,7 @@ theorem Pair.map_unattach {P : α → Prop} Now the function body can be written without extra considerations, and the membership assumption is still available to the termination proof. -```lean (keep := false) +```lean -keep def Tree.map (f : α → β) : Tree α → Tree β | leaf x => leaf (f x) | node p => node (p.map (fun t' => t'.map f)) diff --git a/Manual/Runtime.lean b/Manual/Runtime.lean index b289d981..aa227366 100644 --- a/Manual/Runtime.lean +++ b/Manual/Runtime.lean @@ -29,7 +29,7 @@ These services include: Lean does not require programmers to manually manage memory. Space is allocated when needed to store a value, and values that can no longer be reached (and are thus irrelevant) are deallocated. - In particular, Lean uses {tech key:="reference count"}[reference counting], where each allocated object maintains a count of incoming references. + In particular, Lean uses {tech (key := "reference count")}[reference counting], where each allocated object maintains a count of incoming references. The compiler emits calls to memory management routines that allocate memory and modify reference counts, and these routines are provided by the runtime, along with the data structures that represent Lean values in compiled code. : Multiple Threads @@ -70,7 +70,7 @@ A field of type {lean}`Bool` in an inductive type's constructor is represented u tag := "reference-counting" %%% -Lean uses {deftech key:="reference count"}_reference counting_ for memory management. +Lean uses {deftech (key := "reference count")}_reference counting_ for memory management. Each allocated object maintains a count of how many other objects refer to it. When a new reference is added, the count is incremented, and when a reference is dropped, the count is decremented. When a reference count reaches zero, the object is no longer reachable and can play no part in the further execution of the program. @@ -360,7 +360,7 @@ For simple examples of how to call foreign code from Lean and vice versa, see [t :::leanSection -```lean (show := false) +```lean -show variable {α₁ αₙ β αᵢ} private axiom «α₂→…→αₙ₋₁».{u} : Type u local macro "..." : term => ``(«α₂→…→αₙ₋₁») @@ -371,7 +371,7 @@ It is based on the standard C ABI and calling convention of the target platform. Lean declarations can be marked for interaction with foreign functions using either the attribute {attr}`extern "sym"`, which causes compiled code to use the C declaration {c}`sym` as the implementation, or the attribute {attr}`export sym`, which makes the declaration available as {c}`sym` to C. In both cases, the C declaration's type is derived from the Lean type of the declaration with the attribute. -Let {lean}`α₁ → ... → αₙ → β` be the declaration's {tech key:="normal form"}[normalized] type. +Let {lean}`α₁ → ... → αₙ → β` be the declaration's {tech (key := "normal form")}[normalized] type. If `n` is 0, the corresponding C declaration is ```c extern s sym; @@ -393,17 +393,17 @@ In the case of {attr}`extern`, all {tech}[irrelevant] types are removed first. tag := "ffi-types" %%% -```lean (show := false) +```lean -show universe u variable (p : Prop) private axiom «...» : Sort u local macro "..." : term => ``(«...») ``` -In the {tech key:="application binary interface"}[ABI], Lean types are translated to C types as follows: +In the {tech (key := "application binary interface")}[ABI], Lean types are translated to C types as follows: * The integer types {lean}`UInt8`, …, {lean}`UInt64`, {lean}`USize` are represented by the C types {c}`uint8_t`, ..., {c}`uint64_t`, {c}`size_t`, respectively. - If their {ref "fixed-int-runtime"}[run-time representation] requires {tech key:="boxed"}[boxing], then they are unboxed at the FFI boundary. + If their {ref "fixed-int-runtime"}[run-time representation] requires {tech (key := "boxed")}[boxing], then they are unboxed at the FFI boundary. * {lean}`Char` is represented by {c}`uint32_t`. * {lean}`Float` is represented by {c}`double`. * {name}`Nat` and {name}`Int` are represented by {c}`lean_object *`. @@ -413,7 +413,7 @@ In the {tech key:="application binary interface"}[ABI], Lean types are translate It is the same as the {ref "run-time-inductives"}[run-time representation] of these types. Its runtime value is either a pointer to an object of a subtype of {c}`lean_object` (see the "Inductive types" section below) or it is the value {c}`lean_box(cidx)` for the {c}`cidx`th constructor of an inductive type if this constructor does not have any relevant parameters. - ```lean (show := false) + ```lean -show variable (u : Unit) ``` @@ -445,7 +445,7 @@ Parameters may be marked as {tech}[borrowed] by prefixing their types with {keyw tag := "ffi-initialization" %%% -When including Lean code in a larger program, modules must be {deftech key:="initialize"}_initialized_ before accessing any of their declarations. +When including Lean code in a larger program, modules must be {deftech (key := "initialize")}_initialized_ before accessing any of their declarations. Module initialization entails: * initialization of all “constant definitions” (nullary functions), including closed terms lifted out of other functions, * execution of all code marked with the {attr}`init` attribute, and diff --git a/Manual/Simp.lean b/Manual/Simp.lean index d2cbaaab..c32000e8 100644 --- a/Manual/Simp.lean +++ b/Manual/Simp.lean @@ -95,7 +95,7 @@ In other words, an invocation of a simplification tactic takes the following mod ::::example "Location specifiers for {tactic}`simp`" :::tacticExample -{goal show:=false}`∀ (p : Nat → Prop) (x : Nat) (h : p (x + 5 + 2)) (h' : p (3 + x + 9)), p (6 + x + 1)` +{goal -show}`∀ (p : Nat → Prop) (x : Nat) (h : p (x + 5 + 2)) (h' : p (3 + x + 9)), p (6 + x + 1)` ```setup intro p x h h' ``` @@ -121,11 +121,11 @@ h' : p (3 + x + 9) ::: :::tacticExample -{goal show:=false}`∀ (p : Nat → Prop) (x : Nat) (h : p (x + 5 + 2)) (h' : p (3 + x + 9)), p (6 + x + 1)` +{goal -show}`∀ (p : Nat → Prop) (x : Nat) (h : p (x + 5 + 2)) (h' : p (3 + x + 9)), p (6 + x + 1)` ```setup intro p x h h' ``` -```pre (show := false) +```pre -show p : Nat → Prop x : Nat h : p (x + 5 + 2) @@ -145,11 +145,11 @@ h : p (x + 7) ::: :::tacticExample -{goal show:=false}`∀ (p : Nat → Prop) (x : Nat) (h : p (x + 5 + 2)) (h' : p (3 + x + 9)), p (6 + x + 1)` +{goal -show}`∀ (p : Nat → Prop) (x : Nat) (h : p (x + 5 + 2)) (h' : p (3 + x + 9)), p (6 + x + 1)` ```setup intro p x h h' ``` -```pre (show := false) +```pre -show p : Nat → Prop x : Nat h : p (x + 5 + 2) @@ -169,11 +169,11 @@ h : p (x + 7) ::: :::tacticExample -{goal show:=false}`∀ (p : Nat → Prop) (x : Nat) (h : p (x + 5 + 2)) (h' : p (3 + x + 9)), p (6 + x + 1)` +{goal -show}`∀ (p : Nat → Prop) (x : Nat) (h : p (x + 5 + 2)) (h' : p (3 + x + 9)), p (6 + x + 1)` ```setup intro p x h h' ``` -```pre (show := false) +```pre -show p : Nat → Prop x : Nat h : p (x + 5 + 2) @@ -216,7 +216,7 @@ The simplifier has three kinds of rewrite rules: The simplifier supports simplification procedures, known as {deftech}_simprocs_, that use Lean metaprogramming to perform rewrites that can't be efficiently specified using equations. Lean includes simprocs for the most important operations on built-in types. :::keepEnv -```lean (show := false) +```lean -show -- Validate the above description of reducibility @[irreducible] @@ -290,7 +290,7 @@ They are preprocessed into rules that rewrite the proposition to {lean}`True`. :::::example "Rewriting Propositions" ::::tacticExample -{goal show:=false}`∀(α β : Type) (w y : α) (x z : β), (w, x) = (y, z)` +{goal -show}`∀(α β : Type) (w y : α) (x z : β), (w, x) = (y, z)` ```setup intro α β w y x z ``` @@ -337,7 +337,7 @@ The `only` modifier to the {tactic}`simp` tactic causes it to start with an empt Rules are added to the default simp set using the {attr}`simp` attribute. -:::syntax attr alias := Lean.Meta.simpExtension (title := "Registering {keyword}`simp` Lemmas") +:::syntax attr (alias := Lean.Meta.simpExtension) (title := "Registering {keyword}`simp` Lemmas") The {attr}`simp` attribute adds a declaration to the default simp set. If the declaration is a definition, the definition is marked for unfolding; if it is a theorem, then the theorem is registered as a rewrite rule. @@ -358,7 +358,7 @@ simp ↓ $p? simp $p:prio ``` -```lean (show := false) +```lean -show -- Check above claim about default priority /-- info: 1000 -/ #check_msgs in diff --git a/Manual/SourceFiles.lean b/Manual/SourceFiles.lean index 0476ae14..08a2247d 100644 --- a/Manual/SourceFiles.lean +++ b/Manual/SourceFiles.lean @@ -98,7 +98,7 @@ Letters are English letters, upper- or lowercase, and the letter-like characters Identifier continuation characters consist of letters, letter-like characters, underscores (`'_'`), exclamation marks (`!`), question marks (`?`), subscripts, and single quotes (`'`). As an exception, underscore alone is not a valid identifier. -```lean (show := false) +```lean -show def validIdentifier (str : String) : IO String := Lean.Parser.identFn.test str @@ -165,7 +165,7 @@ The guillemets are not part of the resulting identifier component, so `«x»` an -```lean (show := false) +```lean -show /-- info: "Success! Final stack:\n `«\n »\nAll input consumed." -/ #check_msgs in #eval validIdentifier "«\n»" @@ -197,7 +197,7 @@ tag := "module-structure" %%% -:::syntax Lean.Parser.Module.module (open := false) (title := "Modules") +:::syntax Lean.Parser.Module.module -open (title := "Modules") ```grammar $hdr:header $cmd:command* ``` @@ -216,7 +216,7 @@ tag := "module-headers" Module headers list the modules that should be elaborated prior to the current module. Their declarations are visible in the current module. -:::syntax Lean.Parser.Module.header (open := false) (title := "Module Headers") +:::syntax Lean.Parser.Module.header -open (title := "Module Headers") The module header consists of a sequence of {deftech}[`import` statements]: ```grammar $i:import* @@ -231,7 +231,7 @@ $i:import* If present, the {keyword}`prelude` keyword indicates that the module is part of the implementation of the Lean {deftech}_prelude_, which is the code that is available without explicitly importing any modules—it should not be used outside of Lean's implementation. -:::syntax Lean.Parser.Module.prelude (open := false) (title := "Prelude Modules") +:::syntax Lean.Parser.Module.prelude -open (title := "Prelude Modules") ```grammar prelude ``` @@ -274,7 +274,7 @@ tag := "module-contents" %%% When Lean elaborates a module, the result is an {TODO}[def and xref] environment. -The environment includes the constants, {tech}[inductive types], {tech}[theorems], {tech key:="type class"}[type classes], {tech}[instances], and everything else declared in the module, along with side tables that track data as diverse as {tech}[simp sets], namespace aliases, and {tech}[documentation comments]. +The environment includes the constants, {tech}[inductive types], {tech}[theorems], {tech (key := "type class")}[type classes], {tech}[instances], and everything else declared in the module, along with side tables that track data as diverse as {tech}[simp sets], namespace aliases, and {tech}[documentation comments]. As the module is processed by Lean, commands add content to the environment. A module's environment can be serialized to a {deftech (key:="olean")}[`.olean` file], which contains both the environment and a compacted heap region with the run-time objects needed by the environment. diff --git a/Manual/Tactics.lean b/Manual/Tactics.lean index 8a3094aa..f7ab528a 100644 --- a/Manual/Tactics.lean +++ b/Manual/Tactics.lean @@ -39,7 +39,7 @@ Tactics are imperative programs that modify a {deftech}_proof state_.{index}[pro A proof state consists of an ordered sequence of {deftech}_goals_, which are contexts of local assumptions together with types to be inhabited; a tactic may either _succeed_ with a possibly-empty sequence of further goals (called {deftech}_subgoals_) or _fail_ if it cannot make progress. If a tactic succeeds with no subgoals, then the proof is complete. If it succeeds with one or more subgoals, then its goal or goals will be proved when those subgoals have been proved. -The first goal in the proof state is called the {deftech}_main goal_.{index subterm:="main"}[goal]{index}[main goal] +The first goal in the proof state is called the {deftech}_main goal_.{index (subterm := "main")}[goal]{index}[main goal] While most tactics affect only the main goal, operators such as {tactic}`<;>` and {tactic}`all_goals` can be used to apply a tactic to many goals, and operators such as bullets, {tactic}`next` or {tactic}`case` can narrow the focus of subsequent tactics to only a single goal in the proof state. Behind the scenes, tactics construct {deftech}[proof terms]. @@ -91,7 +91,7 @@ Tactics assign goal names, typically on the basis of constructor names, paramete This proof state contains four goals, all of which are named. This is part of a proof that the {lean}`Monad Option` instance is lawful (that is, to provide the {lean}`LawfulMonad Option` instance), and the case names (highlighted below) come from the names of the fields of {name}`LawfulMonad`. -```proofState tag:="lawful-option-cases" +```proofState (tag := "lawful-option-cases") LawfulMonad Option := by constructor intro α β f x @@ -145,7 +145,7 @@ After {tacticStep}`induction k`, the two new cases' names have `zero` as a prefi #hierarchical-case-names .goal:not(:last-child) .goal-name { background-color: var(--lean-compl-yellow); } ``` -```post tag:="hierarchical-case-names" +```post (tag := "hierarchical-case-names") case zero.zero ⊢ 0 + 0 = 0 + 0 @@ -175,7 +175,7 @@ Assumptions are either arbitrary elements of some type or statements that are pr This goal has four assumptions: -```proofState tag:="ex-assumption-names" +```proofState (tag := "ex-assumption-names") ∀ (α) (xs : List α), xs ++ [] = xs := by intro α xs induction xs @@ -184,7 +184,7 @@ rename_i x xs ih ``` :::keepEnv -```lean show:=false +```lean -show axiom α : Type axiom x : α axiom xs : List α @@ -203,7 +203,7 @@ The conclusion is the statement that prepending `x` to both sides of the equalit :::: -Some assumptions are {deftech}_inaccessible_, {index}[inaccessible] {index subterm:="inaccessible"}[assumption] which means that they cannot be referred to explicitly by name. +Some assumptions are {deftech}_inaccessible_, {index}[inaccessible] {index (subterm := "inaccessible")}[assumption] which means that they cannot be referred to explicitly by name. Inaccessible assumptions occur when an assumption is created without a specified name or when the assumption's name is shadowed by a later assumption. Inaccessible assumptions should be regarded as anonymous; they are presented as if they had names because they may be referred to in later assumptions or in the conclusion, and displaying a name allows these references to be distinguished from one another. In particular, inaccessible assumptions are presented with daggers (`†`) after their names. @@ -216,7 +216,7 @@ In particular, inaccessible assumptions are presented with daggers (`†`) after In this proof state, all assumptions are accessible. -```proofState tag:="option-cases-accessible" +```proofState (tag := "option-cases-accessible") LawfulMonad Option := by constructor intro α β f x @@ -239,7 +239,7 @@ rotate_right In this proof state, only the first and third assumptions are accessible. The second and fourth are inaccessible, and their names include a dagger to indicate that they cannot be referenced. -```proofState tag:="option-cases-inaccessible" +```proofState (tag := "option-cases-inaccessible") LawfulMonad Option := by constructor intro α _ f _ @@ -272,7 +272,7 @@ This can be used to refer to local lemmas by their theorem statement rather than ::::example "Assumptions by Type" :::keepEnv -```lean (show := false) +```lean -show variable (n : Nat) ``` In the following proof, {tactic}`cases` is repeatedly used to analyze a number. @@ -294,7 +294,7 @@ example : x < 3 → x ∈ [0, 1, 2] := by Single-guillemet syntax also works outside of proofs: -```lean name:=evalGuillemets +```lean (name := evalGuillemets) #eval let x := 1 let y := 2 @@ -401,7 +401,7 @@ elem : x ∈ xs :::tacticExample -{goal show:=false}`∀ (i j k : Nat), i < j → j < k → i < k` +{goal -show}`∀ (i j k : Nat), i < j → j < k → i < k` ```setup intros i j k h1 h2 @@ -439,7 +439,7 @@ h2 : j < k ::::example "Explicitly-Created Metavariables" :::tacticExample -{goal show:=false}`∀ (i j k : Nat), i < j → j < k → i < k` +{goal -show}`∀ (i j k : Nat), i < j → j < k → i < k` ```setup intros i j k h1 h2 @@ -548,11 +548,11 @@ While terms are expected to be executed once the values of their variables are k Thus, when {keyword}`if` and {keyword}`match` are used in tactics, their meaning is reasoning by cases rather than selection of a concrete branch. All of their branches are executed, and the condition or pattern match is used to refine the main goal with more information in each branch, rather than to select a single branch. -:::tactic Lean.Parser.Tactic.tacIfThenElse show := "if ... then ... else ..." +:::tactic Lean.Parser.Tactic.tacIfThenElse (show := "if ... then ... else ...") ::: -:::tactic Lean.Parser.Tactic.tacDepIfThenElse show:= "if h : ... then ... else ..." +:::tactic Lean.Parser.Tactic.tacDepIfThenElse (show := "if h : ... then ... else ...") ::: :::example "Reasoning by cases with `if`" @@ -632,7 +632,7 @@ If the tactic fails on any of the {tech}[subgoals], then the whole {tactic}`<;>` ``` -{goal show := false}`∀x, x = 1 ∨ x = 2 → x < 3` +{goal -show}`∀x, x = 1 ∨ x = 2 → x < 3` In this proof state: ```pre @@ -660,9 +660,9 @@ h✝ : x = 2 intro x h ``` -{goal show := false}`∀x, x = 1 ∨ x = 2 → x < 3` +{goal -show}`∀x, x = 1 ∨ x = 2 → x < 3` -```pre (show := false) +```pre -show x : Nat h : x = 1 ∨ x = 2 ⊢ x < 3 @@ -684,9 +684,9 @@ h✝ : x = 2 intro x h ``` -{goal show := false}`∀x, x = 1 ∨ x = 2 → x < 3` +{goal -show}`∀x, x = 1 ∨ x = 2 → x < 3` -```pre (show := false) +```pre -show x : Nat h : x = 1 ∨ x = 2 ⊢ x < 3 @@ -725,7 +725,7 @@ tag := "tactic-language-focusing" Focusing tactics remove some subset of the proof goals (typically leaving only the main goal) from the consideration of some further tactics. In addition to the tactics described here, the {tactic}`case` and {tactic}`case'` tactics focus on the selected goal. -:::tactic Lean.cdot show:="·" +:::tactic Lean.cdot (show := "·") It is generally considered good Lean style to use bullets whenever a tactic line results in more than one new subgoal. This makes it easier to read and maintain proofs, because the connections between steps of reasoning are more clear and any change in the number of subgoals while editing the proof will have a localized effect. @@ -766,7 +766,7 @@ These proof terms exist in a local context, because assumptions in proof states Uses of assumptions correspond to variable references. It is very important that the naming of assumptions be predictable; otherwise, small changes to the internal implementation of a tactic could either lead to variable capture or to a broken reference if they cause different names to be selected. -Lean's tactic language is _hygienic_. {index subterm := "in tactics"}[hygiene] +Lean's tactic language is _hygienic_. {index (subterm := "in tactics")}[hygiene] This means that the tactic language respects lexical scope: names that occur in a tactic refer to the enclosing binding in the source code, rather than being determined by the generated code, and the tactic framework is responsible for maintaining this property. Variable references in tactic scripts refer either to names that were in scope at the beginning of the script or to bindings that were explicitly introduced as part of the tactics, rather than to the names chosen for use in the proof term behind the scenes. @@ -869,10 +869,10 @@ Generally speaking, {tactic}`have` should be used when proving an intermediate l :::tactic Lean.Parser.Tactic.tacticHave' ::: -:::tactic Lean.Parser.Tactic.tacticLet__ show:="let" +:::tactic Lean.Parser.Tactic.tacticLet__ (show := "let") ::: -:::tactic Lean.Parser.Tactic.letrec show:="let rec" +:::tactic Lean.Parser.Tactic.letrec (show := "let rec") ::: :::tactic Lean.Parser.Tactic.tacticLetI__ @@ -886,18 +886,18 @@ Generally speaking, {tactic}`have` should be used when proving an intermediate l tag := "tactic-config" %%% -Many tactics are configurable.{index subterm:="of tactics"}[configuration] +Many tactics are configurable.{index (subterm := "of tactics")}[configuration] By convention, tactics share a configuration syntax, described using {syntaxKind}`optConfig`. The specific options available to each tactic are described in the tactic's documentation. -:::syntax Lean.Parser.Tactic.optConfig (open := false) (title := "Tactic Configuration") +:::syntax Lean.Parser.Tactic.optConfig -open (title := "Tactic Configuration") A tactic configuration consists of zero or more {deftech}[configuration items]: ```grammar $x:configItem* ``` ::: -:::syntax Lean.Parser.Tactic.configItem (open := false) (title := "Tactic Configuration Items") +:::syntax Lean.Parser.Tactic.configItem -open (title := "Tactic Configuration Items") Each configuration item has a name that corresponds to an underlying tactic option. Boolean options may be enabled or disabled using prefix `+` and `-`: ```grammar @@ -927,10 +927,10 @@ tag := "tactic-language-namespaces-options" Namespaces and options can be adjusted in tactic scripts using the same syntax as in terms. -:::tactic Lean.Parser.Tactic.set_option show:="set_option" +:::tactic Lean.Parser.Tactic.set_option (show := "set_option") ::: -:::tactic Lean.Parser.Tactic.open show:="open" +:::tactic Lean.Parser.Tactic.open (show := "open") ::: ### Controlling Unfolding diff --git a/Manual/Tactics/Conv.lean b/Manual/Tactics/Conv.lean index 531507a0..111ecca8 100644 --- a/Manual/Tactics/Conv.lean +++ b/Manual/Tactics/Conv.lean @@ -84,28 +84,28 @@ tag := "conv-control" %%% -:::conv first show := "first" +:::conv first (show := "first") ::: -:::conv convTry_ show := "try" +:::conv convTry_ (show := "try") ::: -:::conv «conv_<;>_» (show:="<;>") (allowMissing := true) +:::conv «conv_<;>_» (show:="<;>") +allowMissing ::: -:::conv convRepeat_ show := "repeat" +:::conv convRepeat_ (show := "repeat") ::: -:::conv skip show:= "skip" +:::conv skip (show := "skip") ::: -:::conv nestedConv show:= "{ ... }" +:::conv nestedConv (show := "{ ... }") ::: -:::conv paren show:= "( ... )" +:::conv paren (show := "( ... )") ::: -:::conv convDone show:= "done" +:::conv convDone (show := "done") ::: # Goal Selection @@ -114,31 +114,31 @@ tag := "conv-goals" %%% -:::conv allGoals show:= "all_goals" +:::conv allGoals (show := "all_goals") ::: -:::conv anyGoals show:= "any_goals" +:::conv anyGoals (show := "any_goals") ::: -:::conv case show:= "case ... => ..." +:::conv case (show := "case ... => ...") ::: -:::conv case' show:= "case' ... => ..." +:::conv case' (show := "case' ... => ...") ::: -:::conv «convNext__=>_» show:= "next ... => ..." +:::conv «convNext__=>_» (show := "next ... => ...") ::: -:::conv focus show := "focus" +:::conv focus (show := "focus") ::: -:::conv «conv·._» show := ". ..." +:::conv «conv·._» (show := ". ...") ::: -:::conv «conv·._» show := "· ..." +:::conv «conv·._» (show := "· ...") ::: -:::conv failIfSuccess show := "fail_if_success" +:::conv failIfSuccess (show := "fail_if_success") ::: @@ -148,19 +148,19 @@ tag := "conv-nav" %%% -:::conv lhs show:= "lhs" +:::conv lhs (show := "lhs") ::: -:::conv rhs show:= "rhs" +:::conv rhs (show := "rhs") ::: -:::conv fun show:= "fun" +:::conv fun (show := "fun") ::: -:::conv congr show:= "congr" +:::conv congr (show := "congr") ::: -:::conv arg show:= "arg [@]i" +:::conv arg (show := "arg [@]i") ::: :::syntax Lean.Parser.Tactic.Conv.enterArg (title := "Arguments to {keyword}`enter`") @@ -175,26 +175,26 @@ $x:ident ``` ::: -:::conv enter show := "enter" +:::conv enter (show := "enter") ::: -:::conv pattern show:= "pattern" +:::conv pattern (show := "pattern") ::: -:::conv ext show:= "ext" +:::conv ext (show := "ext") ::: -:::conv convArgs show := "args" +:::conv convArgs (show := "args") ::: -:::conv convLeft show := "left" +:::conv convLeft (show := "left") ::: -:::conv convRight show := "right" +:::conv convRight (show := "right") ::: -:::conv convIntro___ show := "intro" +:::conv convIntro___ (show := "intro") ::: # Changing the Goal @@ -208,19 +208,19 @@ tag := "conv-reduction" %%% -:::conv whnf show:= "whnf" +:::conv whnf (show := "whnf") ::: -:::conv reduce show:= "reduce" +:::conv reduce (show := "reduce") ::: -:::conv zeta show:= "zeta" +:::conv zeta (show := "zeta") ::: -:::conv delta show:= "delta" +:::conv delta (show := "delta") ::: -:::conv unfold show:= "unfold" +:::conv unfold (show := "unfold") ::: ## Simplification @@ -228,13 +228,13 @@ tag := "conv-reduction" tag := "conv-simp" %%% -:::conv simp show:= "simp" +:::conv simp (show := "simp") ::: -:::conv dsimp show:= "dsimp" +:::conv dsimp (show := "dsimp") ::: -:::conv simpMatch show:= "simp_match" +:::conv simpMatch (show := "simp_match") ::: ## Rewriting @@ -242,19 +242,19 @@ tag := "conv-simp" tag := "conv-rw" %%% -:::conv change show:= "change" +:::conv change (show := "change") ::: -:::conv rewrite show:= "rewrite" +:::conv rewrite (show := "rewrite") ::: -:::conv convRw__ show := "rw" +:::conv convRw__ (show := "rw") ::: -:::conv convErw__ show := "erw" +:::conv convErw__ (show := "erw") ::: -:::conv convApply_ show := "apply" +:::conv convApply_ (show := "apply") ::: # Nested Tactics @@ -266,16 +266,16 @@ tag := "conv-nested" :::tactic Lean.Parser.Tactic.Conv.convTactic ::: -:::conv nestedTactic show:= "tactic" +:::conv nestedTactic (show := "tactic") ::: -:::conv nestedTacticCore show:= "tactic'" +:::conv nestedTacticCore (show := "tactic'") ::: -:::tactic Lean.Parser.Tactic.Conv.convTactic show:= "conv'" +:::tactic Lean.Parser.Tactic.Conv.convTactic (show := "conv'") ::: -:::conv convConvSeq show := "conv => ..." +:::conv convConvSeq (show := "conv => ...") ::: @@ -284,7 +284,7 @@ tag := "conv-nested" tag := "conv-debug" %%% -:::conv convTrace_state show:= "trace_state" +:::conv convTrace_state (show := "trace_state") ::: @@ -293,8 +293,8 @@ tag := "conv-debug" tag := "conv-other" %%% -:::conv convRfl show:= "rfl" +:::conv convRfl (show := "rfl") ::: -:::conv normCast show := "norm_cast" +:::conv normCast (show := "norm_cast") ::: diff --git a/Manual/Tactics/Custom.lean b/Manual/Tactics/Custom.lean index 38b7df29..41ea21f1 100644 --- a/Manual/Tactics/Custom.lean +++ b/Manual/Tactics/Custom.lean @@ -29,7 +29,7 @@ tag := "custom-tactics" %%% -```lean (show := false) +```lean -show open Lean ``` @@ -69,7 +69,7 @@ example : 0 ≤ 4 := by ::: :::: -Like other Lean macros, tactic macros are {tech key:="hygiene"}[hygienic]. +Like other Lean macros, tactic macros are {tech (key := "hygiene")}[hygienic]. References to global names are resolved when the macro is defined, and names introduced by the tactic macro cannot capture names from its invocation site. When defining a tactic macro, it's important to specify that the syntax being matched or constructed is for the syntax category `tactic`. @@ -90,7 +90,7 @@ This is used to make a number of Lean's built-in tactics extensible—new behavi The {tactic}`trivial`, which is used by many other tactics to quickly dispatch subgoals that are not worth bothering the user with, is designed to be extended through new macro expansions. Lean's default {lean}`trivial` can't solve {lean}`IsEmpty []` goals: -```lean (error := true) +```lean +error def IsEmpty (xs : List α) : Prop := ¬ xs ≠ [] diff --git a/Manual/Tactics/Reference.lean b/Manual/Tactics/Reference.lean index 248c43b7..7849884c 100644 --- a/Manual/Tactics/Reference.lean +++ b/Manual/Tactics/Reference.lean @@ -199,7 +199,7 @@ tag := "tactic-ref-goals" :::tactic "change" ::: -:::tactic Lean.Parser.Tactic.changeWith show:="change ... with ..." +:::tactic Lean.Parser.Tactic.changeWith (show := "change ... with ...") ::: :::tactic "generalize" @@ -284,13 +284,13 @@ tag := "tactic-ref-rw" :::tactic Lean.Parser.Tactic.tacticRwa__ ::: -{docstring Lean.Meta.Rewrite.Config (allowMissing := true)} +{docstring Lean.Meta.Rewrite.Config +allowMissing} {docstring Lean.Meta.Occurrences} -{docstring Lean.Meta.TransparencyMode (allowMissing := true)} +{docstring Lean.Meta.TransparencyMode +allowMissing} -{docstring Lean.Meta.Rewrite.NewGoals (allowMissing := true)} +{docstring Lean.Meta.Rewrite.NewGoals +allowMissing} :::tactic "unfold" @@ -340,7 +340,7 @@ Elimination tactics use {ref "recursors"}[recursors] and the automatically-deriv The {tech}[subgoals] that result from these tactics are determined by the types of the minor premises of the eliminators, and using different eliminators with the {keyword}`using` option results in different subgoals. :::::leanSection -```lean (show := false) +```lean -show variable {n : Nat} ``` ::::example "Choosing Eliminators" @@ -349,9 +349,9 @@ variable {n : Nat} ```setup intro n i ``` -{goal show:= false}`∀(n : Nat) (i : Fin (n + 1)), 0 + i = i` +{goal -show}`∀(n : Nat) (i : Fin (n + 1)), 0 + i = i` -```pre (show := false) +```pre -show n : Nat i : Fin (n + 1) ⊢ 0 + i = i @@ -380,9 +380,9 @@ Fin.rec.{u} {n : Nat} {motive : Fin n → Sort u} ```setup intro n i ``` -{goal show:= false}`∀(n : Nat) (i : Fin (n + 1)), 0 + i = i` +{goal -show}`∀(n : Nat) (i : Fin (n + 1)), 0 + i = i` -```pre (show := false) +```pre -show n : Nat i : Fin (n + 1) ⊢ 0 + i = i @@ -476,7 +476,7 @@ These tactics should not be left in a proof; rather, their suggestions should be :::tacticExample -{goal show:=false}`∀ (i j k : Nat), i < j → j < k → i < k` +{goal -show}`∀ (i j k : Nat), i < j → j < k → i < k` ```setup intro i j k h1 h2 ``` @@ -494,7 +494,7 @@ invoking {tacticStep}`apply?` suggests: Try this: exact Nat.lt_trans h1 h2 ``` -```post (show := false) +```post -show ``` ::: @@ -521,10 +521,10 @@ tag := "tactic-ref-decision" %%% -:::tactic Lean.Parser.Tactic.decide show:="decide" +:::tactic Lean.Parser.Tactic.decide (show := "decide") ::: -:::tactic Lean.Parser.Tactic.nativeDecide show:="native_decide" +:::tactic Lean.Parser.Tactic.nativeDecide (show := "native_decide") ::: :::tactic "omega" diff --git a/Manual/Terms.lean b/Manual/Terms.lean index ec277553..721074a3 100644 --- a/Manual/Terms.lean +++ b/Manual/Terms.lean @@ -56,14 +56,14 @@ This creates ambiguity, because an identifier `A.B.C.D.e.f` could refer to any o This list is not exhaustive. Given an identifier, the elaborator must discover which name or names an identifier refers to, and whether any of the trailing components are fields or functions applied via field notation. -This is called {deftech key:="resolve"}_resolving_ the name. +This is called {deftech (key := "resolve")}_resolving_ the name. Some declarations in the global environment are lazily created the first time they are referenced. Resolving an identifier in a way that both creates one of these declarations and results in a reference to it is called {deftech}_realizing_ the name. The rules for resolving and realizing a name are the same, so even though this section refers only to resolving names, it applies to both. Name resolution is affected by the following: - * {tech key:="pre-resolved identifier"}[Pre-resolved names] attached to the identifier + * {tech (key := "pre-resolved identifier")}[Pre-resolved names] attached to the identifier * The {tech}[macro scopes] attached to the identifier * The local bindings in scope, including auxiliary definitions created as part of the elaboration of {keywordOf Lean.Parser.Term.letrec}`let rec`. * Aliases created with {keywordOf Lean.Parser.Command.export}`export` in modules transitively imported by the current module @@ -195,7 +195,7 @@ Even though `A` was opened more recently than the declaration of {name}`B.x`, th :::example "Ambiguous Identifiers" In this example, `x` could refer either to {name}`A.x` or {name}`B.x`, and neither takes precedence. Because both have the same type, it is an error. -```lean (name := ambi) (error := true) +```lean (name := ambi) +error def A.x := "A.x" def B.x := "B.x" open A @@ -274,9 +274,9 @@ tag := "function-types" Lean's function types describe more than just the function's domain and codomain. They also provide instructions for elaborating application sites by indicating that some parameters are to be discovered automatically via unification or {ref "instance-synth"}[type class synthesis], that others are optional with default values, and that yet others should be synthesized using a custom tactic script. -Furthermore, their syntax contains support for abbreviating {tech key:="currying"}[curried] functions. +Furthermore, their syntax contains support for abbreviating {tech (key := "currying")}[curried] functions. -:::syntax term title:="Function types" +:::syntax term (title := "Function types") Dependent function types include an explicit name: ```grammar ($x:ident : $t) → $t2 @@ -288,7 +288,7 @@ $t1:term → $t2 ``` ::: -:::syntax term title:="Curried Function Types" +:::syntax term (title := "Curried Function Types") Dependent function types may include multiple parameters that have the same type in a single set of parentheses: ```grammar ($x:ident* : $t) → $t @@ -296,7 +296,7 @@ Dependent function types may include multiple parameters that have the same type This is equivalent to repeating the type annotation for each parameter name in a nested function type. ::: -:::syntax term title:="Implicit, Optional, and Auto Parameters" +:::syntax term (title := "Implicit, Optional, and Auto Parameters") Function types can describe functions that take implicit, instance implicit, optional, and automatic parameters. All but instance implicit parameters require one or more names. ```grammar @@ -342,7 +342,7 @@ tag := "function-terms" Terms with function types can be created via abstractions, introduced with the {keywordOf Lean.Parser.Term.fun}`fun` keyword.{margin}[In various communities, function abstractions are also known as _lambdas_, due to Alonzo Church's notation for them, or _anonymous functions_ because they don't need to be defined with a name in the global environment.] While abstractions in the core type theory only allow a single variable to be bound, function terms are quite flexible in the high-level Lean syntax. -:::syntax term title:="Function Abstraction" +:::syntax term (title := "Function Abstraction") The most basic function abstraction introduces a variable to stand for the function's parameter: ```grammar @@ -360,7 +360,7 @@ fun $x:ident : term => $t Function definitions defined with keywords such as {keywordOf Lean.Parser.Command.declaration parser:=Lean.Parser.Command.definition}`def` desugar to {keywordOf Lean.Parser.Term.fun}`fun`. Inductive type declarations, on the other hand, introduce new values with function types (constructors and type constructors) that cannot themselves be implemented using just {keywordOf Lean.Parser.Term.fun}`fun`. -:::syntax term title:="Curried Functions" +:::syntax term (title := "Curried Functions") Multiple parameter names are accepted after {keywordOf Lean.Parser.Term.fun}`fun`: @@ -434,7 +434,7 @@ However, when the explicit argument is not provided, uses of {lean}`f` do not re example := f ``` However, uses of `g` do require it to be solved, and fail to elaborate if there is insufficient information available: -```lean (error := true) (name := noAlpha) +```lean +error (name := noAlpha) example := g ``` ```leanOutput noAlpha @@ -447,7 +447,7 @@ context: :::: -:::syntax term title := "Functions with Varying Binders" +:::syntax term (title := "Functions with Varying Binders") The most general syntax for {keywordOf Lean.Parser.Term.fun}`fun` accepts a sequence of binders: ```grammar fun $p:funBinder $p:funBinder* => $t @@ -455,7 +455,7 @@ fun $p:funBinder $p:funBinder* => $t ::: -:::syntax Lean.Parser.Term.funBinder title:="Function Binders" +:::syntax Lean.Parser.Term.funBinder (title := "Function Binders") Function binders may be identifiers: ```grammar $x:ident @@ -498,7 +498,7 @@ As usual, an `_` may be used instead of an identifier to create an anonymous par Lean's core language does not distinguish between implicit, instance, and explicit parameters: the various kinds of function and function type are definitionally equal. The differences can be observed only during elaboration. -```lean (show := false) +```lean -show -- Evidence of claims in prior paragraph example : ({x : Nat} → Nat) = (Nat → Nat) := rfl example : (fun {x} => 2 : {x : Nat} → Nat) = (fun x => 2 : Nat → Nat) := rfl @@ -600,7 +600,7 @@ If any fresh variables were created for missing explicit positional arguments, t Finally, instance synthesis is invoked and as many metavariables as possible are solved: 1. A type is inferred for the entire function application. This may cause some metavariables to be solved due to unification that occurs during type inference. 2. The instance metavariables are synthesized. {tech}[Default instances] are only used if the inferred type is a metavariable that is the output parameter of one of the instances. - 3. If there is an expected type, it is unified with the inferred type; however, errors resulting from this unification are discarded. If the expected and inferred types can be equal, unification can solve leftover implicit argument metavariables. If they can't be equal, an error is not thrown because a surrounding elaborator may be able to insert {tech}[coercions] or {tech key:="lift"}[monad lifts]. + 3. If there is an expected type, it is unified with the inferred type; however, errors resulting from this unification are discarded. If the expected and inferred types can be equal, unification can solve leftover implicit argument metavariables. If they can't be equal, an error is not thrown because a surrounding elaborator may be able to insert {tech}[coercions] or {tech (key := "lift")}[monad lifts]. ::::keepEnv @@ -670,7 +670,7 @@ This means that the remaining arguments can again be passed by name. fun x => (fun x y => sum3 x y 8) x 1 : Nat → Nat ``` -```lean (show := false) +```lean -show -- This is not shown in the manual pending #6373 -- https://github.com/leanprover/lean4/issues/6373 -- When the issue is fixed, this code will stop working and the text can be updated. @@ -720,7 +720,7 @@ Specifically, it becomes the first explicit argument that would not be a type er Aside from that, the application is elaborated as usual. ::::keepEnv -```lean (show := false) +```lean -show section variable (name : Username) ``` @@ -752,7 +752,7 @@ def root : Username := "root" ``` However, {lean}`Username.validate` can't be called on {lean}`"root"` using field notation, because {lean}`String` does not unfold to {lean}`Username`. -```lean (error := true) (name := notString) +```lean +error (name := notString) #eval "root".validate ``` ```leanOutput notString @@ -770,7 +770,7 @@ has type Except.ok () ``` ::: -```lean (show := false) +```lean -show end ``` :::: @@ -862,7 +862,7 @@ $e |>.$_:fieldIdx ::: ::::keepEnv -```lean (show := false) +```lean -show section universe u axiom T : Nat → Type u @@ -877,7 +877,7 @@ axiom T.f : {n : Nat} → Char → T n → String Some functions are inconvenient to use with pipelines because their argument order is not conducive. For example, {name}`Array.push` takes an array as its first argument, not a {lean}`Nat`, leading to this error: -```lean (name := arrPush) (error := true) +```lean (name := arrPush) +error #eval #[1, 2, 3] |> Array.push 4 ``` ```leanOutput arrPush @@ -908,7 +908,7 @@ This process can be iterated: ::: -```lean (show := false) +```lean -show end ``` :::: @@ -916,14 +916,14 @@ end # Literals There are two kinds of numeric literal: natural number literals and {deftech}[scientific literals]. -Both are overloaded via {tech key:="type class"}[type classes]. +Both are overloaded via {tech (key := "type class")}[type classes]. ## Natural Numbers %%% tag := "nat-literals" %%% -```lean (show := false) +```lean -show section variable {n : Nat} ``` @@ -933,7 +933,7 @@ A {tech}[default instance] of {lean}`OfNat Nat n` ensures that the type {lean}`N {docstring OfNat} -```lean (show := false) +```lean -show end ``` @@ -1077,7 +1077,7 @@ else Array indexing requires evidence that the index in question is within the bounds of the array, so {name}`getThird` does not elaborate. -```lean (error := true) (keep := false) (name := getThird1) +```lean +error -keep (name := getThird1) def getThird (xs : Array α) : α := xs[2] ``` ```leanOutput getThird1 @@ -1093,7 +1093,7 @@ xs : Array α Relaxing the return type to {name}`Option` and adding a bounds check results in the same error. This is because the proof that the index is in bounds was not added to the local context. -```lean (error := true) (keep := false) (name := getThird2) +```lean +error -keep (name := getThird2) def getThird (xs : Array α) : Option α := if xs.size ≤ 2 then none else xs[2] @@ -1169,7 +1169,7 @@ $[| $[$e,*]|* => $e]* ``` ::: -:::syntax matchDiscr (title := "Match Discriminants") (open := false) +:::syntax matchDiscr (title := "Match Discriminants") -open ```grammar $e:term ``` @@ -1203,7 +1203,7 @@ They consist of the following: If the identifier is a constructor, the pattern matches values built with that constructor if the argument patterns match the constructor's arguments. If it is a function with the {attr}`match_pattern` attribute, then the function application is unfolded and the resulting term's {tech}[normal form] is used as the pattern. Default arguments are inserted as usual, and their normal forms are used as patterns. - {tech key:="ellipsis"}[Ellipses], however, result in all further arguments being treated as universal patterns, even those with associated default values or tactics. + {tech (key := "ellipsis")}[Ellipses], however, result in all further arguments being treated as universal patterns, even those with associated default values or tactics. : Literals @@ -1283,7 +1283,7 @@ $x:ident@$h:ident:$e ::: -```lean (show := false) (keep := false) +```lean -show -keep -- Check claims about patterns -- Literals @@ -1435,7 +1435,7 @@ In both subsequent patterns in the same match alternative and the right-hand sid ::::keepEnv -```lean (show := false) +```lean -show variable {α : Type u} ``` @@ -1462,7 +1462,7 @@ inductive BalancedTree (α : Type u) : Nat → Type u where ``` To begin the implementation of a function to construct a perfectly balanced tree with some initial element and a given depth, a {tech}[hole] can be used for the definition. -```lean (keep := false) (name := fill1) (error := true) +```lean -keep (name := fill1) +error def BalancedTree.filledWith (x : α) (depth : Nat) : BalancedTree α depth := _ ``` The error message demonstrates that the tree should have the indicated depth. @@ -1477,7 +1477,7 @@ depth : Nat Matching on the expected depth and inserting holes results in an error message for each hole. These messages demonstrate that the expected type has been refined, with `depth` replaced by the matched values. -```lean (error := true) (name := fill2) +```lean +error (name := fill2) def BalancedTree.filledWith (x : α) (depth : Nat) : BalancedTree α depth := @@ -1506,7 +1506,7 @@ depth n : Nat Matching on the depth of a tree and the tree itself leads to a refinement of the tree's type according to the depth's pattern. This means that certain combinations are not well-typed, such as {lean}`0` and {name BalancedTree.branch}`branch`, because refining the second discriminant's type yields {lean}`BalancedTree α 0` which does not match the constructor's type. -```lean (name := patfail) (error := true) +```lean (name := patfail) +error def BalancedTree.isPerfectlyBalanced (n : Nat) (t : BalancedTree α n) : Bool := match n, t with @@ -1546,7 +1546,7 @@ def last? (xs : List α) : Except String α := ``` Without the name, {tactic}`simp_all` is unable to find the contradiction. -```lean (error := true) (name := namedHyp) +```lean +error (name := namedHyp) def last?' (xs : List α) : Except String α := match xs with | [] => @@ -1572,7 +1572,7 @@ The type that results from applying a function with this type to the discriminan :::example "Matching with an Explicit Motive" An explicit motive can be used to provide type information that is otherwise unavailable from the surrounding context. Attempting to match on a number and a proof that it is in fact {lean}`5` is an error, because there's no reason to connect the number to the proof: -```lean (error := true) (name := noMotive) +```lean +error (name := noMotive) #eval match 5, rfl with | 5, rfl => "ok" @@ -1631,13 +1631,13 @@ This latter behavior can be turned off by passing the `(generalizing := false)` :::::keepEnv ::::example "Matching, With and Without Generalization" -```lean (show := false) +```lean -show variable {α : Type u} (b : Bool) (ifTrue : b = true → α) (ifFalse : b = false → α) ``` In this definition of {lean}`boolCases`, the assumption {lean}`b` is generalized in the type of `h` and then replaced with the actual pattern. This means that {lean}`ifTrue` and {lean}`ifFalse` have the types {lean}`true = true → α` and {lean}`false = false → α` in their respective cases, but `h`'s type mentions the original discriminant. -```lean (error := true) (name := boolCases1) (keep := false) +```lean +error (name := boolCases1) -keep def boolCases (b : Bool) (ifTrue : b = true → α) (ifFalse : b = false → α) : @@ -1676,7 +1676,7 @@ In the generalized version, {name}`rfl` could have been used as the proof argume tag := "match_pattern-functions" %%% -```lean (show := false) +```lean -show section variable {n : Nat} ``` @@ -1694,13 +1694,13 @@ match_pattern ::: ::::keepEnv -```lean (show := false) +```lean -show section variable {k : Nat} ``` :::example "Match Patterns Follow Reduction" The following function can't be compiled: -```lean (error := true) (name := nonPat) +```lean +error (name := nonPat) def nonzero (n : Nat) : Bool := match n with | 0 => false @@ -1725,14 +1725,14 @@ No {tech}[ι-reduction] is possible, because the value being matched is a variab In the case of {lean}`k + 1`, that is, {lean}`Nat.add k (.succ .zero)`, the second pattern matches, so it reduces to {lean}`Nat.succ (Nat.add k .zero)`. The second pattern now matches, yielding {lean}`Nat.succ k`, which is a valid pattern. ::: -```lean (show := false) +```lean -show end ``` :::: -```lean (show := false) +```lean -show end ``` @@ -1810,7 +1810,7 @@ $e matches $e When branching on the result of {keywordOf Lean.«term_Matches_|»}`matches`, it's usually better to use {keywordOf termIfLet}`if let`, which can bind pattern variables in addition to checking whether a pattern matches. -```lean (show := false) +```lean -show /-- info: match 4 with | n.succ => true @@ -1870,7 +1870,7 @@ Specify the elaboration of pattern matching to {deftech}[auxiliary match functio # Holes -A {deftech}_hole_ or {deftech}_placeholder term_ is a term that indicates the absence of instructions to the elaborator.{index}[placeholder term]{index subterm:="placeholder"}[term] +A {deftech}_hole_ or {deftech}_placeholder term_ is a term that indicates the absence of instructions to the elaborator.{index}[placeholder term]{index (subterm := "placeholder")}[term] In terms, holes can be automatically filled when the surrounding context would only allow one type-correct term to be written where the hole is. Otherwise, a hole is an error. In patterns, holes represent universal patterns that can match anything. @@ -1949,7 +1949,7 @@ show $_ by $_ This example is unable to execute the tactic proof because the desired proposition is not known. As part of running the earlier tactics, the proposition is automatically refined to be one that the tactics could prove. However, their default cases fill it out incorrectly, leading to a proof that fails. -```lean (name := byBusted) (error := true) +```lean (name := byBusted) +error example (n : Nat) := by induction n next => rfl @@ -1978,7 +1978,7 @@ example (n : Nat) := show 0 + n = n by :::example "Ascribing Types to {keywordOf Lean.Parser.Term.do}`do` Blocks" This example lacks sufficient type information to synthesize the {name}`Pure` instance. -```lean (name := doBusted) (error := true) +```lean (name := doBusted) +error example := do return 5 ``` @@ -1988,7 +1988,7 @@ typeclass instance problem is stuck, it is often due to metavariables ``` A prefix type ascription with {keywordOf Lean.Parser.Term.show}`show`, together with a {tech}[hole], can be used to indicate the monad. -The {tech key:="default instance"}[default] {lean}`OfNat _ 5` instance provides enough type information to fill the hole with {lean}`Nat`. +The {tech (key := "default instance")}[default] {lean}`OfNat _ 5` instance provides enough type information to fill the hole with {lean}`Nat`. ```lean example := show StateM String _ from do return 5 diff --git a/Manual/Types.lean b/Manual/Types.lean index 0d0a1308..0fc76f2e 100644 --- a/Manual/Types.lean +++ b/Manual/Types.lean @@ -66,7 +66,7 @@ Definitional equality includes the following forms of {deftech}[reduction]: Terms in which all possible reductions have been carried out are in {deftech}_normal form_. ::::keepEnv -```lean (show := false) +```lean -show axiom α : Type axiom β : Type axiom f : α → β @@ -113,7 +113,7 @@ example : LengthList String 2 := ``` If the length does not match the number of entries, then the computed type will not match the term: -```lean error:=true name:=wrongNum +```lean +error (name := wrongNum) example : LengthList String 5 := ("Wrong", "number", ()) ``` @@ -163,7 +163,7 @@ Propositions have the following properties: With the exception of {tech}[subsingletons], propositions cannot be eliminated into non-proposition types. -: {deftech key:="propositional extensionality"}[Extensionality] {index subterm:="of propositions"}[extensionality] +: {deftech (key := "propositional extensionality")}[Extensionality] {index (subterm := "of propositions")}[extensionality] Any two logically equivalent propositions can be proven to be equal with the {lean}`propext` axiom. @@ -172,7 +172,7 @@ Propositions have the following properties: # Universes Types are classified by {deftech}_universes_. {index}[universe]{margin}[Universes are also referred to as {deftech}_sorts_.] -Each universe has a {deftech (key:="universe level")}_level_, {index subterm := "of universe"}[level] which is a natural number. +Each universe has a {deftech (key:="universe level")}_level_, {index (subterm := "of universe")}[level] which is a natural number. The {lean}`Sort` operator constructs a universe from a given level. {index}[`Sort`] If the level of a universe is smaller than that of another, the universe itself is said to be smaller. With the exception of propositions (described later in this chapter), types in a given universe may only quantify over types in smaller universes. @@ -186,7 +186,7 @@ example : Sort 2 := Sort 1 ``` On the other hand, {lean}`Sort 3` is not an element of {lean}`Sort 5`: -```lean (error := true) (name := sort3) +```lean +error (name := sort3) example : Sort 5 := Sort 3 ``` @@ -204,7 +204,7 @@ Similarly, because {lean}`Unit` is in {lean}`Sort 1`, it is not in {lean}`Sort 2 ```lean example : Sort 1 := Unit ``` -```lean error := true name := unit1 +```lean +error (name := unit1) example : Sort 2 := Unit ``` @@ -230,7 +230,7 @@ A function type's universe is determined by the universes of its argument and re The specific rules depend on whether the return type of the function is a proposition. Predicates, which are functions that return propositions (that is, where the result of the function is some type in `Prop`) may have argument types in any universe whatsoever, but the function type itself remains in `Prop`. -In other words, propositions feature {deftech}[_impredicative_] {index}[impredicative]{index subterm := "impredicative"}[quantification] quantification, because propositions can themselves be statements about all propositions (and all other types). +In other words, propositions feature {deftech}[_impredicative_] {index}[impredicative]{index (subterm := "impredicative")}[quantification] quantification, because propositions can themselves be statements about all propositions (and all other types). :::Manual.example "Impredicativity" Proof irrelevance can be written as a proposition that quantifies over all propositions: @@ -245,7 +245,7 @@ example : Prop := ∀ (α : Type 5), ∀ (x : α), x = x ``` ::: -For universes at {tech key:="universe level"}[level] `1` and higher (that is, the `Type u` hierarchy), quantification is {deftech}[_predicative_]. {index}[predicative]{index subterm := "predicative"}[quantification] +For universes at {tech (key := "universe level")}[level] `1` and higher (that is, the `Type u` hierarchy), quantification is {deftech}[_predicative_]. {index}[predicative]{index (subterm := "predicative")}[quantification] For these universes, the universe of a function type is the least upper bound of the argument and return types' universes. :::Manual.example "Universe levels of function types" @@ -258,7 +258,7 @@ example (α : Type 2) (β : Type 1) : Type 2 := α → β :::Manual.example "Predicativity of {lean}`Type`" This example is not accepted, because `α`'s level is greater than `1`. In other words, the annotated universe is smaller than the function type's universe: -```lean error := true name:=toosmall +```lean +error (name := toosmall) example (α : Type 2) (β : Type 1) : Type 1 := α → β ``` ```leanOutput toosmall @@ -277,7 +277,7 @@ Each type inhabits precisely one universe. :::Manual.example "No cumulativity" This example is not accepted because the annotated universe is larger than the function type's universe: -```lean error := true name:=toobig +```lean +error (name := toobig) example (α : Type 2) (β : Type 1) : Type 3 := α → β ``` ```leanOutput toobig @@ -293,7 +293,7 @@ of sort `Type 4` ## Polymorphism -Lean supports {deftech}_universe polymorphism_, {index subterm:="universe"}[polymorphism] {index}[universe polymorphism] which means that constants defined in the Lean environment can take {deftech}[universe parameters]. +Lean supports {deftech}_universe polymorphism_, {index (subterm := "universe")}[polymorphism] {index}[universe polymorphism] which means that constants defined in the Lean environment can take {deftech}[universe parameters]. These parameters can then be instantiated with universe levels when the constant is used. Universe parameters are written in curly braces following a dot after a constant name. @@ -320,7 +320,7 @@ structure Codec.{u} : Type (u + 1) where Lean automatically infers most level parameters. In the following example, it is not necessary to annotate the type as {lean}`Codec.{0}`, because {lean}`Char`'s type is {lean}`Type 0`, so `u` must be `0`: -```lean (keep := true) +```lean def Codec.char : Codec where type := Char encode buf ch := buf.push ch.val @@ -343,7 +343,7 @@ Universe-polymorphic definitions in fact create a _schematic definition_ that ca This can be seen in the following example, in which {lean}`T` is a gratuitously-universe-polymorphic function that always returns {lean}`true`. Because it is marked {keywordOf Lean.Parser.Command.declaration}`opaque`, Lean can't check equality by unfolding the definitions. Both instantiations of {lean}`T` have the parameters and the same type, but their differing universe instantiations make them incompatible. -```lean (error := true) (name := uniIncomp) +```lean +error (name := uniIncomp) opaque T.{u} (_ : Nat) : Bool := (fun (α : Sort u) => true) PUnit.{u} @@ -382,7 +382,7 @@ partial def count [Monad m] (p : α → Bool) (act : m α) : m Nat := do return 0 ``` -```lean (show := false) +```lean -show /-- info: Nat : Type -/ #check_msgs in #check Nat @@ -446,7 +446,7 @@ When it is set to {lean}`false`, then they must be added explicitly or declared :::Manual.example "Automatic Implicit Parameters and Universe Polymorphism" When `autoImplicit` is {lean}`true` (which is the default setting), this definition is accepted even though it does not bind its universe parameters: -```lean (keep := false) +```lean -keep set_option autoImplicit true def map {α : Type u} {β : Type v} (f : α → β) : List α → List β | [] => [] @@ -454,7 +454,7 @@ def map {α : Type u} {β : Type v} (f : α → β) : List α → List β ``` When `autoImplicit` is {lean}`false`, the definition is rejected because `u` and `v` are not in scope: -```lean (error := true) (name := uv) +```lean +error (name := uv) set_option autoImplicit false def map {α : Type u} {β : Type v} (f : α → β) : List α → List β | [] => [] @@ -481,7 +481,7 @@ Just as the `variable` command causes a particular identifier to be treated as a ::: :::Manual.example "The `universe` command when `autoImplicit` is `false`" -```lean (keep := false) +```lean -keep set_option autoImplicit false universe u def id₃ (α : Type u) (a : α) := a @@ -493,11 +493,11 @@ Because the automatic implicit parameter feature only inserts parameters that ar :::Manual.example "Automatic universe parameters and the `universe` command" This definition with an explicit universe parameter is accepted: -```lean (keep := false) +```lean -keep def L.{u} := List (Type u) ``` Even with automatic implicit parameters, this definition is rejected, because `u` is not mentioned in the header, which precedes the `:=`: -```lean (error := true) (name := unknownUni) (keep := false) +```lean +error (name := unknownUni) -keep set_option autoImplicit true def L := List (Type u) ``` @@ -505,7 +505,7 @@ def L := List (Type u) unknown universe level 'u' ``` With a universe declaration, `u` is accepted as a parameter even on the right-hand side: -```lean (keep := false) +```lean -keep universe u def L := List (Type u) ``` diff --git a/lake-manifest.json b/lake-manifest.json index 3886d0a8..7c6c4642 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "", - "rev": "78002a2a5c6012e2aee9e680b646dddbaa0a900d", + "rev": "1a84b41c176a576e982676d6e1b0cb3df1786abb", "name": "verso", "manifestFile": "lake-manifest.json", "inputRev": "main",