Zulip Chat Archive
Stream: lean4
Topic: Understanding Expressions
Filippo A. E. Nuccio (Aug 30 2024 at 09:15):
I am trying to learn a bit how expressions are handled, and I do not understand what I got wrong: in the example below, I am trying to set up a tactic that detects if there are functions in the context:
import Lean.Elab
partial def ExtrApp : TacticM Unit :=
withMainContext
(do
let lctx ← getLCtx
let mut xs : (List String) := []
for lh in lctx do
if lh.type.isApp then xs := "yes" :: xs
else xs := "no" :: xs
do logInfo m!"{xs}"
return)
elab "exists_app" : tactic => ExtrApp
example (X Y : Type) (f : X → Y) : true := by
exists_app -- [no, no, no, no]
If I modify the first ExtrApp
changing if lh.type.isApp then xs := "yes" :: xs
to if lh.type.isForall then xs := "yes" :: xs
(so, AFAIU, asking for "for all expressions") I get [yes, no, no, yes]
. I do not understand either of the outputs :sad:
Henrik Böving (Aug 30 2024 at 09:22):
isApp
is for detecting function applications not function types themselves
Filippo A. E. Nuccio (Aug 30 2024 at 09:23):
A term of the form f x
for some f : X -> Y
and some x : X
?
Henrik Böving (Aug 30 2024 at 09:23):
yes
Henrik Böving (Aug 30 2024 at 09:23):
Have you read the constructors of Expr and their documentaiton?
Filippo A. E. Nuccio (Aug 30 2024 at 09:24):
Yes, I have read them. I wouldn't go as far as saying I understood them :smile:
Henrik Böving (Aug 30 2024 at 09:24):
With which one are you having trouble then?
Filippo A. E. Nuccio (Aug 30 2024 at 09:26):
Well, I think I understand them when I read them (apart bvar that is a bit obscure due to this de Brujn index), but then I fail my exercices. So I have probably not understood them properly.
Filippo A. E. Nuccio (Aug 30 2024 at 09:27):
Also, I fail to understand the difference from lambda
expressions and forAll
.
Filippo A. E. Nuccio (Aug 30 2024 at 09:27):
Both are terms of some Pi type, no?
Henrik Böving (Aug 30 2024 at 09:31):
No, lambda
is fun x => ...
and forall
is (x : a) -> b x
Henrik Böving (Aug 30 2024 at 09:32):
in particular forall also covers the case where the output type does not depend on the input value so a -> b
as well. So in general inferring the type of a lambda
should always yield a forall
Henrik Böving (Aug 30 2024 at 09:33):
Filippo A. E. Nuccio said:
A term of the form
f x
for somef : X -> Y
and somex : X
?
Also this view is not quite right. Expr
is just syntax, you can trivially construct type incorrect Expr
. So app
really just syntactically represents f x
, whether f
and x
are of the right type is a whole other question.
Filippo A. E. Nuccio (Aug 30 2024 at 09:51):
Henrik Böving said:
No,
lambda
isfun x => ...
andforall
is(x : a) -> b x
Not sure I understand this; I see your point below that these are "pure syntax" and can be wrong (in the sense that they do not typecheck), but why do you say that these things are different type-theoretically?
Patrick Massot (Aug 30 2024 at 09:52):
They are very different: one can be the type of the other.
Patrick Massot (Aug 30 2024 at 09:53):
fun x : Nat ↦ x
is a lambda
, while Nat → Nat
is a forall
.
Patrick Massot (Aug 30 2024 at 09:53):
The second one is the type of the first one.
Filippo A. E. Nuccio (Aug 30 2024 at 09:53):
You mean that a forall is a Pi-Type?
Patrick Massot (Aug 30 2024 at 09:55):
yes
Filippo A. E. Nuccio (Aug 30 2024 at 09:56):
Oh sure, I was confused. :face_with_peeking_eye:
Henrik Böving (Aug 30 2024 at 09:56):
Filippo A. E. Nuccio said:
You mean that a forall is a Pi-Type?
forall is not only a pi-type, it is the pi type
Filippo A. E. Nuccio (Aug 30 2024 at 09:57):
Yes yes, thanks. I think I am recovering from my blurred state of mind.
Filippo A. E. Nuccio (Aug 30 2024 at 09:57):
So, going back to Expr
, IsForAll
recovers if something is a PiType and IsLambda
recovers if it is a lambda-term (inside some PiType)?
Patrick Massot (Aug 30 2024 at 09:59):
Those functions are so simple that the answer cannot be simpler than the definitions.
Patrick Massot (Aug 30 2024 at 09:59):
/-- Return `true` if the given expression is a forall-expression aka (dependent) arrow. -/
def isForall : Expr → Bool
| forallE .. => true
| _ => false
/-- Return `true` if the given expression is a lambda abstraction aka anonymous function. -/
def isLambda : Expr → Bool
| lam .. => true
| _ => false
Filippo A. E. Nuccio (Aug 30 2024 at 09:59):
Patrick Massot said:
Those functions are so simple that the answer cannot be simpler than the definitions.
Well, this answer is so simple that it cannot be more informative than the question :smile:
Patrick Massot (Aug 30 2024 at 10:00):
The informative part was being copy-pasted.
Patrick Massot (Aug 30 2024 at 10:01):
I should have sent only one message, sorry.
Patrick Massot (Aug 30 2024 at 10:03):
This is really the analogue of
def Nat.isZero : Nat → Bool
| .zero => true
| .succ _ => false
#eval Nat.isZero 0
#eval Nat.isZero 5
Filippo A. E. Nuccio (Aug 30 2024 at 10:03):
No problem, I just meant to say that I read those definitions, still I was a bit struggling. Perhaps an example would do, it is often helpful. Do we agree that IsForall
should return true
if it encounters
(n : Nat) -> Fin n
while IsLambda
should return true
if it encounters
fun n : Nat => (n-1) : Fin n
?
Johan Commelin (Aug 30 2024 at 11:13):
Did you mean
(n : Nat) -> Fin n
in your first example? (arrow instead of comma)
Filippo A. E. Nuccio (Aug 30 2024 at 11:34):
I did (I am still fighting with the "new" notation for PiTypes: I would write Π(n : Nat) Fin n
)
Johan Commelin (Aug 30 2024 at 11:40):
I think you can use the logical forall symbol, if you like it better
Johan Commelin (Aug 30 2024 at 11:40):
Anyway, if you meant the arrow instead of the comma, then the answer to your question is "yes"
Filippo A. E. Nuccio (Aug 30 2024 at 11:41):
Thanks! I realised that most of my trouble came from the inconscious (and wrong, of course) intuition that "Expressions" found in the context could not be types...
Patrick Massot (Aug 30 2024 at 12:39):
@Filippo A. E. Nuccio , you can play with
import Mathlib
open Lean Elab Command
elab "#descr" e:term : command => do
let E ← liftTermElabM <| Term.elabTerm e none
logInfo (repr E)
#descr (n : Nat) → Fin n
#descr fun n : Nat ↦ (Fin.last n)
Filippo A. E. Nuccio (Aug 30 2024 at 12:53):
Oh, that's nice! Thanks @Patrick Massot
Last updated: May 02 2025 at 03:31 UTC