Zulip Chat Archive
Stream: Is there code for X?
Topic: Agda style interactive case splitting?
Solomon (Mar 01 2024 at 06:40):
Is there any way to do agda style case splitting? I imported import «Std».CodeAction
but the only suggestion for holes is to start a tactics proof.
Johan Commelin (Mar 01 2024 at 06:46):
I don't know what agda style case splitting is...
If you import Std
you might get more code actions. And if you import Mathlib
you might get even more.
Can you give an #mwe of what you are expecting?
Solomon (Mar 01 2024 at 07:46):
In Agda if you have a function with a hole in it like this:
def foo : (n : ℕ) → ℕ := _
You can press a ctrl-c ctrl-c
on the hole and enter the variable name and it will insert a pattern match on the variable. This is incredibly helpful, especially when working with inductive types and sigma types.
Joachim Breitner (Mar 01 2024 at 08:22):
That would be great to have. I think we have something similar where you write
import Mathlib
def foo (n : ℕ) : ℕ := by
induction n with
(but not match n with
, for whatever reason) and you get a code action to complete it to
import Mathlib
def foo (n : ℕ) : ℕ := by
induction n with
| zero => sorry
| succ n ih => sorry
so doing it for function definitions should be possible as well.
Kyle Miller (Mar 01 2024 at 08:26):
At least if the type is a function you can generate the pattern match:
def foo : ℕ → ℕ := fun
| .zero => _
| .succ n => _
Joachim Breitner (Mar 01 2024 at 10:24):
Nice! I need to get better at discovering and using these code actions
Kyle Miller (Mar 01 2024 at 18:39):
It'd be neat if match n
would generate a code action too!
Patrick Massot (Mar 01 2024 at 18:40):
Yes, every now and then I rediscover it doesn’t and I’m disappointed.
Kyle Miller (Mar 01 2024 at 18:43):
This has made me wonder why it is again we need nomatch
syntax. Wouldn't match x
with no with
clause suffice for nomatch x
?
Then match x
by itself could suggest a code action with the cases you need to handle, if indeed there are any cases you need to handle.
Solomon (Mar 01 2024 at 21:59):
Kyle Miller said:
At least if the type is a function you can generate the pattern match:
def foo : ℕ → ℕ := fun | .zero => _ | .succ n => _
What do i need to import to get this code action?
Mario Carneiro (Mar 02 2024 at 08:34):
Patrick Massot said:
Yes, every now and then I rediscover it doesn’t and I’m disappointed.
Maybe you should report an issue or ping me when these things happen ;)
Mario Carneiro (Mar 02 2024 at 08:36):
Kyle Miller said:
This has made me wonder why it is again we need
nomatch
syntax. Wouldn'tmatch x
with nowith
clause suffice fornomatch x
?Then
match x
by itself could suggest a code action with the cases you need to handle, if indeed there are any cases you need to handle.
I think we should also allow match x
with an (empty) with
, along the lines of lean#3555
Mario Carneiro (Mar 02 2024 at 08:37):
I don't like that nomatch
requires learning a new keyword, it's less discoverable.
Mario Carneiro (Mar 02 2024 at 08:39):
But I guess it's too late now to stop the nofun
in 4.7.0-rc1 which is imminent...
Joachim Breitner (Mar 02 2024 at 09:04):
It’s only a release candidate, I'd say it is only fair to listen to feedback from our rc beta testers (i.e. mathlib) :-)
To me it seems reasonable for match x with
to be accepte instead of nomatch x
, but I didn’t follow the discussions around nomatch
and nofun
fully. OTOH, the nomatch
is a nice explicit herald. :shrug:
Joachim Breitner (Mar 02 2024 at 09:34):
I also wonder if the nofun
keyword is necessary if (nomatch \.)
is equivalent (assuming it is)
Mario Carneiro (Mar 02 2024 at 09:38):
nofun
is to fun | a => _ | b => _
as nomatch x
is to match x with | a => _ | b => _
Mario Carneiro (Mar 02 2024 at 09:39):
It's also not equivalent to that, it's equivalent to (nomatch ., ., .)
with the appropriate number of .
Mario Carneiro (Mar 02 2024 at 09:40):
that is, the empty argument might not be the first one
Mario Carneiro (Mar 02 2024 at 09:42):
although, having written that, the nomatch a, b
form is hella ambiguous and I think it's a good argument for match a, b with
working
Mario Carneiro (Mar 02 2024 at 09:45):
I didn’t follow the discussions around
nomatch
andnofun
fully
There weren't really any (at least not in public), it was a suggestion and then an implementation. I recall Scott mentioning that he was surprised it was taken seriously
Mario Carneiro (Mar 02 2024 at 09:46):
The implementation is based on fun.
and match x with.
which I added to std to replace uses of the empty pattern match (match x with end
and def foo : empty -> A.
) in lean 3
Mario Carneiro (Mar 02 2024 at 09:48):
the dot was there to avoid ambiguity with the lean parser, it would not have been necessary if implemented in core, but then it got absorbed into core
Mario Carneiro (Mar 02 2024 at 09:51):
Although another syntax suggestion that is making the rounds in rust land is the "never pattern" !
, and some discussion about deprecating match x {}
in favor of match x { ! }
. Agda uses ()
as a never pattern but I think that's not an option in either lean or rust because that means the value of the unit type
Mario Carneiro (Mar 02 2024 at 09:53):
The lean version of that might look like fun | !
Mario Carneiro (Mar 02 2024 at 09:54):
but on the other hand lean doesn't use !
as syntax for the empty type, and adding it as a term would probably make for lots of ambiguity with all the other uses of !
Last updated: May 02 2025 at 03:31 UTC