I'm trying to write a gallina function that quotes typing judgments. (I hope this is not a doomed endeavor.) Right now I'm running into the problem that the type_Const
case takes an argument of type consistent_instance_ext
which after unfolding consistent_instance_ext
, consistent_instance
, valid_constraints
, valid_constraints0
, and satisfies
holds an argument of type forall v : valuation, ConstraintSet.For_all (satisfies0 v) Σ -> ConstraintSet.For_all (satisfies0 v) (subst_instance_cstrs u c.2)
.
This is a problem, because I cannot quote lambdas in general. The valuation
type is not finite (it holds string -> positive
and nat -> nat
), and so I cannot enumerate it. While ConstraintSet
s are finite and hence ConstraintSet.For_all
poses no problem in quotation, I cannot invert satisfies0
to construct a finite list of valuation
s that satisfy a given universe constraint. Thus, unlike for wf_universe
, it's not obvious that valid_constraints
is decidable. I see that there's a completeness proof relating valid_constraints
to check_constraints
, but it seems to require manufacturing a bunch of other information which it's not clear to me is implied by valid_constraints
, namely I have to manufacture G : universes_graph
and uctx : ContextSet.t
such that global_uctx_invariants uctx
, consistent uctx.2
, is_graph_of_uctx G uctx
, global_uctx_invariants (uctx.1, ctrs)
.
Is there any hope of quoting valid_constraints
? If not, could I convince the MetaCoq devs to base the inductive typing judgments on some more model-independent notion of valid constraints, which does not even in theory depend on what sorts of nat -> nat
functions can exist beyond the syntactic ones?
I guess there's only a finite amount of information from the valuation used for any given constraint set, so I should be able to just enumerate that information...
I'm not sure you will convince us to change it back to graphs. Our goal is to have the specification as natural as possible and mostly implementation independent. That said, you should probably be fine if you can use the fact that the two are equivalent right? I'll let someone who worked on it tell you where to find such proof (assuming it was proven).
Yes, I'm fine as long as the two are actually equivalent. (I believe check_constraints_spec
and check_constraints_complete
prove equivalence with a version based on universes_graph
, which I guess is a starting place...)
But as I said that version requires a bunch of extra data that I'm not sure how to generate
It seems like I need some function ConstraintSet.t -> ContextSet.t
or ConstraintSet.t -> LevelSet.t
? (Do you know of some such function?)
And now I'm running into a similar trouble with eq_levelalg
, where even the graph-version doesn't seem to be obviously decidable?
Indeed, as Theo said, we definitely do not want typing to be obviously decidable, but rather to be as "natural" as possible. I guess we could have an intermediate presentation, that while still presented as a judgement is somehow model-independent as you say (and probably closer to the implementation). This is morally what bidirectional typing does, but internally it still uses the same definitions as typing, for instance for constraints.
But since for the type-checker we need to show that everything is decidable, you should have all you need in the development. I would probably try and work from the type-checker to locate the decision procedures corresponding to the judgments you have trouble with, and replace those with the decision procedure outputing true
.
In the typechecker it seems that you only show things are decidable under well-formedness assumptions or something? I'm having trouble finding deciders for consistent
/ gc_consistent
, for valid_constraints
(in particular I'm not sure how to satisfy the preconditions of check_constraints_spec
/ check_constraints_complete
), eq_levelalg
/ gc_eq_levelalg
, and leq_levelalg_n
/ gc_leq_levelalg_n
I think it often happens that the decider is sound/complete under some additional hypothesis, yes
But these should typically hold if the decider is called in a valid environment
I think the place to look at for this is probably again in SafeChecker, where to call these deciders and use the fact that they indeed decide the right thing we must show these preconditions are satisfied.
The issue is that my work is probably an order of magnitude simpler if I can decide the predicate in all cases, not just under additional assumptions.
I know the issue, I faced it too when wanting to write the completeness proof… But I think in the end most statements are some kind of "bundles", and usually the first part of the bundle gives you the precondition for the decider of the second to be correct. Isn't this enough for you?
It's the other way around for me. If I need to satisfy the preconditions of the checker, then I must map bundles to bundles wholesale, because the second part of my input bundle is required to satisfy the preconditions for using the checker to generate the first part of my output bundle.
And this makes things more painful, because it means that I can no longer work with untyped syntax at all in my development, but instead have to phrase everything in terms of well-typed syntax
And there are some things that I want to try out that I don't know how to do when using only syntax that is indexed on its type, so I'm inclined to just write the decider myself rather than bundle...
I'm not sure I understand what your issue is. But I agree that staying away from intrinsically well-typed syntax sound wise
I'm trying to write a Gallina function quote : Ast.term -> Ast.term
such that quote x
is more-or-less equivalent to <% x %>
when x
is closed / in the empty context.
Separately, I want to show that if Σ
is rich enough and Γ
is well-formed, then Σ;;; Γ |- quote x : <% Ast.term %>
in all cases, independent of x
(even if x
is not sufficiently well-formed, that is)
And then I also want to have quote_typing : (Σ;;; Γ |- t : T) -> Ast.term
, and a similar proof about the typing of quote_typing pf
.
(This is all so that I can formalize Löb's theorem about Coq)
And what you are saying is that you want the least amount possible of dependencies between those definitions?
Yes, I don't want to have to assume (Σ;;; Γ |- t : T)
to write quote : Ast.term -> Ast.term
. Because my prior experience is that inconsistency about abstraction barriers (in this case, about whether I'm operating on typed or untyped syntax) is begging for pain.
Yup, that I agree with
I'm not sure about this, but I think that the current positivity criterion is too weak to be able to quote Ast.term
or typing
. From what I understand, nested inductive types are not supported by it yet, and both term and typing use list of terms/typing judgments in their definitions.
Which would mean you cannot have a well-formed environment (in the sense of MetaCoq) containing either one of them :/
This is really unfortunate :-(
(This does not mean I cannot quote them, though, just that I cannot prove that the quotation is well-typed)
(But this is all the more reason to separate quotation from well-typedness)
Indeed!
Although I do not think this is because of "deep" difficulties, just that inductive types are already extremely technical, and that nested ones are even worse
Nasty inductives are a recurring topic of conversation in Nantes, so the addition of nested ones to MetaCoq is bound to happen (especially if we have a good reason to do so) but nobody is working on it just yet. So I don't know how long it will take to have them :/
I don't think it'll be a blocker for my use-case unless / until I'm ready to write a paper; I'm planning on parameterizing everything over "a global env strong enough to hold quoted versions of Ast.term, etc", until the very very end where I'll instantiate it with some particular global env. In the meantime it's okay if my theorems are technically vacuous because no well-formed global env can hold quoted versions of Ast.term
I see, then indeed you should be fine. Maybe this will even give someone a strong enough push to tackle these!
Thoughts on replacing valuation
functions with association lists, essentially forcing universe assignments to be finite?
I guess you could simply use finite-support functions like mathcomp's finfuns
I've managed to bypass this issue using deciders, eg at https://github.com/JasonGross/metacoq-lob/blob/4222900653a338b2870e933d1b6a5da7a94a2eb7/theories/Template/Decidable/Universes.v#L218, there's only one I can't figure out (I'll bump that thread)
Jason Gross has marked this topic as resolved.
Last updated: May 31 2023 at 04:01 UTC