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 withnomatch
?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 match
es 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