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:

image.png

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:

image.png

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'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.

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 and nofun 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