Zulip Chat Archive

Stream: lean4

Topic: Recursive definition in `Expr`


Mathis Bouverot-Dupuis (Oct 04 2024 at 11:57):

Hello ! I'm building some terms in Expr, and in particular I would like to define a recursive function. I'm having a hard time using recursors (.rec, .recOn, etc).

  1. What is the complete list of recursors which are automatically defined for an inductive ?
  2. Is there a way to do this with a higher-level API than recursors ?

Eric Wieser (Oct 04 2024 at 12:28):

You can write

def foo (e : Expr) : Nat :=
  match e with
  | .proj _ _ => sorry
  | .app f a => foo f + foo a
-- etc

Henrik Böving (Oct 04 2024 at 12:29):

I think Mathis means generating an Expr that represents a recursive function

Mathis Bouverot-Dupuis (Oct 04 2024 at 12:30):

Henrik Böving said:

I think Mathis means generating an Expr that represents a recursive function

Yes exactly.

Eric Wieser (Oct 04 2024 at 12:34):

I guess my suggeston then becomes "can you emit Syntax and elaborate it, rather than building an Expr"?

Mathis Bouverot-Dupuis (Oct 04 2024 at 12:37):

I would prefer not as I use some Expr-related machinery to build my terms, such as unification or local declarations. Is there a way to stay in Expr ?

Eric Wieser (Oct 04 2024 at 13:16):

By Expr-related, do you mean TermElabM-related?

Eric Wieser (Oct 04 2024 at 13:16):

You can jump back and forth between Expr and Syntax using docs#Lean.Expr.toSyntax and docs#Lean.Elab.Term.elabTerm

Mathis Bouverot-Dupuis (Oct 04 2024 at 13:36):

Eric Wieser said:

By Expr-related, do you mean TermElabM-related?

Yes, I'm using TermElabM and MetaM.

Mathis Bouverot-Dupuis (Oct 04 2024 at 13:37):

I see, so how would I use Syntax to build a match expression ? EDIT : a recursive definition (I was thinking about fixpoints)

Eric Wieser (Oct 04 2024 at 13:45):

Can you give an example of the kind of expression you want to build?

Mathis Bouverot-Dupuis (Oct 04 2024 at 13:49):

I would like to build something like this :

def myListMap (f : α  β) (xs : List α) : List β :=
  match xs with
  | [] => []
  | x :: xs => f x :: myListMap f xs

Eric Wieser (Oct 04 2024 at 13:55):

import Lean

open  Lean Meta Elab Term

def foo : TermElabM Expr := do
  let stx  `(term|
    let rec myListMap {α β} (f : α  β) (xs : List α) : List β :=
      match xs with
      | [] => []
      | x :: xs => f x :: myListMap f xs
    myListMap)
  elabTerm stx none

Mathis Bouverot-Dupuis (Oct 04 2024 at 14:08):

With your definition foo, I tried inspecting the resulting term :

#eval do
  let e  instantiateMVars =<< foo
  IO.println s!"{ ← ppExpr e }"

And I get (fun myListMap ↦ myListMap) ?m.16. How come the result has unassigned metavars ?

Eric Wieser (Oct 04 2024 at 14:50):

I think that metavariable is one satisfying docs#Lean.Elab.Term.isLetRecAuxMVar

Eric Wieser (Oct 04 2024 at 14:55):

I think the idea is that once you finally add the declaration to the environment, the let rec is added at the same time and the metavariable resolved; but I've not tried using let recs in meta code before


Last updated: May 02 2025 at 03:31 UTC