I wrote the following proposition in Idris:
total
plusOneCommutes : (n : Nat) -> (m : Nat) -> (n + S m = S n + m)
plusOneCommutes Z k = Refl
plusOneCommutes (S k) j =
let inductiveHypothesis = plusOneCommutes k j in
rewrite inductiveHypothesis in Refl
Using inspiration from the Prelude.Nat
source code, I understand why it makes sense to use the recursive call (in the second case) as an induction hypothesis in order to prove the case. However, going through the details of the rewriting with holes, I don't really grok what's going on and why this works.
If I write:
plusOneCommutes (S k) j = ?hole
I get the following from the compiler:
- + HolyGrail.hole [P]
`-- k : Nat
j : Nat
------------------------------------------------------
HolyGrail.hole : S (plus k (S j)) = S (S (plus k j))
which does not really seem right. According to the signature of plusOneCommutes
this hole should have type (plus (S k) (S j)) = (plus (S (S k)) j)
.
Going one step further and introducing induction hypothesis, if I write:
plusOneCommutes (S k) j =
let inductiveHypothesis = plusOneCommutes k j in
?hole
then type of hole
becomes:
- + HolyGrail.hole [P]
`-- k : Nat
j : Nat
inductiveHypothesis : k + S j = S k + j
-------------------------------------------------------------------------
HolyGrail.hole : S (plus k (S j)) = S (S (plus k j))
then using the rewrite rule given by inductiveHypothesis
- + HolyGrail.hole [P]
`-- k : Nat
j : Nat
inductiveHypothesis : k + S j = S k + j
_rewrite_rule : k + S j = S k + j
-------------------------------------------------------------------------
HolyGrail.hole : (\replaced => S replaced = S (S (plus k j))) (S k + j)
which leads to S (plus (S k) j) = S (S (plus k j))
which is the expected type, and Idris can complete the proof automatically replacing ?hole
with Refl
.
What's puzzling me then is the unexpected difference in types between what I infer from the signature and what the compiler infers from the hole. If I introduce voluntarily an error:
I get the following message:
- + Errors (1)
`-- HolyGrail.idr line 121 col 16:
When checking right hand side of plusOneCommutes with expected type
S k + S j = S (S k) + j
Type mismatch between
S (S (plus k j)) = S (S (plus k j)) (Type of Refl)
and
S (plus k (S j)) = S (S (plus k j)) (Expected type)
Specifically:
Type mismatch between
S (plus k j)
and
plus k (S j)
The Type mismatch...
part is consistent with the above steps but not the When checking ...
part which gives the type I would expect.