0

So while learning Coq I did a simple example with the game paper, scissor, rock. I defined a data type.

Inductive PSR : Set := paper | scissor | rock.

And three functions:

Definition me (elem: PSR) : PSR := elem.

Definition beats (elem: PSR) : PSR :=
 match elem with
  | paper => scissor
  | rock => paper
  | scissor => rock
 end.

Definition beatenBy (elem: PSR) : PSR :=
 match elem with
  | paper => rock
  | rock => scissor
  | scissor => paper
 end.

I also define composition (although this should be somewhere in the standard library)

Definition compose {A B C} (g : B -> C) (f : A -> B) : (A -> C) :=
  fun x : A => g (f x).

I implement the class monoid as described here

Class Monoid {A : Type} (dot : A -> A -> A) (unit : A) : Type := {
 dot_assoc : forall x y z:A,
  dot x (dot y z)= dot (dot x y) z;
 unit_left : forall x,
  dot unit x = x;
 unit_right : forall x,
  dot x unit = x 
}.

I finally managed to prove that you can PSR forms a monoid under compose as + and me as 1

Instance MSPR : Monoid compose me.
 split.
 intros. reflexivity.
 intros. reflexivity.
 intros. reflexivity.
 Qed.

Question

Why does the proof of Instance MSPR : Monoid compose me. work just by applying intros and reflexivity? Honestly, I did split and intros knowing what I was doing, but after intros I got something like

3 subgoal
x : PSR -> PSR
y : PSR -> PSR
z : PSR -> PSR
______________________________________(1/3)
compose x (compose y z) = compose (compose x y) z

tried apply compose. but it didn't work. Magically reflexivity. solved it but I don't know why.

Side Note

This worked wonderfully, if you define power like this

Fixpoint power {A dot one} {M : @Monoid A dot one}(a:A)(n:nat) :=
 match n with 0 % nat => one
  | S p => dot a (power a p)
 end.

then Compute (power beats 2) paper. yields

= rock
     : PSR

which did this beats (beats paper) = beats scissor = rock !!!

Cristian Garcia
  • 9,630
  • 6
  • 54
  • 75
  • `me` is the identity function; what you've proven is that the function space `PSR -> PSR` is a monoid with `compose` as binary op and `id` as unit. It is true of any set of endomorphisms. Your proofs work by reflexivity because function composition is associative (try using `unfold compose` and see what happens). – gallais Jun 26 '14 at 08:08

2 Answers2

2

The reflexivity principle in Coq is actually more powerful than than mere syntactic equality, as one could expect. Roughly speaking, Coq considers to be equal any two things that can be simplified to the same value. Simplification here is taken in a slightly more restrictive sense than in algebra, for instance, where one is allowed to manipulate formulas according to algebraic laws. Instead, Coq comes with a fixed set of computation rules that describe how programs compute. In your example, simplifying the expression would yield

compose x (fun a => y (z a)) = compose (fun a => x (y a)) z
fun a => x (y (z a)) = fun a => x (y (z a))

Where "fun" is Coq's notation for an anonymous function, I.e. a function without a name. Since these two things are equal, reflexivity suffices. The same idea apllies to the other goals.

Arthur Azevedo De Amorim
  • 23,012
  • 3
  • 33
  • 39
1

After the intros, you can do unfold compose to ask Coq to only unfold compose definition, you will see that both side of the equality are syntactically the same, thus reflexivity manages to solve your goal (reflexivity can "see" through definitions).

The question remains: why are they the same: See Arthur's answer for that ;)

V.

Vinz
  • 5,997
  • 1
  • 31
  • 52