Zulip Chat Archive
Stream: lean4
Topic: match in quasiquotation
Simon Hudon (Jan 11 2022 at 01:55):
I'm trying to build the syntax tree for
match List.get? [1,2,3] with
| none => 2
| some x => x
Here is the code I wrote for that (based on the Lean 4 code base):
def test' : TermElabM Expr := do
let discr ← `(List.get? [1,2,3])
let p1 ← `( none )
let p2 ← `( some x )
let br1 ← `(matchAltExpr| | $p1 => 3)
let br2 ← `(matchAltExpr| | $p2 => x)
let brs := #[br1, br2]
let e ← `(match $discr:term with $brs:matchAlt*)
elabTerm e (some (mkConst `Nat))
It fails to elaborate. He is what happens when I print it out:
let _discr := List.get? [1, 2, 3];
sorryAx Nat
What am I missing?
Simon Hudon (Jan 11 2022 at 02:00):
Actually the following is closer to what I've seen in the Lean 4 code base but it has the same effect:
def test' : TermElabM Expr := do
let discr ← `(List.get? [1,2,3])
let discr := #[discr]
let p1 ← `( none )
let p1 := #[p1]
let p2 ← `( some x )
let p2 := #[p2]
let br1 ← `(matchAltExpr| | $[$p1:term],* => 3)
let br2 ← `(matchAltExpr| | $[$p2:term],* => x)
let brs := #[br1, br2]
let e ← `(match $[$discr:term],* with $brs:matchAlt*)
elabTerm e (some (mkConst `Nat))
Mac (Jan 11 2022 at 04:31):
My first thought would be that the x
in `( some x )
is likely not the same as the x
in `(matchAltExpr| | $p2 => x)
due to hygiene.
Simon Hudon (Jan 11 2022 at 04:41):
replacing that x
with 2
doesn't help
Mario Carneiro (Jan 11 2022 at 04:42):
the easy way to fix that is to do let x <- `(x)
and then use $x
in its occurrences
Mario Carneiro (Jan 11 2022 at 04:42):
Could you post a #mwe?
Mario Carneiro (Jan 11 2022 at 04:45):
I get unknown parser matchAltExpr
when parsing test
and test'
Mario Carneiro (Jan 11 2022 at 04:51):
Here's an MWE of your first example:
import Lean
open Lean Parser Term Elab Term
def test' : TermElabM Expr := do
let discr ← `(List.get? [1,2,3])
let p1 ← `( none )
let p2 ← `( some x )
let br1 ← `(matchAltExpr| | $p1 => 3)
let br2 ← `(matchAltExpr| | $p2 => x)
let brs := #[br1, br2]
let e ← `(match $discr:term with $brs:matchAlt*)
elabTerm e (some (mkConst `Nat))
#eval test'
<TermElabM>:0:0: error: type mismatch
none
has type
Option ?m.60 : Type ?u.59
but is expected to have type
Nat → Option ?m.47 : Type ?u.46
let _discr._@.Test._hyg.3 : Nat -> (Option.{?_uniq.46} ?_uniq.47) := List.get?.{?_uniq.3} ?_uniq.47 (List.cons.{?_uniq.7} ?_uniq.47 (OfNat.ofNat.{?_uniq.7} ?_uniq.47 1 ?_uniq.12) (List.cons.{?_uniq.20} ?_uniq.47 (OfNat.ofNat.{?_uniq.20} ?_uniq.47 2 ?_uniq.25) (List.cons.{?_uniq.33} ?_uniq.47 (OfNat.ofNat.{?_uniq.33} ?_uniq.47 3 ?_uniq.38) (List.nil.{?_uniq.46} ?_uniq.47)))); sorryAx.{1} Nat Bool.true
The latter part matches the expression you claim (although printed less clearly), but this also comes with an error message that indicates more of the problem
Mario Carneiro (Jan 11 2022 at 04:54):
Note that you get the same error even without any of the syntax construction stuff:
#check
match List.get? [1,2,3] with
| none => 3
| some x => x
type mismatch
none
has type
Option ?m.2251 : Type ?u.2250
but is expected to have type
Nat → Option Nat : Type
Mario Carneiro (Jan 11 2022 at 04:55):
the problem being that List.get? [1,2,3]
is an unapplied function, you need to get a specific index before it will yield an option
Mario Carneiro (Jan 11 2022 at 05:04):
Fixed:
import Lean
open Lean Parser Term Elab Term
def test' : TermElabM Expr := do
let discr ← `(List.get? [1,2,3] 0)
let x ← `(x)
let p1 ← `( none )
let p2 ← `( some $x )
let br1 ← `(matchAltExpr| | $p1 => 3)
let br2 ← `(matchAltExpr| | $p2 => x)
let brs := #[br1, br2]
let e ← `(match $discr:term with $brs:matchAlt*)
elabTerm e (some (mkConst `Nat))
#eval show TermElabM _ from do
let e ← withDeclName `foo test'
Meta.ppExpr e
let _discr := List.get? [1, 2, 3] 0;
match List.get? [1, 2, 3] 0 with
| none => 3
| some x => x
Not sure what's up with the dead let
expression. It seems like a bug in match elaboration
Simon Hudon (Jan 11 2022 at 05:17):
Thank you!
It seems that let x ← `(x)
can be dropped and it still works
Simon Hudon (Jan 11 2022 at 05:19):
What remains is:
List.get? [1, 2, 3] -> List.get? [1, 2, 3] 0
so that we pattern match onOption Nat
instead ofNat -> Option Nat
- Run the elaborator from within a call to
withDeclName
.
Item 2.
I'm not sure why it matters. Can you explain?
Mario Carneiro (Jan 11 2022 at 05:35):
You can try it without and see the error message
Mario Carneiro (Jan 11 2022 at 05:36):
match
generates auxiliary definitions, and it needs a base declaration name to do that. When using this as part of a tactic that will not be a problem, but in testing code such as this (in the scope of an #eval
) there is no declaration name so we have to give it a dummy name
Simon Hudon (Jan 11 2022 at 05:36):
I wasn't getting an error message without it. The elaboration would only be incomplete
Simon Hudon (Jan 11 2022 at 05:37):
I see! Thanks for the explanation!
Mario Carneiro (Jan 11 2022 at 05:37):
are you using the same MWE as me? when I remove the withDeclName
I get an error
Mario Carneiro (Jan 11 2022 at 05:37):
<TermElabM>:0:0: error: auxiliary declaration cannot be created when declaration name is not available
Mario Carneiro (Jan 11 2022 at 05:38):
certainly I wouldn't have added that part otherwise
Mario Carneiro (Jan 11 2022 at 05:38):
If you are testing it in the real context and don't get that error, that's fine and you don't need it
Mario Carneiro (Jan 11 2022 at 05:40):
although the error seems to be reported through a side channel, there is no red squiggle on the #eval
and it just evaluates to something containing a sorryAx nat
Simon Hudon (Jan 11 2022 at 05:43):
Yes I see. I was calling it from within MetaM
and the error seems to get discarded. If I eval the TermElabM
, I see the error. That's going to make things easier
Gabriel Ebner (Jan 11 2022 at 09:04):
Mac said:
My first thought would be that the
x
in`( some x )
is likely not the same as thex
in`(matchAltExpr| | $p2 => x)
due to hygiene.
It is exactly the same x
. You only get a new x
if you're inside a withFreshMacroScope
.
Simon Hudon (Jan 11 2022 at 17:11):
Thanks for the clarification!
Last updated: Dec 20 2023 at 11:08 UTC