-
Notifications
You must be signed in to change notification settings - Fork 700
made Vector.nth substructural #16731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| fix nth_fix {n : nat} (v : t A n) {struct v} : Fin.t n -> A := | ||
| match v with | ||
| | nil _ => fun p => False_rect A (Fin.case0 _ p) | ||
| | cons _ x m v' => fun p => | ||
| match p in (Fin.t m') return (m' = S m -> A) with | ||
| | Fin.F1 => fun _ => x | ||
| | Fin.FS p' => fun E => nth_fix v' (eq_rect _ _ p' m (f_equal Nat.pred E)) | ||
| end eq_refl | ||
| end. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternative definition without equalities:
| fix nth_fix {n : nat} (v : t A n) {struct v} : Fin.t n -> A := | |
| match v with | |
| | nil _ => fun p => False_rect A (Fin.case0 _ p) | |
| | cons _ x m v' => fun p => | |
| match p in (Fin.t m') return (m' = S m -> A) with | |
| | Fin.F1 => fun _ => x | |
| | Fin.FS p' => fun E => nth_fix v' (eq_rect _ _ p' m (f_equal Nat.pred E)) | |
| end eq_refl | |
| end. | |
| fix nth_fix {n : nat} (v : t A n) {struct v} : Fin.t n -> A := | |
| match v with | |
| | nil _ => fun p => False_rect A (Fin.case0 _ p) | |
| | cons _ x m v' => fun p => | |
| match p with | |
| | Fin.F1 => fun _ => x | |
| | Fin.FS p => fun go => go p | |
| end (nth_fix v') | |
| end. |
I suspect it is correct but I haven't actually tested it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, no. Your proposed version was the first one I wrote. However, the test mentioned in the intro fails with
Recursive definition of test is ill-formed.
In environment
test : container -> unit
c : container
v : t container 2
Recursive call to test has principal argument equal to
"nth v (Fin.FS Fin.F1)" instead of "v".
Recursive definition is:
"fun c : container =>
match c with
| container_v v => test (nth v (Fin.FS Fin.F1))
| container_0 => tt
end".
It would be interesting to know why this is the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what I am doing wrong but for me both ways of writing nth fail the test case. This is on 8.16.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, I was using Vector.nth instead of my local nth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what I am doing wrong but for me both ways of writing
nthfail the test case. This is on 8.16.
Exactly the following works (for me) on 8.16:
Require Vector.
Definition my_nth {A} :=
fix nth_fix {n : nat} (v : Vector.t A n) {struct v} : Fin.t n -> A :=
match v with
| Vector.nil _ => fun p => False_rect A (Fin.case0 _ p)
| Vector.cons _ x m v' => fun p =>
match p in (Fin.t m') return (m' = S m -> A) with
| Fin.F1 => fun _ => x
| Fin.FS p' => fun E => nth_fix v' (eq_rect _ _ p' m (f_equal Nat.pred E))
end eq_refl
end.
Inductive container : Type :=
| container_v : Vector.t container 2 -> container
| container_0 : container.
Fixpoint test (c : container) : unit :=
match c with
| container_0 => tt
| container_v v => test (my_nth v (Fin.FS Fin.F1))
end.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Janno More precisely, the return type in not an inductive type but the result of a match
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However in either case I don't know if extraction will eliminate the commutative cuts, whereas with a cut on equality it should get erased.
The cut gets erased at extraction. I am pretty sure ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean properly extracted with the match p in Fin.t m return Vector.t _ (pred m) -> _ with version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cutting with just th vector extracts fine, but cutting with nth_fix v' extracts to
let rec nth _ v p =
match v with
| Nil -> assert false (* absurd case *)
| Cons (x, m, v') -> let x0 = nth m v' in (match p with
| F1 _ -> x
| FS (_, p') -> x0 p')which may or may not compile as efficiently
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let us see what the CI has to say about @SkySkimmer's and @DmxLarchey's suggestions
|
@coqbot run full ci |
|
I added a changelog entry, and a case to the test-suite to check for strict subterms. |
added test-case
575807e to
334cfab
Compare
andres-erbsen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know Vector that well, but the reasoning for this change makes sense to me. @coq/stdlib-maintainers please feel free to weigh in; if nothing is said in a couple of days I intend to merge.
|
@coqbot run full ci because I cannot figure out how to view the previous results |
It seems the commit that got full CI was 6ae4735 (pipeline https://gitlab.com/coq/coq/-/pipelines/678316994) |
|
@coqbot merge now |
|
@andres-erbsen: You cannot merge this PR because:
|
|
@coqbot merge now |
The documentation of
Vector.nthstates "Computational behavior of this function should be the same as ocaml function."However, the current implementation is not structural in the vector, but in the position.
This is different from OCaml: https://github.com/ocaml/ocaml/blob/83762af41d5a302ed793d6fb4bbe18a3447e18b1/stdlib/list.ml#L37.
The present PR makes
Vector.nthfollow OCamlnthand return a strict subterm of the input vector.For example, this allows recursion on
nth(which otherwise complains about a non-decreasing argument):Fixes / closes #16738