Let me teach you one strange trick. This may not be the answer to all your problems, but it can help, at least conceptually.
Let the addition for natural numbers be realized, the latter is given
Inductive nat : Set := | zero : nat | suc : nat -> nat.
You can try writing an add-on on tactics, but it happens.
Theorem plus' : nat -> nat -> nat. Proof. induction 1. plus' < 2 subgoals ============================ nat -> nat subgoal 2 is: nat -> nat
you cannot see what you are doing.
The trick is to take a closer look at what you are doing. We can introduce a gratis dependent type, nat cloning.
Inductive PLUS (xy : nat) : Set := | defPLUS : nat -> PLUS x y.
The idea is that PLUS xy is a type of "method for calculating PLUS xy ." We need a projection that allows us to extract the result of such a calculation.
Theorem usePLUS : forall xy, PLUS xy -> nat. Proof. induction 1. exact n. Defined.
Now we are ready to program by proving.
Theorem mkPLUS : forall xy, PLUS x y. Proof. mkPLUS < 1 subgoal
The conclusion of the goal shows us our current left side and context. The analogue of Cc Cc in Agda is ...
induction x. mkPLUS < 2 subgoals ============================ forall y : nat, PLUS zero y subgoal 2 is: forall y : nat, PLUS (suc x) y
And you can see that he laid out the case! Let me knock down the base case.
intros y. exact (defPLUS zero yy).
Calling the PLUS constructor is like writing an equation. Imagine the = sign in front of its third argument. For the step case, we need to make a recursive call.
intros y. eapply (fun h => (defPLUS (suc x) y (suc (usePLUS xyh)))).
To make a recursive call, we call usePLUS with the necessary arguments here x and y , but we abstract out the third argument, which explains how to actually compute it. We only have this sub-goal left, the completion check is effective.
mkPLUS < 1 subgoal x : nat IHx : forall y : nat, PLUS xy y : nat
And now, instead of using Coq's security check, you use ...
auto.
... which verifies that inductive hypotheses embrace a recursive call. we
Defined.
We have a worker, but we need a cover.
Theorem plus : nat -> nat -> nat. Proof. intros x y. exact (usePLUS xy (mkPLUS xy)). Defined.
And we are ready to go.
Eval compute in (plus (suc (suc zero)) (suc (suc zero))). Coq < = suc (suc (suc (suc zero))) : nat
You have an interactive building tool. You can play the game to show you the relevant details of the problem you are solving, making the types more informative. Received proof script ...
Theorem mkPLUS : forall xy, PLUS x y. Proof. induction x. intros y. exact (defPLUS zero yy). intros y. eapply (fun h => (defPLUS (suc x) y (suc (usePLUS xyh)))). auto. Defined.
... clearly about the program he creates. You can see this defining addition.
If you automate this setting to build a program, then the layer on the interface showing your program that you are building and the key problem is simplifying tactics, you get a funny little programming language called Epigram 1.