In Agda, it's quite easy to prove that if a relation R is transitive then we can define pointwise transitivity on lists:
open import Data.List
Rel : Set → Set₁
Rel A = A → A → Set
private
variable
A : Set
R : A → A → Set
data Pointwise (R : Rel A) : Rel (List A) where
p-nil : Pointwise R [] []
p-cons : ∀ {x y xs ys} → R x y → Pointwise R xs ys → Pointwise R (x ∷ xs) (y ∷ ys)
Transitive : Rel A → Set
Transitive R = ∀ {x y z} → R x y → R y z → R x z
TransitivePointwise : Transitive R → Transitive (Pointwise R)
TransitivePointwise t p-nil p-nil = p-nil
TransitivePointwise t (p-cons Rxy ps) (p-cons Ryz qs) = p-cons (t Rxy Ryz) (TransitivePointwise t ps qs)
However, in Coq, when trying to achieve the same:
Inductive pointwise {A} (R : A -> A -> Prop) : list A -> list A -> Prop :=
| p_nil : pointwise R nil nil
| p_cons : forall {x y} {xs ys}, R x y -> pointwise R xs ys -> pointwise R (x :: xs) (y :: ys).
Theorem transitive_pointwise : forall {A} R, transitive A R -> transitive (list A) (pointwise R).
Proof.
unfold transitive.
intros.
induction H0.
- assumption.
-
Qed.
I get stuck because I need to recurse on H0 : pointwise R x y and H1 : pointwise R y z at the same time. I've tried using refine with a fixpoint, but in that case, Coq tells me that the fixpoint is ill-formed. It would also be nice to know why when doing destruct H0, H1, Coq gives me four cases, while Agda only gives two.
If you do an induction over lists (instead of over an hypothesis of type
pointwise ? ?) and a few calls toinversion, it works.(Edited)
Ups! You can also induct over
Hxy: pointwise x y: