Set the syntax to be Coq in the post
This commit is contained in:
parent
fce8e75dde
commit
fe0437eabf

@ 14,7 +14,7 @@ Of course, my definition led to only having palindromes of even length. In order


* A list with a single value is a palindrome.




This translates readily into Coq:


```


```Coq


Inductive palindrome { X : Type } : list X > Prop :=


 palindrome_nil : palindrome []


 palindrome_x : forall (x : X), palindrome [x]



@ 24,7 +24,7 @@ Inductive palindrome { X : Type } : list X > Prop :=




### The first direction


It’s nearly trivial to show that a palindrome is its own inverse:


```


```Coq


Theorem pal_rev { X : Type } : forall (l : list X), palindrome l > l = rev l.


Proof.


intros l H.



@ 49,7 +49,7 @@ Then, the proposition holds for all values of that type. This can be easily seen




As I was working with my definition of a palindrome, it dawned on me that generalizing a single variable in that definition would create another inductive definition of a list. If we change the inductive rule in the palindrome definition from saying “surrounding another palindrome with x on both sides” to “surrounding another list with some x on one side and some y on the other”, we can effectively construct any list. We can then state a different structural induction principle:




```


```Coq


Theorem alt_induction { X : Type } : forall (P : list X > Prop),


P [] >


(forall (x : X), P [x]) >



@ 61,7 +61,7 @@ But how would we go about proving this? If we try to just use induction on `ln`,




#### Proving Equivalence


What’s missing is that there’s nothing as yet stating that appending values to the back and the front of another list is an equivalent way to appending a value only to the front of a list. We need to state this explicitly; but how? I decided that the easiest way would be by defining a new inductive property, `list_alt` which holds for all lists that can be constructed by adding things to the back and the front. Then, we can show that it holds for all lists, and, therefore, that any list can be constructed this way. I defined the property as such:


```


```Coq


Inductive list_alt { X : Type } : list X > Prop :=


 list_alt_base : list_alt []


 list_alt_x : forall (x : X), list_alt [x]



@ 70,7 +70,7 @@ Inductive list_alt { X : Type } : list X > Prop :=




Then, to prove it true for all lists, I first showed what is effectively the inductive hypothesis of a proof by induction on the structure of a list:




```


```Coq


Theorem list_alt_cons { X : Type } : forall (x : X) (l : list X),


list_alt l > list_alt (x::l).


Proof.



@ 91,7 +91,7 @@ Qed.


```




Next, the actual proof of equivalence simply used the previous theorem:


```


```Coq


Theorem list_alt_correct { X : Type } : forall (l : list X), list_alt l.


Proof.


induction l.



@ 102,7 +102,7 @@ Qed.




Finally, we can prove our custom principle of induction (by induction (!) on the property list_alt, which we now know holds for all lists):




```


```Coq


Theorem alt_induction { X : Type } : forall (P : list X > Prop),


P [] >


(forall (x : X), P [x]) >



@ 118,7 +118,7 @@ Proof.




Finally, the palindrome proof can simply use this principle. Coq turns out to have a mechanism to use a custom induction principle via `induction … using …`:




```


```Coq


Theorem rev_pal' { X : Type } : forall (l : list X), l = rev l > palindrome l.


Proof.


intros l H. induction l using alt_induction.




Loading…
Reference in New Issue