Zulip Chat Archive
Stream: new members
Topic: Converting a \forall into a \exists inside a tactic
florath (Sep 12 2024 at 10:37):
Hello!
As a first project in meta-programming I'm trying to write a tactic that handles expressions in First-Order-Logic, like:
example : True := by handle_logic
example : (∃ (x1 : Prop), x1) := by handle_logic
example : (∀ (x1 : Prop), (((x1 → (x1)) → ((∃ (x4 : Prop), (x4 → x4)) ∨ x1)))) := by handle_logic
If a proof exists, it should output the used tactics, e.g.
example : ((∃ (x4 : Prop), x4) ∧ (∃ (x5 : Prop), x5)) := by handle_logic
Output:
constructor
apply Exists.intro True
decide
apply Exists.intro True
decide
Some operators are working (like Or, And, Implication, ...), but I did not get the "handleForall" completed.
What I want to do is: if a "∀ (<var_name> : <var_type>), <body>" is found, I want to add a "have : ∃ (<var_name> : <var_type>), <body>" tactic. The idea is then to check for True and False and if one resolves into False, the "∀" is False if not it's True. (I know that I'm mixing different levels of True/False but I hope it is understandable.)
I did not manage to get all the needed information in the correct form (types) and put them together and execute the tactic.
Here are the first some lines of my function that handles the Forall case:
partial def handleForall (expr : Expr) (lB : IO.Ref (List String)) (tB : IO.Ref (List String)): TacticM NodeState := do
logB lB s!"handleForall: expression [{expr}]"
let body := expr.bindingBody! -- Get the body of the forall
logB lB s!"handleForall: body [{body}]"
let varType := expr.bindingDomain! -- Get the type of the bound variable
logB lB s!"handleForall: varType [{varType}]"
let localTB ← IO.mkRef ([] : List String)
-- Extract the variable and body of the forall expression
let varName := expr.bindingName!
logB lB s!"handleForall: Bound variable [{varName}]"
-- Convert varName, varType, and body to TSyntax format for use in tactics
-- let varNameSyntax := mkIdent varName
let varNameSyntax : TSyntax `ident := mkIdent varName
logB lB s!"handleForall: varNameSyntax [{varNameSyntax}]"
let varTypeSyntax ← Expr.toSyntax varType
logB lB s!"handleForall: varTypeSyntax [{varTypeSyntax}]"
let bodySyntax ← Expr.toSyntax body
logB lB s!"handleForall: bodySyntax [{bodySyntax}]"
-- Try substituting the bound variable with False
logB lB "handleForall: Trying exists False"
let localFalseTB ← IO.mkRef ([] : List String)
-- XXX Test for "(∀ (x1 : Prop), x1)" as I have no idea how to
-- extract and use the variable and the term.
evalTactic (← `(tactic| have h_false : ∃ (x1 : $varTypeSyntax), $bodySyntax := by
exists False))
-- XXX "varNameSyntax" has type TSyntax `ident : Type but is expected to have type TSyntax `Lean.binderIdent : Type
-- XXX "varName" has type Name : Type but is expected to have type TSyntax `Lean.binderIdent : Type
-- evalTactic (← `(tactic| have h_false : ∃ ($varName : $varTypeSyntax), $bodySyntax := by exists False))
-- XXX What is the state of the goal? Is this now an "∃" statement?
And logs from a simple test:
handleForall: expression [forall (x1 : Prop), x1]
handleForall: body [#0]
handleForall: varType [Prop]
handleForall: Bound variable [x1]
handleForall: varNameSyntax [`x1]
handleForall: varTypeSyntax [(Term.syntheticHole "?" `a._@.miniF2F-Lean4.lean4.src.test.ap039._hyg.8059)]
My questions:
- How to correctly construct the "have" tactic?
- How to get the correct goal (i.e. the
∃ (<var_name> : <var_type>), <body>
?
Any hint is welcome!
Last updated: May 02 2025 at 03:31 UTC