Make more progress on Coq post.
This commit is contained in:
parent
60eb50737d
commit
6f92a50c83

@ 274,3 +274,84 @@ and will become \\(v  \\{c\\}\\).




If all of these conditions are met, our program, starting at \\((c, a, v)\\), will terminate in the state \\((c'', a'', v'')\\). This third rule completes our semantics; a program being executed will keep running instructions using the third rule, until it finally


hits an invalid program counter (terminating with the first rule) or gets to the end of the program (terminating with the second rule).




#### Aside: Vectors and Finite \\(\mathbb{N}\\)


We'll be getting to the Coq implementation of our semantics soon, but before we do:


what type should \\(c\\) be? It's entirely possible for an instruction like \\(\\texttt{jmp} \\; 10000\\)


to throw our program counter way before the first instruction of our program, so at first, it seems


as though we should use an integer. But the prompt doesn't even specify what should happen in this


case  it only says an instruction shouldn't be run twice. The "valid set", although it may help resolve


this debate, is our invention, and isn't part of the original specification.




There is, however, something we can infer from this problem. Since the problem of jumping "too far behind" or


"too far ahead" is never mentioned, we can assume that _all jumps will lead either to a valid instruction,


or right to the end of a program_. This means that \\(c\\) is a natural number, with




{{< latex >}}


0 \leq c \leq \text{length}(p)


{{< /latex >}}




In a language like Coq, it's possible to represent such a number. Since we've gotten familliar with


inference rules, let's present two rules that define such a number:




{{< latex >}}


\frac


{n \in \mathbb{N}^+}


{Z : \text{Fin} \; n}


\quad


\frac


{f : \text{Fin} \; n}


{S f : \text{Fin} \; (n+1)}


{{< /latex >}}




This is a variation of the [Peano encoding](https://wiki.haskell.org/Peano_numbers) of natural numbers.


It reads as follows: zero (\\(Z\\)) is a finite natural number less than any positive natural number \\(n\\). Then, if a finite natural number


\\(f\\) is less than \\(n\\), then adding one to that number (using the successor function \\(S\\))


will create a natural number less than \\(n+1\\). We encode this in Coq as follows


([originally from here](https://coq.inria.fr/library/Coq.Vectors.Fin.html#t)):




```Coq


Inductive t : nat > Set :=


 F1 : forall {n}, t (S n)


 FS : forall {n}, t n > t (S n).


```




The `F1` constructor here is equivalent to our \\(Z\\), and `FS` is equivalent to our \\(S\\).


To represent positive natural numbers \\(\\mathbb{N}^+\\), we simply take a regular natural


number from \\(\mathbb{N}\\) and find its successor using `S` (simply adding 1). Again, we have


to explicitly use `forall` in our type signatures.




We can use a similar technique to represent a list with a known number of elements, known


in the Idris and Coq world as a vector. Again, we only need two inference rules to define such


a vector:




{{< latex >}}


\frac


{t : \text{Type}}


{[] : \text{Vec} \; t \; 0}


\quad


\frac


{x : \text{t} \quad \textit{xs} : \text{Vec} \; t \; n}


{(x::\textit{xs}) : \text{Vec} \; t \; (n+1)}


{{< /latex >}}




These rules read: the empty list \\([]\\) is zerolength vector of any type \\(t\\). Then,


if we take an element \\(x\\) of type \\(t\\), and an \\(n\\)long vector \\(\textit{xs}\\) of \\(t\\),


then we can prepend \\(x\\) to \\(\textit{xs}\\) and get an \\((n+1)\\)long vector of \\(t\\).


In Coq, we write this as follows ([originally from here](https://coq.inria.fr/library/Coq.Vectors.VectorDef.html#t)):




```Coq


Inductive t A : nat > Type :=


 nil : t A 0


 cons : forall (h:A) (n:nat), t A n > t A (S n).


```




The `nil` constructor represents the empty list \\([]\\), and `cons` represents


the operation of prepending an element (called `h` in the code in \\(x\\) in our inference rules)


to another vector of length \\(n\\), which is remains unnamed in the code but is called \\(\\textit{xs}\\) in our rules.




These two definitions work together quite well. For instance, suppose we have a vector of length \\(n\\).


If we were to access its elements by indices starting at 0, we'd be allowed to access indices 0 through \\(n1\\).


These are precisely the values of the finite natural numbers less than \\(n\\), \\(\\text{Fin} \\; n \\).


Thus, given such an index \\(\\text{Fin} \\; n\\) and a vector \\(\\text{Vec} \\; t \\; n\\), we are guaranteed


to be able to retrieve the element at the given index! In our code, we will not have to worry about bounds checking.




Loading…
Reference in New Issue
Block a user