Coq how to pretty-print a term constructed using tactics?
I'm new to Coq and am doing some exercises to get more familiar with it. My understanding is that proving a proposition in Coq "really" is writing down a type in Gallina and then showing that it's inhabited using tactics to combine terms together in deterministic ways. I'm wondering if there's a way to get a pretty-printed representation of the actual term, with all the tactics removed. In the example below, an anonymous term of type plus_comm (x y : N) : plus x y = plus y x is ultimately produced... I think. What should I do if I want to look at it? In a certain sense, I'm curious what the tactics "desugar" to. Here's the code in question, lifted essentially verbatim from a tutorial on YouTube https://www.youtube.com/watch?v=OaIn7g8BAIc. Inductive N : Type := | O : N | S : N -> N . Fixpoint plus (x y : N) : N := match x with | O => y | S x' => S (plus x' y) end. Lemma plus_0 (x : N) : plus x O = x. Proof. induction x. - simpl. reflexivity. - simpl. rewrite IHx. reflexivity. Qed. Lemma plus_S (x y : N) : plus x (S y) = S(plus x y). Proof. induction x. - simpl. reflexivity. - simpl. rewrite IHx. reflexivity. Qed. Lemma plus_comm (x y : N) : plus x y = plus y x. Proof. induction x. - simpl. rewrite plus_0. reflexivity. - simpl. rewrite IHx. rewrite plus_S. reflexivity. Qed.
First of all, plus_comm is not a part of the type. You get a term named plus_comm of type forall x y : N, plus x y = plus y x. You can check it using the following command Check plus_comm. So, an alternative way of defining the plus_comm lemma is Lemma plus_comm : forall x y : N, plus x y = plus y x. As a side note: in this case you'll need to add intros x y. (or just intros.) after the Proof. part. Tactics (and the means to glue them together) are a metalanguage called Ltac, because they are used to produce terms of another language, called Gallina, which is the specification language of Coq. For example, forall x y : N, plus x y = plus y x is an instance of Gallina sentence as well as the body of the plus function. To obtain the term attached to plus_comm use the Print command: Print plus_comm. plus_comm = fun x y : N => N_ind (fun x0 : N => plus x0 y = plus y x0) (eq_ind_r (fun n : N => y = n) eq_refl (plus_0 y)) (fun (x0 : N) (IHx : plus x0 y = plus y x0) => eq_ind_r (fun n : N => S n = plus y (S x0)) (eq_ind_r (fun n : N => S (plus y x0) = n) eq_refl (plus_S y x0)) IHx) x : forall x y : N, plus x y = plus y x It is not an easy read, but with some experience you'll be able to understand it. Incidentally, here is how we could have proved the lemma not using tactics: Definition plus_comm : forall x y : N, plus x y = plus y x := fix IH (x y : N) := match x return plus x y = plus y x with | O => eq_sym (plus_0 y) | S x => eq_ind _ (fun p => S p = plus y (S x)) (eq_sym (plus_S y x)) _ (eq_sym (IH x y)) end. To explain a few things: fix is the means of defining recursive functions, eq_sym is used to change x = y into y = x, and eq_ind corresponds to the rewrite tactic.
How to “flip” an equality proposition in Coq?
Redundant clause in match
Dependent type list concatenation in Coq
How to access the elements of a record in coq
Type hierarchy definition in Coq or Agda
Applying tactics to local subgoals of a semicolon chain in Coq
How to build an inductive type for cobordisms using Coq?
Coq: “dependent induction” inside Ltac
Omitting forall in Coq
Why can't inversion be used on a universally qualified hypothesis in Coq?
How to duplicate a hypothesis in Coq?
Why Coq doesn't allow inversion, destruct, etc. when the goal is a Type?
Working with semirings in Coq
Eliminating cases with propositions in Coq
Using sets as hyphotesis and goal in COQ
What does `omega` really do here?