(Update: I start on these, and then someone else gives an answer after I've worked quite a bit up, so I go ahead and put up what I've done.
What I was wanting to know came in the other answer, which is the use of term ?thesis
in the proof, to help match up the error message with where the problem is.
Maybe my answer here adds a little context for the other answer.)
Below, I use !!
for meta-logic all
, instead of \<And>
.
You've entered into to the mysterious meta-logic-vs-object-logic-zone. A little understanding makes things a lot less mysterious.
Below, I give you a way to show the use of the hidden Trueprop
function, which will take some of the mystery away.
- explain a little about the 3 Pure meta-logic operators, and their relationship oto the HOL object-logic,
- give 3 different forms of your
lemma
, starting with yours,
- where the
show ?thesis
of the third form is finally acceptable to the proof engine.
I don't completely sort things out here. For myself, many times it's not important that I completely understand everything, but it is important that I'm not totally in the dark about the types of the meta-logic and object-logic functions that are being used, which is at the heart of all this.
HOL bool, Pure prop, and Trueprop :: (bool => prop), to tie HOL into Pure
The notation for the Trueprop
function is normally hidden. You can define notation to see where it's applied in the output panel. I define notation
here with some declares:
notation (output) Trueprop ("_:@T" [1000] 999)
declare[[show_brackets=false, show_types, show_sorts=false, show_consts]]
Here's the type of Trueprop
:
term "Trueprop :: bool => prop"
In your lemma
below, because you're using -->
instead of ==>
, the output shows that the series of implications is of type bool
, and it's being coerced to prop
by Trueprop
, as shown by the notation :@T
.
HOL logical connectives are of type bool
. For example,
term "op --> :: (bool => bool => bool)"
term "A --> B :: bool"
3 main operators of Pure: eq (==), imp (==>), and all (!!)
Here, I confirm their types. CNTL-click on them to take you to them. A little awareness of the types involved, can make error messages less mysterious.
term "Pure.eq :: 'a => 'a => prop"
term "Pure.imp :: prop => prop => prop"
term "Pure.all :: ('a => prop) => prop"
There's too much to try and say about all this. Someone needs to write a textbook, for logic novices, like me, explaining the logic of Isabelle/HOL, starting with Pure.
prop vs bool
Free variables are implicitly, universally quantified, so I can get rid of the use of !!
. The result is that the type of the term changes from prop
to bool
. Turning on type info can help make sense of type error messages.
term "(!! d k l :: int. 0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1
--> -(2 * l) < 2 * k - 1 --> k ≤ l
--> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)) :: prop"
term "(0 < (d::int) --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1
--> -(2 * l) < 2 * k - 1 --> k ≤ l
--> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)) :: bool"
Your original
You start out with ?thesis ::
int => int => int => bool`.
declare[[show_types=false]]
lemma "!! d k l :: int. 0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1
--> -(2 * l) < 2 * k - 1 --> k ≤ l
--> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" (*
1. !!d k l. (0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 -->
- (2 * l) < 2 * k - 1 --> k ≤ l -->
d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)):@T *)
proof -
fix d k l ::int
assume " ¬ 2 * k + 1 ≤ 2 * l" "k ≤ l"
then have "k = l" by simp
then have "d * (4 * l - 1) = d * (4 * k - 1) " by auto
moreover have "d * (2 * l - 2) + d * (2 * l) + d = d * (4 * l - 1)" by algebra
ultimately have "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" by auto
from this
term "?thesis" (*
"λd k l. 0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1
--> - (2 * l) < 2 * k - 1
--> k ≤ l --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
:: "int => int => int => bool" *)
show ?thesis (*
Type unification failed: Clash of types "_ => _" and "bool"
Type error in application: incompatible operand type
Operator: Trueprop :: bool => prop
Operand: ?thesis∷int => int => int => bool ::
int => int => int => bool
Coercion Inference:
Local coercion insertion on the operand failed:
No coercion known for type constructors: "fun" and "bool" *)
oops
Getting rid of the explicit use of !!
I get rid of !!
, and now I get ?thesis :: bool
, and the error message changes to a very common, frustrating error, "fails to refine any pending goal". It means somehow, I'm not matching up what I'm going to show
, with what the proof engine sees as the goal (I guess).
lemma "0 < (d::int)
--> ¬ 2 * k + 1 ≤ 2 * l
--> 2 * l ≠ 1
--> - (2 * l) < 2 * k - 1 --> k ≤ l
--> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
proof -
fix d k l ::int
assume " ¬ 2 * k + 1 ≤ 2 * l" "k ≤ l"
then have "k=l" by simp
then have "d * (4 * l - 1) = d * (4 * k - 1) " by auto
moreover have "d * (2 * l - 2) + d * (2 * l) + d = d * (4 * l - 1)" by algebra
ultimately have "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" by auto
from this
term "?thesis" (*
"0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 --> - (2 * l) < 2 * k - 1
--> k ≤ l --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
:: "bool"
*)
show ?thesis (*
Failed to refine any pending goal
Local statement fails to refine any pending goal
Failed attempt to solve goal by exported rule:
((¬ 2 * ?ka2 + 1 ≤ 2 * ?la2):@T) ==>
((?ka2 ≤ ?la2):@T) ==>
(0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 --> - (2 * l) < 2 * k - 1
--> k ≤ l --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)):@T *)
oops
Now ==> in place of -->, and a show ?thesis
that gets accepted
And now I replace -->
with ==>
. The type of ?thesis
is still bool
, and it now accepts show ?thesis
.
lemma "0 < (d::int)
==> ¬ 2 * k + 1 ≤ 2 * l
==> 2 * l ≠ 1
==> - (2 * l) < 2 * k - 1 ==> k ≤ l
==> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
proof -
fix d k l ::int
assume " ¬ 2 * k + 1 ≤ 2 * l" "k ≤ l"
then have "k=l" by simp
then have "d * (4 * l - 1) = d * (4 * k - 1) " by auto
moreover have "d * (2 * l - 2) + d * (2 * l) + d = d * (4 * l - 1)" by algebra
ultimately have "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" by auto
from this
term "?thesis" (*
"d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" :: "bool"*)
show ?thesis (*
goal (1 subgoal):
1. (d * ((2::int) * k - (2::int)) + d * ((2::int) * l) + d =
d * ((4::int) * k - (1::int))):@T *)
oops
No need to strain my brain any more today. There are subtleties in what we have to do, to give the proof the engine the facts it wants, in the way it wants them. I can look at the other answer and figure things out more.