lean4-htt/tests/lean/interactive/hover.lean.expected.out
David Thrane Christiansen 45df6fcd37
fix: hovers and docstrings for (co)inductive types (#10738)
This PR fixes a regression introduced by #10307, where hovering the name
of an inductive type or constructor in its own declaration didn't show
the docstring. In the process, a bug in docstring handling for
coinductive types was discovered and also fixed. Tests are added to
prevent the regression from repeating in the future.
2025-10-15 09:32:11 +00:00

758 lines
42 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 3, "character": 8}}
{"range":
{"start": {"line": 3, "character": 8}, "end": {"line": 3, "character": 18}},
"contents":
{"value":
"```lean\nTrue.intro : True\n```\n***\n`True` is true, and `True.intro` (or more commonly, `trivial`)\nis the proof. \n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 7, "character": 8}}
{"range":
{"start": {"line": 7, "character": 8}, "end": {"line": 7, "character": 18}},
"contents":
{"value":
"```lean\nTrue.intro : True\n```\n***\n`True` is true, and `True.intro` (or more commonly, `trivial`)\nis the proof. \n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 12, "character": 4}}
{"range":
{"start": {"line": 12, "character": 4}, "end": {"line": 12, "character": 12}},
"contents":
{"value":
"```lean\nNat.zero : Nat\n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 21, "character": 2}}
{"range":
{"start": {"line": 21, "character": 2}, "end": {"line": 21, "character": 23}},
"contents": {"value": "My tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 21, "character": 8}}
{"range":
{"start": {"line": 21, "character": 2}, "end": {"line": 21, "character": 23}},
"contents": {"value": "My tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 21, "character": 13}}
{"range":
{"start": {"line": 21, "character": 13}, "end": {"line": 21, "character": 23}},
"contents":
{"value":
"```lean\nTrue.intro : True\n```\n***\n`True` is true, and `True.intro` (or more commonly, `trivial`)\nis the proof. \n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 28, "character": 6}}
{"range":
{"start": {"line": 28, "character": 6}, "end": {"line": 28, "character": 12}},
"contents":
{"value":
"```lean\nLean.Parser.Category.tactic : Lean.Parser.Category\n```\n***\n`tactic` is the builtin syntax category for tactics. These appear after\n`by` in proofs, and they are programs that take in the proof context\n(the hypotheses in scope plus the type of the term to synthesize) and construct\na term of the expected type. For example, `simp` is a tactic, used in:\n```\nexample : 2 + 2 = 4 := by simp\n```\n\n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 28, "character": 32}}
{"range":
{"start": {"line": 28, "character": 32}, "end": {"line": 28, "character": 36}},
"contents":
{"value":
"```lean\nLean.Parser.Category.term : Lean.Parser.Category\n```\n***\n`term` is the builtin syntax category for terms. A term denotes an expression\nin lean's type theory, for example `2 + 2` is a term. The difference between\n`Term` and `Expr` is that the former is a kind of syntax, while the latter is\nthe result of elaboration. For example `by simp` is also a `Term`, but it elaborates\nto different `Expr`s depending on the context. \n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 31, "character": 6}}
{"range":
{"start": {"line": 31, "character": 6}, "end": {"line": 31, "character": 12}},
"contents":
{"value":
"```lean\nLean.Parser.Category.tactic : Lean.Parser.Category\n```\n***\n`tactic` is the builtin syntax category for tactics. These appear after\n`by` in proofs, and they are programs that take in the proof context\n(the hypotheses in scope plus the type of the term to synthesize) and construct\na term of the expected type. For example, `simp` is a tactic, used in:\n```\nexample : 2 + 2 = 4 := by simp\n```\n\n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 31, "character": 24}}
{"range":
{"start": {"line": 31, "character": 23}, "end": {"line": 31, "character": 27}},
"contents":
{"value":
"```lean\nLean.Parser.Category.term : Lean.Parser.Category\n```\n***\n`term` is the builtin syntax category for terms. A term denotes an expression\nin lean's type theory, for example `2 + 2` is a term. The difference between\n`Term` and `Expr` is that the former is a kind of syntax, while the latter is\nthe result of elaboration. For example `by simp` is also a `Term`, but it elaborates\nto different `Expr`s depending on the context. \n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 36, "character": 2}}
{"range":
{"start": {"line": 36, "character": 2}, "end": {"line": 36, "character": 23}},
"contents": {"value": "My tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 44, "character": 2}}
{"range":
{"start": {"line": 44, "character": 2}, "end": {"line": 44, "character": 23}},
"contents": {"value": "My tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 49, "character": 16}}
{"range":
{"start": {"line": 49, "character": 15}, "end": {"line": 49, "character": 21}},
"contents":
{"value": "```lean\nmyNota : Lean.ParserDescr\n```\n***\nMy notation ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 52, "character": 7}}
{"range":
{"start": {"line": 52, "character": 7}, "end": {"line": 52, "character": 15}},
"contents":
{"value": "```lean\n1 : Nat\n```\n***\nMy notation ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 59, "character": 7}}
{"range":
{"start": {"line": 59, "character": 7}, "end": {"line": 59, "character": 15}},
"contents":
{"value": "```lean\nNat\n```\n***\nMy notation ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 69, "character": 7}}
{"range":
{"start": {"line": 69, "character": 7}, "end": {"line": 69, "character": 16}},
"contents":
{"value": "```lean\nNat\n```\n***\nMy ultimate notation ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 73, "character": 21}}
{"range":
{"start": {"line": 73, "character": 18}, "end": {"line": 73, "character": 25}},
"contents":
{"value":
"```lean\nmyInfix : Lean.TrailingParserDescr\n```\n***\nAddition of natural numbers, typically used via the `+` operator.\n\nThis function is overridden in both the kernel and the compiler to efficiently evaluate using the\narbitrary-precision arithmetic library. The definition provided here is the logical model.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 73, "character": 39}}
{"range":
{"start": {"line": 73, "character": 38}, "end": {"line": 73, "character": 45}},
"contents":
{"value":
"```lean\nNat.add : Nat → Nat → Nat\n```\n***\nAddition of natural numbers, typically used via the `+` operator.\n\nThis function is overridden in both the kernel and the compiler to efficiently evaluate using the\narbitrary-precision arithmetic library. The definition provided here is the logical model.\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 77, "character": 10}}
{"range":
{"start": {"line": 77, "character": 7}, "end": {"line": 77, "character": 14}},
"contents":
{"value":
"```lean\nNat\n```\n***\nAddition of natural numbers, typically used via the `+` operator.\n\nThis function is overridden in both the kernel and the compiler to efficiently evaluate using the\narbitrary-precision arithmetic library. The definition provided here is the logical model.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 82, "character": 7}}
{"range":
{"start": {"line": 82, "character": 7}, "end": {"line": 82, "character": 8}},
"contents":
{"value":
"```lean\nNat : Type\n```\n***\nThe natural numbers, starting at zero.\n\nThis type is special-cased by both the kernel and the compiler, and overridden with an efficient\nimplementation. Both use a fast arbitrary-precision arithmetic library (usually\n[GMP](https://gmplib.org/)); at runtime, `Nat` values that are sufficiently small are unboxed.\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 87, "character": 14}}
{"range":
{"start": {"line": 87, "character": 14}, "end": {"line": 87, "character": 36}},
"contents":
{"value":
"```lean\nLean.Parser.Term.doSeq : Lean.Parser.Parser\n```\n***\nA `doSeq` is a sequence of `doElem`, the main argument after the `do` keyword and other\ndo elements that take blocks. It can either have the form `\"{\" (doElem \";\"?)* \"}\"` or\n`many1Indent (doElem \";\"?)`, where `many1Indent` ensures that all the items are at\nthe same or higher indentation level as the first line. \n***\n*import Lean.Parser.Do*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 89, "character": 30}}
{"range":
{"start": {"line": 89, "character": 29}, "end": {"line": 89, "character": 34}},
"contents":
{"value":
"```lean\nLean.Parser.Term.doSeq : Lean.Parser.Parser\n```\n***\nA `doSeq` is a sequence of `doElem`, the main argument after the `do` keyword and other\ndo elements that take blocks. It can either have the form `\"{\" (doElem \";\"?)* \"}\"` or\n`many1Indent (doElem \";\"?)`, where `many1Indent` ensures that all the items are at\nthe same or higher indentation level as the first line. \n***\n*import Lean.Parser.Do*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 92, "character": 2}}
{"range":
{"start": {"line": 92, "character": 0}, "end": {"line": 92, "character": 7}},
"contents": {"value": "My command ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 99, "character": 2}}
{"range":
{"start": {"line": 99, "character": 0}, "end": {"line": 99, "character": 7}},
"contents": {"value": "My command ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 102, "character": 16}}
{"range":
{"start": {"line": 102, "character": 16},
"end": {"line": 102, "character": 23}},
"contents":
{"value":
"```lean\nLean.Parser.ppSpace : Lean.Parser.Parser\n```\n***\nNo-op parser that advises the pretty printer to emit a space/soft line break. \n***\n*import Lean.Parser.Extra*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 102, "character": 24}}
{"range":
{"start": {"line": 102, "character": 24},
"end": {"line": 102, "character": 31}},
"contents":
{"value":
"```lean\nLean.ParserDescr.sepBy1 (p : Lean.ParserDescr) (sep : String) (psep : Lean.ParserDescr)\n (allowTrailingSep : Bool := false) : Lean.ParserDescr\n```\n***\n`sepBy1` is just like `sepBy`, except it takes 1 or more instead of\n0 or more occurrences of `p`. \n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 102, "character": 31}}
{"range":
{"start": {"line": 102, "character": 31},
"end": {"line": 102, "character": 35}},
"contents":
{"value":
"```lean\nLean.Parser.Category.term : Lean.Parser.Category\n```\n***\n`term` is the builtin syntax category for terms. A term denotes an expression\nin lean's type theory, for example `2 + 2` is a term. The difference between\n`Term` and `Expr` is that the former is a kind of syntax, while the latter is\nthe result of elaboration. For example `by simp` is also a `Term`, but it elaborates\nto different `Expr`s depending on the context. \n***\n*import Init.Notation*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 111, "character": 2}}
{"range":
{"start": {"line": 111, "character": 0}, "end": {"line": 111, "character": 8}},
"contents": {"value": "My ultimate command ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 115, "character": 10}}
{"range":
{"start": {"line": 115, "character": 8},
"end": {"line": 115, "character": 14}},
"contents":
{"value":
"Structure instance. `{ x := e, ... }` assigns `e` to field `x`, which may be\ninherited. If `e` is itself a variable called `x`, it can be elided:\n`fun y => { x := 1, y }`.\nA *structure update* of an existing value can be given via `with`:\n`{ point with x := 1 }`.\nThe structure type can be specified if not inferable:\n`{ x := 1, y := 2 : Point }`.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 119, "character": 8}}
{"range":
{"start": {"line": 119, "character": 8},
"end": {"line": 119, "character": 10}},
"contents":
{"value":
"```lean\nid.{u} {α : Sort u} (a : α) : α\n```\n***\nThe identity function. `id` takes an implicit argument `α : Sort u`\n(a type in any universe), and an argument `a : α`, and returns `a`.\n\nAlthough this may look like a useless function, one application of the identity\nfunction is to explicitly put a type on an expression. If `e` has type `T`,\nand `T'` is definitionally equal to `T`, then `@id T' e` typechecks, and Lean\nknows that this expression has type `T'` rather than `T`. This can make a\ndifference for typeclass inference, since `T` and `T'` may have different\ntypeclass instances on them. `show T' from e` is sugar for an `@id T' e`\nexpression.\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 119, "character": 10}}
{"range":
{"start": {"line": 119, "character": 8},
"end": {"line": 119, "character": 21}},
"contents": {"value": "```lean\nTrue\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 126, "character": 2}}
{"range":
{"start": {"line": 126, "character": 2}, "end": {"line": 126, "character": 3}},
"contents": {"value": "```lean\nn : Id \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 133, "character": 9}}
{"range":
{"start": {"line": 133, "character": 7},
"end": {"line": 133, "character": 17}},
"contents": {"value": "```lean\nfoo : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 138, "character": 7}}
{"range":
{"start": {"line": 138, "character": 7},
"end": {"line": 138, "character": 10}},
"contents": {"value": "```lean\nBar.foo : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 141, "character": 9}}
{"range":
{"start": {"line": 141, "character": 7},
"end": {"line": 141, "character": 17}},
"contents": {"value": "```lean\n_root_.foo : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 144, "character": 4}}
{"range":
{"start": {"line": 144, "character": 4}, "end": {"line": 144, "character": 7}},
"contents": {"value": "```lean\nBar.bar : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 147, "character": 10}}
{"range":
{"start": {"line": 147, "character": 10},
"end": {"line": 147, "character": 13}},
"contents": {"value": "```lean\nBar.Foo : Type\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 147, "character": 17}}
{"range":
{"start": {"line": 147, "character": 17},
"end": {"line": 147, "character": 19}},
"contents":
{"value": "```lean\nBar.Foo.mk (hi : ) : Foo\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 150, "character": 2}}
{"range":
{"start": {"line": 150, "character": 2}, "end": {"line": 150, "character": 4}},
"contents":
{"value": "```lean\nBar.Foo.hi (self : Foo) : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 153, "character": 10}}
{"range":
{"start": {"line": 153, "character": 10},
"end": {"line": 153, "character": 13}},
"contents": {"value": "```lean\nBar.Bar : Type\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 155, "character": 4}}
{"range":
{"start": {"line": 155, "character": 4}, "end": {"line": 155, "character": 6}},
"contents": {"value": "```lean\nBar.Bar.mk : Bar\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 158, "character": 2}}
{"range":
{"start": {"line": 158, "character": 0}, "end": {"line": 158, "character": 8}},
"contents":
{"value":
"```lean\nBar.«instToStringNat_external:file:///hover.lean» : ToString \n```",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 160, "character": 9}}
{"range":
{"start": {"line": 160, "character": 9},
"end": {"line": 160, "character": 10}},
"contents": {"value": "```lean\nBar.f : ToString \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 163, "character": 10}}
{"range":
{"start": {"line": 163, "character": 10},
"end": {"line": 163, "character": 16}},
"contents":
{"value": "A type universe. `Type ≡ Type 0`, `Type u ≡ Sort (u + 1)`. ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 166, "character": 4}}
{"range":
{"start": {"line": 166, "character": 4},
"end": {"line": 166, "character": 11}},
"contents": {"value": "```lean\nBar.foo.bar : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 166, "character": 8}}
{"range":
{"start": {"line": 166, "character": 4},
"end": {"line": 166, "character": 11}},
"contents": {"value": "```lean\nBar.foo.bar : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 173, "character": 6}}
{"range":
{"start": {"line": 173, "character": 6}, "end": {"line": 173, "character": 7}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 176, "character": 4}}
[{"targetUri": "file:///hover.lean",
"targetSelectionRange":
{"start": {"line": 173, "character": 6},
"end": {"line": 173, "character": 7}},
"targetRange":
{"start": {"line": 173, "character": 6},
"end": {"line": 173, "character": 7}},
"originSelectionRange":
{"start": {"line": 176, "character": 4},
"end": {"line": 176, "character": 5}}}]
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 176, "character": 4}}
{"range":
{"start": {"line": 176, "character": 4}, "end": {"line": 176, "character": 5}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 180, "character": 12}}
{"range":
{"start": {"line": 180, "character": 11},
"end": {"line": 180, "character": 33}},
"contents":
{"value": "Enables or disables all unused variable linter warnings ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 183, "character": 8}}
{"range":
{"start": {"line": 183, "character": 8}, "end": {"line": 183, "character": 9}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 186, "character": 8}}
[{"targetUri": "file:///hover.lean",
"targetSelectionRange":
{"start": {"line": 183, "character": 8},
"end": {"line": 183, "character": 9}},
"targetRange":
{"start": {"line": 183, "character": 8},
"end": {"line": 183, "character": 9}},
"originSelectionRange":
{"start": {"line": 186, "character": 8},
"end": {"line": 186, "character": 9}}}]
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 186, "character": 8}}
{"range":
{"start": {"line": 186, "character": 8}, "end": {"line": 186, "character": 9}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 191, "character": 25}}
{"range":
{"start": {"line": 191, "character": 25},
"end": {"line": 191, "character": 26}},
"contents": {"value": "```lean\nn : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 194, "character": 2}}
{"range":
{"start": {"line": 194, "character": 2}, "end": {"line": 194, "character": 8}},
"contents":
{"value":
"Changes the inlining behavior. This attribute comes in several variants:\n- `@[inline]`: marks the definition to be inlined when it is appropriate.\n- `@[inline_if_reduce]`: marks the definition to be inlined if an application of it after inlining\n and applying reduction isn't a `match` expression. This attribute can be used for inlining\n structurally recursive functions.\n- `@[noinline]`: marks the definition to never be inlined.\n- `@[always_inline]`: marks the definition to always be inlined.\n- `@[macro_inline]`: marks the definition to always be inlined at the beginning of compilation.\n This makes it possible to define functions that evaluate some of their parameters lazily.\n Example:\n ```\n @[macro_inline]\n def test (x y : Nat) : Nat :=\n if x = 42 then x else y\n\n #eval test 42 (2^1000000000000) -- doesn't compute 2^1000000000000\n ```\n Only non-recursive functions may be marked `@[macro_inline]`.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 200, "character": 2}}
{"range":
{"start": {"line": 200, "character": 2},
"end": {"line": 200, "character": 15}},
"contents":
{"value":
"`· tac` focuses on the main goal and tries to solve it using `tac`, or else fails. ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 203, "character": 28}}
{"range":
{"start": {"line": 203, "character": 27},
"end": {"line": 203, "character": 32}},
"contents":
{"value":
"```lean\nId \n```\n***\nParentheses, used for grouping expressions (e.g., `a * (b + c)`).\nCan also be used for creating simple functions when combined with `·`. Here are some examples:\n - `(· + 1)` is shorthand for `fun x => x + 1`\n - `(· + ·)` is shorthand for `fun x y => x + y`\n - `(f · a b)` is shorthand for `fun x => f x a b`\n - `(h (· + 1) ·)` is shorthand for `fun x => h (fun y => y + 1) x`\n - also applies to other parentheses-like notations such as `(·, 1)` and `(· : Nat → Nat)`\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 206, "character": 8}}
{"range":
{"start": {"line": 206, "character": 8}, "end": {"line": 206, "character": 9}},
"contents": {"value": "```lean\n?m\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 206, "character": 10}}
{"range":
{"start": {"line": 206, "character": 8},
"end": {"line": 206, "character": 13}},
"contents":
{"value":
"```lean\n?m x1✝ x2✝\n```\n***\n`a + b` computes the sum of `a` and `b`.\nThe meaning of this notation is type-dependent. \n\nConventions for notations in identifiers:\n\n * The recommended spelling of `+` in identifiers is `add`.",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 215, "character": 28}}
{"range":
{"start": {"line": 215, "character": 28},
"end": {"line": 215, "character": 29}},
"contents": {"value": "```lean\nx : α\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 217, "character": 28}}
{"range":
{"start": {"line": 217, "character": 28},
"end": {"line": 217, "character": 29}},
"contents": {"value": "```lean\nα\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 219, "character": 31}}
{"range":
{"start": {"line": 219, "character": 31},
"end": {"line": 219, "character": 32}},
"contents": {"value": "```lean\nx : α\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 222, "character": 22}}
{"range":
{"start": {"line": 222, "character": 22},
"end": {"line": 222, "character": 32}},
"contents": {"value": "my_intro tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 222, "character": 31}}
{"range":
{"start": {"line": 222, "character": 31},
"end": {"line": 222, "character": 32}},
"contents": {"value": "```lean\nα\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 229, "character": 22}}
{"range":
{"start": {"line": 229, "character": 22},
"end": {"line": 229, "character": 32}},
"contents": {"value": "my_intro tactic ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 231, "character": 17}}
{"range":
{"start": {"line": 231, "character": 17},
"end": {"line": 231, "character": 25}},
"contents":
{"value": "```lean\nmy_intro : \n```\n***\nmy_intro term ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 235, "character": 8}}
{"range":
{"start": {"line": 235, "character": 8}, "end": {"line": 235, "character": 9}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 238, "character": 4}}
{"range":
{"start": {"line": 238, "character": 4}, "end": {"line": 238, "character": 8}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 241, "character": 4}}
{"range":
{"start": {"line": 241, "character": 4}, "end": {"line": 241, "character": 8}},
"contents":
{"value":
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 241, "character": 9}}
{"range":
{"start": {"line": 241, "character": 9},
"end": {"line": 241, "character": 10}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 245, "character": 8}}
{"range":
{"start": {"line": 245, "character": 8}, "end": {"line": 245, "character": 9}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 247, "character": 12}}
{"range":
{"start": {"line": 247, "character": 12},
"end": {"line": 247, "character": 13}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 249, "character": 4}}
{"range":
{"start": {"line": 249, "character": 4}, "end": {"line": 249, "character": 8}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 252, "character": 9}}
{"range":
{"start": {"line": 252, "character": 9},
"end": {"line": 252, "character": 10}},
"contents":
{"value":
"```lean\n\n```\n***\nA *hole* (or *placeholder term*), which stands for an unknown term that is expected to be inferred based on context.\nFor example, in `@id _ Nat.zero`, the `_` must be the type of `Nat.zero`, which is `Nat`.\n\nThe way this works is that holes create fresh metavariables.\nThe elaborator is allowed to assign terms to metavariables while it is checking definitional equalities.\nThis is often known as *unification*.\n\nNormally, all holes must be solved for. However, there are a few contexts where this is not necessary:\n* In `match` patterns, holes are catch-all patterns.\n* In some tactics, such as `refine'` and `apply`, unsolved-for placeholders become new goals.\n\nRelated concept: implicit parameters are automatically filled in with holes during the elaboration process.\n\nSee also `?m` syntax (synthetic holes).\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 252, "character": 11}}
{"range":
{"start": {"line": 252, "character": 11},
"end": {"line": 252, "character": 13}},
"contents": {"value": "```lean\nih : True\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 257, "character": 6}}
{"range":
{"start": {"line": 257, "character": 4}, "end": {"line": 257, "character": 9}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 257, "character": 15}}
{"range":
{"start": {"line": 257, "character": 13},
"end": {"line": 257, "character": 18}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 260, "character": 6}}
{"range":
{"start": {"line": 260, "character": 4}, "end": {"line": 260, "character": 9}},
"contents":
{"value":
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 260, "character": 17}}
{"range":
{"start": {"line": 260, "character": 15},
"end": {"line": 260, "character": 20}},
"contents":
{"value":
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 263, "character": 27}}
{"range":
{"start": {"line": 263, "character": 27},
"end": {"line": 263, "character": 37}},
"contents":
{"value":
"```lean\nInhabited.mk.{u} {α : Sort u} (default : α) : Inhabited α\n```\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 263, "character": 28}}
{"range":
{"start": {"line": 263, "character": 28},
"end": {"line": 263, "character": 36}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](REFERENCE/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 269, "character": 2}}
{"range":
{"start": {"line": 269, "character": 2}, "end": {"line": 269, "character": 3}},
"contents":
{"value":
"```lean\n\n```\n***\nA *hole* (or *placeholder term*), which stands for an unknown term that is expected to be inferred based on context.\nFor example, in `@id _ Nat.zero`, the `_` must be the type of `Nat.zero`, which is `Nat`.\n\nThe way this works is that holes create fresh metavariables.\nThe elaborator is allowed to assign terms to metavariables while it is checking definitional equalities.\nThis is often known as *unification*.\n\nNormally, all holes must be solved for. However, there are a few contexts where this is not necessary:\n* In `match` patterns, holes are catch-all patterns.\n* In some tactics, such as `refine'` and `apply`, unsolved-for placeholders become new goals.\n\nRelated concept: implicit parameters are automatically filled in with holes during the elaboration process.\n\nSee also `?m` syntax (synthetic holes).\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 272, "character": 4}}
{"range":
{"start": {"line": 272, "character": 4}, "end": {"line": 272, "character": 8}},
"contents":
{"value": "```lean\nauto (o : := by exact 1) : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 277, "character": 22}}
{"range":
{"start": {"line": 277, "character": 22},
"end": {"line": 277, "character": 23}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 277, "character": 13}}
{"range":
{"start": {"line": 277, "character": 13},
"end": {"line": 277, "character": 15}},
"contents": {"value": "```lean\n_e : 1 = x\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 282, "character": 8}}
{"range":
{"start": {"line": 282, "character": 8},
"end": {"line": 282, "character": 10}},
"contents": {"value": "```lean\n_e : 1 = 0\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 285, "character": 9}}
{"range":
{"start": {"line": 285, "character": 9},
"end": {"line": 285, "character": 10}},
"contents": {"value": "```lean\nx : \n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 290, "character": 13}}
{"range":
{"start": {"line": 290, "character": 13},
"end": {"line": 290, "character": 16}},
"contents":
{"value":
"```lean\nList.nil.{u} {α : Type u} : List α\n```\n***\nThe empty list, usually written `[]`. \n\nConventions for notations in identifiers:\n\n * The recommended spelling of `[]` in identifiers is `nil`.\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 292, "character": 13}}
{"range":
{"start": {"line": 292, "character": 11},
"end": {"line": 292, "character": 15}},
"contents":
{"value":
"```lean\nList.cons.{u} {α : Type u} (head : α) (tail : List α) : List α\n```\n***\nThe list whose first element is `head`, where `tail` is the rest of the list.\nUsually written `head :: tail`.\n\n\nConventions for notations in identifiers:\n\n * The recommended spelling of `::` in identifiers is `cons`.\n\n * The recommended spelling of `[a]` in identifiers is `singleton`.\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 294, "character": 18}}
{"range":
{"start": {"line": 294, "character": 17},
"end": {"line": 294, "character": 20}},
"contents":
{"value":
"```lean\nList.map.{u_1, u_2} {α : Type u_1} {β : Type u_2} (f : α → β) (l : List α) : List β\n```\n***\nApplies a function to each element of the list, returning the resulting list of values.\n\n`O(|l|)`.\n\nExamples:\n* `[a, b, c].map f = [f a, f b, f c]`\n* `[].map Nat.succ = []`\n* `[\"one\", \"two\", \"three\"].map (·.length) = [3, 3, 5]`\n* `[\"one\", \"two\", \"three\"].map (·.reverse) = [\"eno\", \"owt\", \"eerht\"]`\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 297, "character": 26}}
{"range":
{"start": {"line": 297, "character": 25},
"end": {"line": 297, "character": 29}},
"contents":
{"value":
"```lean\nList.zip.{u, v} {α : Type u} {β : Type v} : List α → List β → List (α × β)\n```\n***\nCombines two lists into a list of pairs in which the first and second components are the\ncorresponding elements of each list. The resulting list is the length of the shorter of the input\nlists.\n\n`O(min |xs| |ys|)`.\n\nExamples:\n* `[\"Mon\", \"Tue\", \"Wed\"].zip [1, 2, 3] = [(\"Mon\", 1), (\"Tue\", 2), (\"Wed\", 3)]`\n* `[\"Mon\", \"Tue\", \"Wed\"].zip [1, 2] = [(\"Mon\", 1), (\"Tue\", 2)]`\n* `[x₁, x₂, x₃].zip [y₁, y₂, y₃, y₄] = [(x₁, y₁), (x₂, y₂), (x₃, y₃)]`\n\n***\n*import Init.Data.List.Basic*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 297, "character": 19}}
{"range":
{"start": {"line": 297, "character": 19},
"end": {"line": 297, "character": 22}},
"contents":
{"value":
"```lean\nList.zip.{u, v} {α : Type u} {β : Type v} : List α → List β → List (α × β)\n```\n***\nCombines two lists into a list of pairs in which the first and second components are the\ncorresponding elements of each list. The resulting list is the length of the shorter of the input\nlists.\n\n`O(min |xs| |ys|)`.\n\nExamples:\n* `[\"Mon\", \"Tue\", \"Wed\"].zip [1, 2, 3] = [(\"Mon\", 1), (\"Tue\", 2), (\"Wed\", 3)]`\n* `[\"Mon\", \"Tue\", \"Wed\"].zip [1, 2] = [(\"Mon\", 1), (\"Tue\", 2)]`\n* `[x₁, x₂, x₃].zip [y₁, y₂, y₃, y₄] = [(x₁, y₁), (x₂, y₂), (x₃, y₃)]`\n\n***\n*import Init.Data.List.Basic*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 306, "character": 24}}
{"range":
{"start": {"line": 306, "character": 6},
"end": {"line": 306, "character": 38}},
"contents": {"value": "```lean\nBool\n```", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 312, "character": 10}}
{"range":
{"start": {"line": 312, "character": 10},
"end": {"line": 312, "character": 11}},
"contents":
{"value": "```lean\nS : Type\n```\n***\nThese are docs\n", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 315, "character": 2}}
{"range":
{"start": {"line": 315, "character": 2}, "end": {"line": 315, "character": 4}},
"contents":
{"value": "```lean\nS.mk (x : ) : S\n```\n***\nSo are these ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 318, "character": 2}}
{"range":
{"start": {"line": 318, "character": 2}, "end": {"line": 318, "character": 3}},
"contents":
{"value": "```lean\nS.x (self : S) : \n```\n***\nAnd these ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 321, "character": 9}}
{"range":
{"start": {"line": 321, "character": 9},
"end": {"line": 321, "character": 10}},
"contents":
{"value": "```lean\nx : \n```\n***\nAnd these ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 321, "character": 18}}
{"range":
{"start": {"line": 321, "character": 18},
"end": {"line": 321, "character": 19}},
"contents":
{"value": "```lean\nS : Type\n```\n***\nThese are docs\n", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 326, "character": 10}}
{"range":
{"start": {"line": 326, "character": 10},
"end": {"line": 326, "character": 12}},
"contents":
{"value": "```lean\nS' : Type\n```\n***\nDocs ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 329, "character": 4}}
{"range":
{"start": {"line": 329, "character": 4}, "end": {"line": 329, "character": 6}},
"contents":
{"value": "```lean\nS'.mk (x : ) : S'\n```\n***\nMore docs ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 332, "character": 9}}
{"range":
{"start": {"line": 332, "character": 8},
"end": {"line": 332, "character": 11}},
"contents":
{"value": "```lean\nS'.mk (x : ) : S'\n```\n***\nMore docs ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 332, "character": 16}}
{"range":
{"start": {"line": 332, "character": 16},
"end": {"line": 332, "character": 18}},
"contents":
{"value": "```lean\nS' : Type\n```\n***\nDocs ", "kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 337, "character": 12}}
{"range":
{"start": {"line": 337, "character": 12},
"end": {"line": 337, "character": 18}},
"contents":
{"value":
"```lean\nInfSeq.{u_1} {α : Sort u_1} (r : αα → Prop) : α → Prop\n```\n***\nAn infinite sequence ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 340, "character": 7}}
{"range":
{"start": {"line": 340, "character": 4}, "end": {"line": 340, "character": 8}},
"contents":
{"value":
"```lean\nInfSeq.step.{u_1} {α : Sort u_1} (r : αα → Prop) {a b : α} : r a b → InfSeq r b → InfSeq r a\n```\n***\nTake a step ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 343, "character": 7}}
{"range":
{"start": {"line": 343, "character": 7},
"end": {"line": 343, "character": 13}},
"contents":
{"value":
"```lean\nInfSeq.{u_1} {α : Sort u_1} (r : αα → Prop) : α → Prop\n```\n***\nAn infinite sequence ",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 346, "character": 7}}
{"range":
{"start": {"line": 346, "character": 7},
"end": {"line": 346, "character": 18}},
"contents":
{"value":
"```lean\nInfSeq.step.{u_1} {α : Sort u_1} (r : αα → Prop) {a b : α} : r a b → InfSeq r b → InfSeq r a\n```\n***\nTake a step ",
"kind": "markdown"}}