Zulip Chat Archive
Stream: lean4
Topic: Implicit arguments in getAppArgs
Moritz Doll (May 23 2023 at 21:36):
Given variable {a b : ℕ}
and the term a = b
if I elaborate this term with elabTerm
and then apply Lean.Expr.getAppArgs'
(same for unprimed and the second component of Lean.Expr.getAppFnArgs
) it yields #[ℕ, a, b]
, but I would expect #[a, b]
. Is there some way to get rid of implicit arguments?
Kyle Miller (May 23 2023 at 21:39):
Are you specifically wanting to process equalities? docs4#Lean.Expr.eq? lets you get the type, LHS, and RHS as a tuple
Moritz Doll (May 23 2023 at 21:43):
Unfortunately not. Background is that I resumed porting congrm
and for matching the pattern I of course only want to deal with the explicit arguments
Kyle Miller (May 23 2023 at 21:44):
I think there's a function used by other congr meta code to get detailed information about every function argument.
Kyle Miller (May 23 2023 at 21:45):
here's a place it's used in mathlib code: https://github.com/leanprover-community/mathlib4/blob/master/Mathlib/Tactic/Congr!.lean#LL540C16-L540C31
Kyle Miller (May 23 2023 at 21:47):
You can filter the arguments by which ones have a paramInfo.binderInfo == .default
Moritz Doll (May 23 2023 at 22:06):
thanks, there is actually ParamInfo.isExplicit
Moritz Doll (May 23 2023 at 22:07):
which does the exact equality check
Moritz Doll (May 23 2023 at 22:32):
Ok, making progress, but still not quite there. In the function below I consistently get that the length of pinfo
is zero:
def _root_.Lean.Expr.getExplicitArgs (f : Expr) : MetaM (Array Expr) := do
let args := f.getAppArgs
let pinfo := (← Lean.Meta.getFunInfoNArgs f args.toList.length).paramInfo
logInfo s!"all arguments: {← args.mapM ppExpr} and num patternInfos: {pinfo.toList.length}"
return (pinfo.zip args).filterMap (λ arg => if arg.1.isExplicit then some arg.2 else none)
Mario Carneiro (May 23 2023 at 22:35):
Moritz Doll (May 23 2023 at 22:42):
There you go:
import Lean.Meta.FunInfo
import Lean.Elab.Tactic
open Lean Parser Tactic Elab Tactic Meta
def _root_.Lean.Expr.getExplicitArgs (f : Expr) : MetaM (Array Expr) := do
let args := f.getAppArgs
let pinfo := (← Lean.Meta.getFunInfoNArgs f args.toList.length).paramInfo
logInfo s!"all arguments: {← args.mapM ppExpr} and patternInfos: {pinfo.toList.length}"
return (pinfo.zip args).filterMap (λ arg => if arg.1.isExplicit then some arg.2 else none)
syntax (name := prettyExpr) "prettyExpr " term : tactic
elab_rules : tactic | `(tactic| prettyExpr $expr:term) => withMainContext do
let _foo ← (← elabTerm expr none).getExplicitArgs
return
-- Testing for implicit arguments in function application
example (a b c : α) (h : b = c) : a = b ↔ a = c := by
prettyExpr (_ = _)
prettyExpr ((· = · ) _ _)
prettyExpr (@Eq _ _)
sorry
Mario Carneiro (May 23 2023 at 22:46):
looks like you need to pass the head of the function, that is f.getAppFn
, to getFunInfoNArgs
instead of f
Moritz Doll (May 23 2023 at 22:49):
yes that works, thanks. What is the reason for (_ = _)
having three arguments, but ((· = · ) _ _)
having two?
Mario Carneiro (May 23 2023 at 22:51):
the first one is @Eq _ _ _
and the second one is (fun x y => @Eq _ x y) _ _
Kyle Miller (May 23 2023 at 23:33):
Rather than args.toList.length
you can do args.size
. And just in case you ever need it (if you don't also need the array of arguments), there's Lean.Expr.getAppNumArgs
.
Moritz Doll (May 24 2023 at 00:03):
I knew about getAppNumArgs
, but not Array.size
, thanks
Last updated: Dec 20 2023 at 11:08 UTC