I asked the following question on the CS SE:
For example, in the proof of lemma 6.4.1 in the HoTT book, a function inductively defined over a function is simply applied on paths
loop
andrefl
, and then a path betweenloop
andrefl
is used (presumably by congruence viaf
) to construct a path betweenf loop
andf refl
:Suppose that
loop = refl base
. [...] withx : A
andp : x = x
, there is a functionf : S1 → A
defined byf(base) :≡ x
andf(loop) := p
, we havep = f(loop) = f(refl base) = refl x.
But in a cubical setting, things are not so clear-cut.
f(loop)
is not well-typed, onlyf(loop i)
is, for somei : I
. But then that above proof becomesp = <i> f (loop i) = <i> f (refl base i) = refl x
but doesn't that need some kind of "interval extensionality" in the middle step? What exactly is the justification of the middle step in cubical type theory? I can see how to prove
∀ i → f (loop i) = f (refl base i)
, but how does one "lift" that to<i> f (loop i) = <i> f (refl base i)
?
I haven't received a response there so I'm going to try here, with concrete Agda code to back it.
I am trying to turn the above proof into Cubical Agda as follows. First, given p
, the definition of f
is straightforward:
hyp : loop ≡ refl {x = base}
p : x ≡ x
f : S¹ → A
f base = x
f (loop i) = p i
We can prove pointwise along loop
that f (loop i) ≡ f (refl i)
:
proofAt_ : ∀ i → f (loop i) ≡ f base
proofAt i = cong (λ p → f (p i)) hyp
(to see why, here it is in more detail:
proofAt_ : ∀ i → f (loop i) ≡ f base
proofAt i = begin
f (loop i) ≡⟨ cong (λ p → f (p i)) hyp ⟩
f (refl {x = base} i) ≡⟨⟩
f base ∎
)
but if I try to prove it for the whole thing:
proof : p ≡ refl
proof = begin
(λ i → p i) ≡⟨⟩
(λ i → f (loop i)) ≡⟨ (λ i → proofAt i) ⟩
(λ i → f base) ≡⟨⟩
(λ i → refl {x = x} i) ∎
it fails, I would think because of the "interval extensionality" I am trying to use:
Cannot instantiate the metavariable
_342
to solutionf (loop i) ≡ f base
since it contains the variablei
which is not in scope of the metavariable or irrelevant in the metavariable but relevant in the solutionwhen checking that the expression
proofAt i
has type_A_342
trying to eta-convert it to just proofAt_
also fails, but for a different reason (and I think there is, in general, no eta conversion for paths):
proof : p ≡ refl
proof = begin
(λ i → p i) ≡⟨⟩
(λ i → f (loop i)) ≡⟨ proofAt_ ⟩
(λ i → f base) ≡⟨⟩
(λ i → refl {x = x} i) ∎
((i : I) → f (loop i) ≡ f base)
!=<_344 ≡ _y_345
of type;Agda.Primitive.Setω
So, what is the correct CTT transliteration of the above HoTT proof?
Paths do have eta rules
however the type path is not the same as the type of functions from the interval "I", so sometimes you need a lambda abstraction just to convert between the two types. (Lambda and application are ad-hoc overloaded between the two types).
f loop
indeed does not typecheck, not in even in HoTT. However the book uses it as a shorthand for ap f loop
, where ap = cong
from the cubical library.
Also, your proof can be completed, but you need to use proofAt_
correctly: the i
dimension in proof
is the one connecting cong f loop
and refl {x = f base}
, so you want to provide i
as the second argument of proofAt_
.
proof : p ≡ refl
proof = begin
(λ i → p i) ≡⟨⟩
(λ i → f (loop i)) ≡⟨ (λ i j → proofAt j i) ⟩
(λ i → f base) ≡⟨⟩
(λ i → refl {x = x} i) ∎