forked from leanprover-community/mathlib4
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathToFun.lean
More file actions
79 lines (68 loc) · 3 KB
/
Copy pathToFun.lean
File metadata and controls
79 lines (68 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/-
Copyright (c) 2025 Jovan Gerbscheid. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Jovan Gerbscheid
-/
module
public import Mathlib.Util.AddRelatedDecl
public import Mathlib.Tactic.Push
public import Mathlib.Tactic.Translate.Attributes
/-!
# The `to_fun` attribute
Adding `@[to_fun]` to a lemma named `foo` creates a new lemma named `fun_foo`, which is obtained by
running `pull fun _ ↦ _` on the type of `F`. This can be useful for generating the applied form
of a continuity lemma from the unapplied form.
-/
meta section
open Lean Meta Elab Tactic
namespace Mathlib.Tactic
/--
Generate an eta-expanded version of a lemma. Adding `@[to_fun]` to a lemma written in "point-free"
form, e.g.
```
theorem Differentiable.mul (hf : Differentiable 𝕜 f) (hg : Differentiable 𝕜 g) :
Differentiable 𝕜 (f * g)
```
will generate a new lemma `Differentiable.fun_mul` with conclusion
`Differentiable 𝕜 fun x => f x * g x`.
You can specify the name of the new declaration manually, as in `@[to_fun Differentiable.fun_mul]`.
If you do so, the newly generated name is namespaced to match the original declaration's name:
tagging `Foo.bar` with `to_fun baz` generates `Foo.baz`;
tagging `Foo.Bar.baz` with `Bars.baz` generates `Foo.Bars.baz`, etc.
Use the `to_fun (attr := ...)` (or `to_fun (attr := ...) new_name`) syntax
to add the same attribute to both declarations.
-/
syntax (name := to_fun) "to_fun" optAttrArg (ppSpace ident)? : attr
def toFunImpl (src : Name) (stx : Syntax) (kind : AttributeKind) : AttrM Name := do
let `(attr| to_fun%$tk $optAttr $[$id]?) := stx | throwUnsupportedSyntax
if (kind != AttributeKind.global) then
throwError "`to_fun` can only be used as a global attribute"
let name := match id with
| some name => (src.splitAt name.getId.getNumParts).1 ++ name.getId
| none => src.appendBefore "fun_"
if let some id := id then
if name == src.appendBefore "fun_" then
logWarningAt id m!"`to_fun` correctly autogenerated the provided name `{.ofConstName name}`.\
\nYou may remove it."
MetaM.run' <| addRelatedDecl src name (id.elim tk (·.raw)) optAttr
(docstringPrefix? := s!"Eta-expanded form of `{src}`") (hoverInfo := true)
fun value levels => do
let type ← inferType value
let r ← Push.pullCore .lambda type none
if r.expr == type then
throwError "`@[to_fun]` failed to eta-expand any part of `{.ofConstName src}`."
-- Ensure that the returned `value` has type `r.expr`.
let value ← match r.proof? with
| none => mkExpectedTypeHint value r.expr
| some proof => mkAppOptM ``cast #[type, r.expr, proof, value]
return (value, levels)
return name
initialize
registerGeneratingAttr `to_fun ((#[·]) <$> toFunImpl · · ·)
registerBuiltinAttribute {
name := `to_fun
descr :=
"generate a copy of a lemma where point-free functions are expanded to their `fun` form"
applicationTime := .afterCompilation
add := (discard <| toFunImpl · · ·)}
end Mathlib.Tactic