If I have some notation that binds an identifier, is there any way to turn that identifier into a string on the right hand side? I acknowledge this is stretching things quite far but it would be nice to annotate a term representing a variable with a user-provided name that way.
@Pierre-Marie Pédrot does ltac2 have an API to print a term? (applied to a variable would produce its string, and with tac-in-terms could do what @Shea Levy asks for). I have one in Elpi, but it would be silly to pull it in jut for this.
I'd also like a way to do this, de Bruijn indexes are very hard to read.
Enrico Tassi said:
Pierre-Marie Pédrot does ltac2 have an API to print a term? (applied to a variable would produce its string, and with tac-in-terms could do what Shea Levy asks for). I have one in Elpi, but it would be silly to pull it in jut for this.
Is "tac-in-terms" documented anywhere? From the name I can guess what it means but not sure how I'd actually use it.
People have been messing with the Ltac1 / Ltac2 FFI to do this indeed
ltac:( tactic )
is equivalent to the (proof) term generated by tactic. ltac:(exact t)
is like t
.
So can you sketch the code for us? ltac2:( print $t )
or something?
For the mentioned use-case, I think that merely matching the term using Constr.Unsafe.kind
is going to give you the term structure from which you can extract the ident
Depending on what you want to do with this exactly the remaining is quite different
Pierre-Marie Pédrot said:
Depending on what you want to do with this exactly the remaining is quite different
I'd like to create a term of type Strings.String.string
OK so I see ident_to_string
, I'm not sure how to get a kind
to match on given some term in context, and then I'm not sure how to lift that ltac2 string into a gallina string
I suppose for the second one I can write a tactic to construct the string directly if all else fails. So just need to figure out how to match
Ooof if there's no internal way to do it though it's going to be a 256-branch case :joy:
Oh wait I'm sure there's an of_int or whatever in the coq stdlib for chars. Not so bad.
So there is a library that does that already, let me find it.
https://gitlab.mpi-sws.org/iris/string-ident is probably a good start
They have to go through hoops because they want to reuse the ident as an Ltac1 ident, but just getting a Coq string should be easier
Hm, actually what you want seems to be the other way around
Looks like that's going in the opposite direction?
Yeah, essentially you'll have to write an Ltac2 function from Ltac2 string to constr that builds the corresponding Gallina string
Simple but tedious.
Yeah, I see how to go from a string to a sequence of chars and a char to an int and I'm sure once there I can get back into a coq string, just trying to see how to get the kind
out of the variable in context
I am afraid Ltac2 is not very much battery included...
So it'd be something like ltac2:(mytac $x)
where mytac : constr -> constr
and x
is the constr variable you want to match on
Ltac2 mytac x := match Constr.Unsafe.kind x with Var => blah | _ => fail end
Ah OK I missed that the constr
type is what I want. So I assume I can get a constr
by somehow quoting my variable, and then use constr_kind
, and go from there?
The last question, which I will figure out by trying, is if quoting the variable on the RHS of a notation gives me the ident I used in defining the notation or the one I used when I used it :sweat_smile:
depends exactly where you put that tactic
Notations bind Ltac2 variables as preterms, i.e. untyped syntactic expressions
Have to pause for the day but I'm going to try something like Notation "'foo' x" := ltac2(do_something_with 'x) (x ident)
And hope that foo y
reduces to ltac2(do_something_with 'y)
, not ltac2(do_something_with 'x)
Hm, I don't know how term notations handle the "x ident" part
This might not get passed to Ltac2
or maybe yes, I actually don't know very well
Notations are a fairly hairy component of Coq
But yes, that's the general guideline. If you have trouble do not hesitate to ask back here
Thank you!
(Were it not for the "x ident" you would indeed get the AST of the notation argument; giving a bound variable doesn't make much sense)
Hmm I guess worst case I could bind x in a lambda (of type tt or whatever) and then ltac2 inside that, right?
This should work indeed.
Last updated: Oct 12 2024 at 11:01 UTC