Zulip Chat Archive

Stream: new members

Topic: Applying tactic `cases` on a non-variable


Gabriel Alfour (Nov 09 2023 at 09:06):

In tactic mode, in my hypothesis, I have something of an application (like f x), and I'd like to do cases on it.
In Coq, when I do so, all instances of f x get pattern-matched over. In Lean4, nothing happens.

I have tried:

  1. Doing something like let fx := f x, and then rewriting using rw [fx,\left fx] at hypothesis, but does not work either.
  2. Doing something like let fx := fx, then let fx_eq : fx = f x := rfl and then cases fx, but it does not work either. Not even fx gets destructed.

What would be the Lean4 way of performing this step?

Code below if anyone is interested

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
      have f_ih_r := f_ih ?_
      . admit
      . unfold main at success
        -- Attempt 1
          -- cases (main ctx arg)
        -- Attempt 2
          -- let marg := main ctx arg
          -- rewrite [marg] at success
        -- Attempt 3
          -- let marg := main ctx arg
          -- have marg_eq : marg = main ctx arg := rfl
          -- rewrite [← marg_eq] at success arg_ih
          -- cases marg
        . sorry
    . sorry



end Typed


-- environment eval
-- inductive eval_step_result : Type

-- def eval_step

Ruben Van de Velde (Nov 09 2023 at 09:13):

Did I not see someone pointing out cases h : f x to you in another thread?

Gabriel Alfour (Nov 09 2023 at 09:19):

@Ruben Van de Velde I have tried many permutations that were pointed to me, I might have missed that one, let me check

Gabriel Alfour (Nov 09 2023 at 09:21):

@Ruben Van de Velde
still the same problem, f x in the hypotheses (main ctx arg in the code) does not get destructed
But I get an equality relation on it!!! Thanks
Is this the expected way to do so in Lean4? Looks a bit verbose (comparable to case_eq in Coq), but if it is, I can make-do with it!


Last updated: Dec 20 2023 at 11:08 UTC