Zulip Chat Archive

Stream: lean4

Topic: equation compiler magic in lean4


Eric Rodriguez (Nov 25 2022 at 14:15):

for example, consider this lean3 code:

inductive s : Type | A | B
example : s.A  s.B.
example : s.A  s.B := by {have : s.A  s.B := λ h, match h with end, assumption}

how would we write these in lean4? I heard something about a nomatch keyword, but I can't seem to find much documentation about it

Ruben Van de Velde (Nov 25 2022 at 14:15):

I think with fun.

Ruben Van de Velde (Nov 25 2022 at 14:16):

theorem not_false' : ¬false := fun.

Sebastian Ullrich (Nov 25 2022 at 14:20):

There's documentation right in the editor as soon as you type in nomatch :) . Though I suppose you first need to know that it is a term syntax. https://leanprover-community.github.io/mathlib4_docs/Lean/Parser/Term.html#Lean.Parser.Term.nomatch

Kyle Miller (Nov 25 2022 at 14:21):

Ruben Van de Velde said:

theorem not_false' : ¬false := fun.

That . is a syntax error.

Here's one way to do nomatch:

example : s.A  s.B := fun h => nomatch h

Sebastian Ullrich (Nov 25 2022 at 14:22):

If you want to golf: (nomatch ·)

Ruben Van de Velde (Nov 25 2022 at 14:26):

Kyle Miller said:

Ruben Van de Velde said:

theorem not_false' : ¬false := fun.

That . is a syntax error.

Here's one way to do nomatch:

example : s.A  s.B := fun h => nomatch h

Really? I copied it from mathlib4

Jannis Limperg (Nov 25 2022 at 14:27):

The fun. syntax is a std4/mathlib4 addition.

Kyle Miller (Nov 25 2022 at 14:31):

@Sebastian Ullrich Has anyone considered nofun to go with nomatch?

macro "nofun" : term => `((nomatch ·))

inductive s : Type | A | B
example : s.A  s.B := nofun

Kevin Buzzard (Nov 25 2022 at 16:59):

That's not appropriate because these proofs are a lot of fun

Mario Carneiro (Nov 26 2022 at 08:00):

Kyle Miller said:

Sebastian Ullrich Has anyone considered nofun to go with nomatch?

macro "nofun" : term => `((nomatch ·))

inductive s : Type | A | B
example : s.A  s.B := nofun

That's exactly the fun. syntax mentioned above

Alex Keizer (Nov 26 2022 at 10:09):

Kyle Miller said:

Ruben Van de Velde said:

theorem not_false' : ¬false := fun.

That . is a syntax error.

Here's one way to do nomatch:

example : s.A  s.B := fun h => nomatch h

IIRC, the fun . syntax is defined by mathlib4, not Lean itself

Ruben Van de Velde (Nov 26 2022 at 10:56):

Alex Keizer said:

Kyle Miller said:

Ruben Van de Velde said:

theorem not_false' : ¬false := fun.

That . is a syntax error.

Here's one way to do nomatch:

example : s.A  s.B := fun h => nomatch h

IIRC, the fun . syntax is defined by mathlib4, not Lean itself

Yeah, Jannis mentioned this as well

Kyle Miller (Nov 26 2022 at 11:25):

@Mario Carneiro That may be functionally the same, but the serious part of what I was getting at is why not have the syntax parallel nomatch? You can't guess that fun. might be related.

Kyle Miller (Nov 26 2022 at 11:26):

@Mario Carneiro That may be functionally the same, but the serious part of what I was getting at is why not have the syntax parallel nomatch? You can't guess that fun. might be related.

Mario Carneiro (Nov 26 2022 at 11:26):

I actually prefer fun. for its syntactic consistency. There is also intro. and match x with. in the same file

Mario Carneiro (Nov 26 2022 at 11:27):

nomatch is a more special notation IMO

Mario Carneiro (Nov 26 2022 at 11:27):

it doesn't compose as well with other stuff

Mario Carneiro (Nov 26 2022 at 11:33):

