Zulip Chat Archive
Stream: general
Topic: Notation for `Finsupp`
Eric Wieser (Aug 04 2023 at 16:54):
Right now, we have notation for functions from Fin n
as ![x, y, z]
. #6367 introduces notation for Finsupp
, allowing sparse vectors to be written as fun₀ | 0 => x | 2 => z
.
The notation matches the builtin fun | 0 => x | 2 => z | _ => 0
notation for functions.
Eric Wieser (Aug 04 2023 at 16:55):
Perhaps more controversially, this PR also introduces an unexpander, which means that finsupp.single i x
is now replaced by fun₀ | i => x
in the info view (and docs).
Eric Wieser (Aug 04 2023 at 16:57):
I labelled #6367 RFC for now; I'd appreciate feedback on:
- The notation itself
- The expansion to
update (update (single i x) j y) k z)
rather than anupdate i x 0
at the bottom - The agressiveness of the unexpander, and whether hiding
single
from goals is good or bad.
Alex J. Best (Aug 04 2023 at 16:57):
Eric Wieser said:
Perhaps more controversially, this PR also introduces an unexpander, which means that
finsupp.single i x
is now replaced byfun | i => x
in the info view (and docs).
fun
or fun₀
?
Eric Wieser (Aug 04 2023 at 17:00):
Fixed, thanks!
Jireh Loreaux (Aug 04 2023 at 18:42):
Eric, you may want to fix it in the top two posts above as well. I think the second fun₀
should be fun
and the last fun
should be fun₀
.
Eric Wieser (Aug 07 2023 at 12:18):
Should be corrected now, apologies for the typos
Thomas Murrills (Aug 10 2023 at 09:45):
I left this as a comment on the PR, but perhaps it's better to put it here:
I really like this! :) Given that ↦
is standard for fun
expressions in mathlib, though, I would suggest that:
- both
=>
and↦
should be available as input notation, and - the delaborator and
Repr
instance should use↦
so that it's as close as possible to fun syntax.
Ruben Van de Velde (Aug 10 2023 at 09:47):
Is it, though? (standard for mathlib)
Thomas Murrills (Aug 10 2023 at 09:52):
Yes, I believe so; for example, if you write example : True := by let _ := fun x : Bool => x; trivial
in a typical mathlib theory file, the value will show up as fun x ↦ x
in the infoview. (I'm not sure where exactly this delaborator is located.)
Eric Wieser (Aug 10 2023 at 09:59):
It's standard in the infoview, but not in the source
Thomas Murrills (Aug 10 2023 at 10:02):
Ah, ok—in any case my suggestion was consistent with that :) (allow both arrows in source and stick to ↦
in delaboration/Repr
)
Eric Wieser (Aug 10 2023 at 10:03):
I think it already allows both in the source, but I will check
Thomas Murrills (Aug 10 2023 at 10:04):
(deleted)
Thomas Murrills (Aug 10 2023 at 10:09):
On another point, I was wondering about this:
/-- A variant of `Lean.Parser.Term.matchAlts` with less line wrapping. -/
def fun₀.matchAlts : Parser :=
leading_parser withPosition $ ppRealGroup <| many1Indent (ppSpace >> ppGroup matchAlt)
What's the effect of this, and why do we want it?
Eric Wieser (Aug 10 2023 at 10:09):
Ok, so ↦
doesn't work in that PR, but it also doesn't work for regular functions:
#check show ℕ → ℕ from fun | 0 => 0 | Nat.succ n => n + 2 -- ok
#check show ℕ → ℕ from fun | 0 ↦ 0 | Nat.succ n ↦ n + 2 -- fail
Thomas Murrills (Aug 10 2023 at 10:10):
Ah, so it's just e.g. fun x ↦ y
that works! ...I think we want to fix that, right?
Eric Wieser (Aug 10 2023 at 10:10):
Yes, I think we probably do want to fix that for regular fun
; and since they use the same parser, we will get the feature for Finsupp
for free once it's fixed
Thomas Murrills (Aug 10 2023 at 17:21):
Just want to bring this message down so it doesn't fade into obscurity :)
Thomas Murrills said:
On another point, I was wondering about this:
/-- A variant of `Lean.Parser.Term.matchAlts` with less line wrapping. -/ def fun₀.matchAlts : Parser := leading_parser withPosition $ ppRealGroup <| many1Indent (ppSpace >> ppGroup matchAlt)
What's the effect of this, and why do we want it?
Eric Wieser (Aug 10 2023 at 17:38):
Compare with src#Lean.Parser.Term.matchAlts:
def matchAlts (rhsParser : Parser := termParser) : Parser :=
leading_parser withPosition $ many1Indent (ppLine >> matchAlt rhsParser)
Eric Wieser (Aug 10 2023 at 17:40):
The effect is:
fun₀ | 0 => x + x + x | 1 => y + y + y
is rendered on a single line if possible (the removedppLine
)- If not possible, the wrapping always happens at the
|
s before the+
s (theppGroup
)
I think theppRealGroup
was part of the same thing.
Eric Wieser (Aug 10 2023 at 17:41):
The reason we want the first one is that we want (fun₀ | 0 => x) + (fun₀ | 0 => y) = fun₀ | 0 => x + y
to render on one line in the goal view, otherwise it's completely unreadable
Eric Wieser (Aug 10 2023 at 17:42):
With the default matchAlts
it printed as:
Finsupp.single_add.{u_2, u_1} {α : Type u_1} {M : Type u_2} [inst✝ : AddZeroClass M] (a : α) (b₁ b₂ : M) :
(fun₀
| a => b₁ + b₂) =
(fun₀
| a => b₁) +
fun₀
| a => b₂
Thomas Murrills (Aug 10 2023 at 18:11):
That's great! I stress tested the parser (by itself) a bit and nothing seemed to break when it shouldn't. All the inputs that I wanted to work did. :)
Eric Wieser (Aug 10 2023 at 18:25):
One thing that puzzled me while developing this is that we seem to have all this logic for clever line wrapping, only to completely ignore the width of the goal view when rendering it...
Martin Dvořák (Sep 05 2023 at 16:20):
Does the ![x, y, ...]
notation from Mathlib.Data.Fin.VecNotation
work for dependent vectors as well?
Eric Wieser (Sep 05 2023 at 16:59):
No, and probably it shouldn't because that would be annoying for elaboration.
Eric Wieser (Sep 05 2023 at 16:59):
(but it could be a different syntax
Yaël Dillies (Sep 25 2023 at 15:23):
Btw your notation is currently broken when the user accidentally uses the same index twice. This sounds like a dumb restriction, but it actually came up for me since I was doing stuff like fun₀ | 1 => 0 | 0 => -1 : R →₀ S
for a possibly trivial ring R
. The solution there was to use +
instead of docs#Finsupp.update.
Notification Bot (Sep 25 2023 at 16:42):
A message was moved here from #Is there code for X? > Factorisation of squarefree naturals by Eric Wieser.
Eric Wieser (Sep 25 2023 at 16:46):
This was deliberate on my part; I thought addition would be more surprising for the semantics than replacements
Eric Wieser (Sep 25 2023 at 16:46):
For instance, {0: 1, 0: 2}
in python means {0: 2}
not {0: 3}
.
Eric Wieser (Sep 25 2023 at 16:47):
(fun | 1 => 2 | 1 => 2 | _ => 0)
is an error (redundant alternative
) so unfortunately I can't claim I'm emulating that
Yaël Dillies (Sep 25 2023 at 18:45):
Well I've resorted to using (fun₀ | 1 => 1) - fun₀ | 0 => 1 : R →₀ ℤ
instead of fun₀ | 1 => 1 | 0 => -1 : R →₀ ℤ
here because of that, so I'm unconvinced.
Yaël Dillies (Sep 25 2023 at 18:46):
This had the advantage of
- meaning the correct thing even when the ring is trivial
- not requiring side goals
Eric Wieser (Sep 25 2023 at 19:02):
I think your spelling is better anyway because there's no ambiguity in what it could mean
Eric Wieser (Sep 25 2023 at 19:03):
Which is to say, I would rather see (fun₀ | 1 => 1) - (fun₀ | 0 => 1)
than fun₀ | 1 => 1 | 0 => -1
in the goal view for the case you describe
Eric Rodriguez (Nov 22 2023 at 10:35):
Is there any way to temporarily turn off the notation, to prove things about it? I'm not exactly sure how it's implemented so it's hard to know
Eric Wieser (Nov 22 2023 at 10:40):
No, there isn't; but it's sort of the same as proving things about {a, b}
; instead of insert
and singleton
, the term is built of update
and single
Eric Wieser (Nov 22 2023 at 10:43):
Maybe the docstring and/or hover behavior needs improving
Eric Wieser (Nov 22 2023 at 10:44):
This hover text is pretty dumb: oops!
Alex J. Best (Nov 22 2023 at 17:23):
You can use set_option pp.notation false
btw, I just wouldn't know how to make it more fine-grained.
Wrenna Robson (Nov 23 2023 at 17:03):
Is it still the case that FinSupp is noncomputable btw?
Eric Wieser (Nov 23 2023 at 17:05):
Yes, use DFinsupp
if you want a computable version
Last updated: Dec 20 2023 at 11:08 UTC