Zulip Chat Archive
Stream: new members
Topic: Add new goal and hypothesis at the same time
Gabriel Alfour (Nov 09 2023 at 00:06):
Hi, still new to Lean4.
I have a hypothesis h : A -> B
, in tactic mode, I'd like to write something like pose (h _)
, this should:
- Create a new goal / proof obligation for A
- After this new goal / proof obligation is performed, add B to the hypotheses
If there's no equivalent, I'd like to know what is an equivalent to assert A
in Coq. ChatGPT gives me old syntax, and I still haven't found a guide of "Lean4 for the old Coq-er"
Thanks!
Gabriel Alfour (Nov 09 2023 at 00:08):
I have found the equivalent of assert A
, which is have _ : A := show ...
!
I am still looking for something like pose (h _)
Eric Wieser (Nov 09 2023 at 00:10):
I think that's just have := h ?_
Gabriel Alfour (Nov 09 2023 at 00:13):
@Eric Wieser nice, thx! Is there an equivalent that reverses the two goals? (So that I have to prove the implicit obligation from ?_
first?)
Yaël Dillies (Nov 09 2023 at 00:13):
Yes, it's suffices
Gabriel Alfour (Nov 09 2023 at 00:15):
@Yaël Dillies I'm sorry, I don't get it. What is the equivalent of have h_applied := h ?_
with suffices
?
Notification Bot (Nov 09 2023 at 00:24):
This topic was moved here from #general > Add new goal and hypothesis at the same time by Kyle Miller.
Kyle Miller (Nov 09 2023 at 00:25):
@Gabriel Alfour Something we like around here to ground questions is an #mwe -- if you can create a little example
s to accompany your questions that set up some sort of context that illustrates what you're talking about, then people can fill it in with a concrete suggestion.
Gabriel Alfour (Nov 09 2023 at 00:31):
@Kyle Miller sgtm
I tried to share from the Lean4 Editor, but the URL is unwieldy, should I just copy-paste the code like so?
inductive ast : Type
| Lam : String -> ast -> ast
| Var : String -> ast
| App : ast -> ast -> ast
-- rewriting
inductive rewrite_step_result : Type
| Finish
| Next : ast -> rewrite_step_result
open ast
open rewrite_step_result
def substitute (expr : ast) (var : String) (sub : ast) :=
match expr with
| Var var' => if var = var' then sub else Var var'
| App f arg => App (substitute f var sub) (substitute arg var sub)
| Lam var' body => if var = var' then Lam var' body else Lam var' (substitute body var sub)
def rewrite_step : ast -> rewrite_step_result
| Var _var => Finish
| Lam _var _body => Finish
| App f arg => (
match rewrite_step f with
| Finish => (
match rewrite_step arg with
| Finish => (
match f with
| Lam var body => Next (substitute body var arg)
| _ => Finish
)
| Next arg' => Next (App f arg')
)
| Next f' => Next (App f' arg)
)
def is_normal (expr : ast) := rewrite_step expr = Finish
open Nat
def rewrite_n_steps (expr : ast) (n : Nat) :=
match n with
| zero => Next expr
| succ n' => (
match rewrite_step expr with
| Finish => Finish
| Next expr' => rewrite_n_steps expr' n'
)
def terminates (expr : ast) := ∃ n , rewrite_n_steps expr n = Finish
def looper : ast :=
App (Lam "x" (App (Var "x") (Var "x"))) (Lam "x" (App (Var "x") (Var "x")))
theorem looper_loops : rewrite_n_steps looper 1 = Next looper :=
by
eq_refl
theorem looper_loops_forever : forall n , rewrite_n_steps looper n = Next looper :=
by
intro n
induction n with
| zero => eq_refl
| succ _ ih =>
exact ih
theorem non_terminating : ∃ (expr : ast) , ¬terminates expr :=
by
exists looper
unfold terminates
intro tl
let ⟨ n , ih ⟩ := tl
have ih' : (rewrite_n_steps looper n = Next looper) := looper_loops_forever n
rw [ih] at ih'
contradiction
namespace Typed
inductive type : Type
| Nat
| Fun : type -> type -> type
deriving DecidableEq
inductive tast : Type
| TVar : String -> tast
| TApp : tast -> tast -> tast
| TLam : String -> type -> tast -> tast
open tast
def remove_types : tast -> ast
| TLam v _ty body => Lam v (remove_types body)
| TVar v => Var v
| TApp f arg => App (remove_types f) (remove_types arg)
namespace Typecheck
inductive result : Type
| Fail
| Succeed : type -> result
def context : Type := List (String × type)
open result
open type
def main (ctx : context) : tast -> result
| TVar v => (
match List.lookup v ctx with
| none => Fail
| some ty => Succeed ty
)
| TLam v ty body => (
let ctx := List.cons (v , ty) ctx
main ctx body
)
| TApp f arg => (
match main ctx arg with
| Fail => Fail
| Succeed arg_ty => (
match main ctx f with
| Fail => Fail
| Succeed f' => (
match f' with
| Fun in_ty out_ty => (
if in_ty = arg_ty then Succeed out_ty
else Fail
)
| _ => Fail
)
)
)
end Typecheck
open Typecheck
theorem stlc_terminate :
∀ (ctx : context) (tast : tast) (ty : type) ,
main ctx tast = result.Succeed ty -> ∃ n ,
rewrite_n_steps (remove_types tast) n = Finish :=
by
intros ctx tast ty success
induction tast
. exists 1
. rename_i f arg f_ih arg_ih
-- in the following line, I'd like the two goals generated to be reversed
have f_ih_r := f_ih ?_
. admit
. unfold main at success
--- This is where in Coq, I would do `destruct (main ctx arg)`, and it would get rewritten in all assumptions
end Typed
Kyle Miller (Nov 09 2023 at 00:47):
Code blocks like that are preferred. There's even a web editor link in the upper-right corner.
Kyle Miller (Nov 09 2023 at 00:48):
One feature you might use here are named metavariables:
have f_ih_r := f_ih ?g
case g =>
unfold main at success
sorry
Kyle Miller (Nov 09 2023 at 00:49):
(Lean tradition is to use sorry
to apologize for not being done yet rather than using admit
to concede the argument :smile:)
Kyle Miller (Nov 09 2023 at 00:50):
You can also swap
the goals
Gabriel Alfour (Nov 09 2023 at 08:57):
@Kyle Miller Thanks!
Gabriel Alfour (Nov 09 2023 at 11:35):
@Kyle Miller swap
is not recognized
Gabriel Alfour (Nov 09 2023 at 11:36):
and can't find it online
Eric Wieser (Nov 09 2023 at 11:40):
You'll need import Mathlib.Tactic
, though probably there's a smaller file you could import
Martin Dvořák (Nov 09 2023 at 12:20):
import Mathlib.Tactic.PermuteGoals
Richard Copley (Nov 09 2023 at 12:26):
Or Mathlib.Tactic.Common
.
This file imports all tactics which do not have significant theory imports,
and hence can be imported very low in the theory import hierarchy,
thereby making tactics widely available without needing specific imports.
So, including it in user code is not exactly what it is meant for, but one can argue that user code that does not have many imports is also "low in the theory import hierarchy".
Last updated: Dec 20 2023 at 11:08 UTC