(In case it isn't clear, the syntax pattern I want to encourage is that anywhere a | a => b list is accepted, a . also works and means an empty match)

Sebastian Ullrich (Nov 26 2022 at 11:40):

I like the consistency idea, but I can't say I like . specifically. It is essentially a Coq remnant that withered down to one specific use case.

Mario Carneiro (Nov 26 2022 at 12:51):

We can potentially do "nothing at all" as the marker, but that would have to be integrated with the original syntax

Mario Carneiro (Nov 26 2022 at 12:52):

this would be following my general plan to replace most uses of 1+ syntax in lean with 0+ syntax

David Thrane Christiansen (Nov 26 2022 at 12:58):

What about nested matches of constructorless types? Agda has the absurd pattern (), and it can occur in any position that expects a pattern, not just the top level. A pattern that validly contains an absurd pattern is then never associated with an RHS. It's quite convenient for pointing at precisely why a case is impossible.

Mario Carneiro (Nov 26 2022 at 12:59):

lean automatically does nested pattern matching of impossible cases, you just don't mention the case

Mario Carneiro (Nov 26 2022 at 13:00):

() is obviously not available as the absurd pattern in lean since it's the pattern for unit

Sebastian Ullrich (Nov 26 2022 at 13:01):

It's quite convenient for pointing at precisely why a case is impossible.

I think that would be a nice addition! Though perhaps not terribly high-priority.

Sebastian Ullrich (Nov 26 2022 at 13:03):

Mario Carneiro said:

We can potentially do "nothing at all" as the marker, but that would have to be integrated with the original syntax

I think we've rejected that for Lean 3 before. There should be something indicating an absurd pattern match

Mario Carneiro (Nov 26 2022 at 13:04):

okay, so... .

Mario Carneiro (Nov 26 2022 at 13:05):

it's derived from the lean 3 syntax but not the same, since it goes in arbitrary terms instead of only coming at the end of a definition

Sebastian Ullrich (Nov 26 2022 at 13:19):

Is this such a common occurrence that every character counts? I would much prefer a more readable notation such as match | absurd, which is forward-compatible with David's suggestion.

Sebastian Ullrich (Nov 26 2022 at 13:21):

Tbh the expected use frequency was the whole reason we introduced only nomatch and not nofun etc.

Mario Carneiro (Nov 26 2022 at 13:47):

yes, this does come up in places where every character counts

Mario Carneiro (Nov 26 2022 at 13:48):

Here is an example where I would really not have liked to need to use fun | absurd

Mario Carneiro (Nov 26 2022 at 13:52):

In Std, there are 47 uses of fun., 44 uses of nomatch and 2 uses of match e with. (these are used in places where match is used as a tactic, since there is no nomatch tactic)

Mario Carneiro (Nov 26 2022 at 13:53):

nomatch feels very ad hoc and incomplete compared to the others, since it is only defined for the expected common case

David Thrane Christiansen (Nov 26 2022 at 13:58):

I wasn't suggesting () as concrete syntax in Lean, just that it's nice to have _some_ syntax for absurd patterns. It's convenient to leave them out most of the time, but sometimes code communicates more when the author can be more explicit.

Kevin Buzzard (Nov 26 2022 at 15:24):

How about a Unicode contradiction symbol as notation for something like nomatch

James Gallicchio (Nov 26 2022 at 17:58):

When I show other CS students ocaml's | _ -> . absurd case syntax they do find the dot very confusing and arbitrary; I would not mind a symbol like \bot or a full absurd keyword to represent a pattern that matches an empty type with no RHS

Parth Shastri (Nov 26 2022 at 18:23):

What about having . functioning as an optional end? (Or if . is too terse, then just end) That way the syntax works beyond the special case of an empty match and could (though I wouldn't recommend it) be used to delimit nested matches without needing parentheses or indentation, which might be useful for macros:

match m with | 0 => n | 1 => match n with | 0 => m | n' + 1 => n'. | m' + 2 => m'

James Gallicchio (Nov 26 2022 at 20:03):

(that . is incredibly hard to spot in that snippet, but would love end)

Sebastian Ullrich (Nov 26 2022 at 22:39):

Why would this matter for macros? Macros manipulate syntax trees, not strings.

Parth Shastri (Nov 28 2022 at 04:12):

Interesting, I didn't realize that macros support matches with no branches:

macro "test%" : term =>
  let l := #[]
  let r := #[]
  `(match sorryAx False with $[| $l => $r]*)

#check test% -- nomatch (_ : False) : ?m.2440

So having an explicit terminator is not necessary.

Mario Carneiro (Nov 28 2022 at 07:45):

this is technically a malformed syntax object, since the parser is declared to accept one or more match branch... but yes, the rejection of empty matches is only "skin deep" - the support is all there in the backend, you just have to bypass the front end or pass an invalid syntax and hope that the syntax quotation code doesn't assert that the array is nonempty in the future

Mario Carneiro (Nov 28 2022 at 07:46):

That's how match e with. is implemented BTW - it just calls the match backend with an empty list of branches


Last updated: Dec 20 2023 at 11:08 UTC