fix: make structure instance notation (e.g., { a, b }) works in patterns after we define the Set notation in Mathlib

This commit is contained in:
Leonardo de Moura 2022-05-25 19:14:22 -07:00
parent a26827f58b
commit bef1cd4872
2 changed files with 81 additions and 1 deletions

View file

@ -221,7 +221,16 @@ partial def collect (stx : Syntax) : M Syntax := withRef stx <| withFreshMacroSc
/- Similar to previous case -/
doubleQuotedNameToPattern stx
else if k == choiceKind then
let args := stx.getArgs
/- Remark: If there are `Term.structInst` alternatives, we keep only them. This is a hack to get rid of
Set-like notation in patterns. Recall that in Mathlib `{a, b}` can be a set with two elements or the
structure instance `{ a := a, b := b }`. Possible alternative solution: add a `pattern` category, or at least register
the `Syntax` node kinds that are allowed in patterns. -/
let args :=
let args := stx.getArgs
if args.any (·.isOfKind ``Parser.Term.structInst) then
args.filter (·.isOfKind ``Parser.Term.structInst)
else
args
let stateSaved ← get
let arg0 ← collect args[0]
let stateNew ← get

View file

@ -0,0 +1,71 @@
structure Foo where
a : Nat
b : Nat
def bla (x : Foo) : IO Unit := do
let { a, b } := x
def Set (α : Type u) := α → Prop
def setOf {α : Type u} (p : α → Prop) : Set α :=
p
namespace Set
protected def mem (a : α) (s : Set α) :=
s a
instance : Membership α (Set α) :=
⟨Set.mem⟩
protected def subset (s₁ s₂ : Set α) :=
∀ {a}, a ∈ s₁ → a ∈ s₂
instance : EmptyCollection (Set α) :=
⟨λ a => false⟩
protected def insert (a : α) (s : Set α) : Set α :=
fun b => b = a b ∈ s
protected def singleton (a : α) : Set α :=
fun b => b = a
syntax "{" term,+ "}" : term
macro_rules
| `({$x:term}) => `(Set.singleton $x)
| `({$x:term, $xs:term,*}) => `(Set.insert $x {$xs:term,*})
#check { 1, 2 } -- Set Nat
end Set
def f1 (a b : Nat) : Set Nat :=
{ a, b }
def f2 (a b : Nat) : Foo :=
{ a, b }
def f3 (a b : Nat) :=
{ a, b }
#check f3 -- Nat → Nat → Set Nat
def f4 (a b : α) :=
{ a, b }
#check @f4 -- {α : Type u_1} → αα → Set α
def f5 (a b : Nat) :=
{ a, b : Foo }
def boo1 (x : Foo) : IO Unit :=
let { a, b } := x
pure ()
def boo2 (x : Foo) : IO Unit := do
let { a, b } := x
pure ()
def boo3 (x : Nat → IO Foo) : IO Nat := do
let { a, b } ← x 0
return a + b