Flawed argument in the proof of function extensionality in cubical type theory? I am reading the lectures about cubical type theory in this github repo. In lecture 1 the author defines function extensionality the following way:

funExt (A B : U) (f g : A -&gt; B)
       (p : (x : A) -&gt; Path B (f x) (g x)) :
       Path (A -&gt; B) f g = &lt;i&gt; \(a : A) -&gt; (p a) @ i


and writes

To see that this makes sense compute the end-points of the path:

  (&lt;i&gt; \(a : A) -&gt; (p a) @ i) @ 0 = \(a : A) -&gt; (p a) @ 0
                                  = \(a : A) -&gt; f a
                                  = f


I don't follow. Specifically, when we replace (p a) @ 0 with f a in my mind we use the following fact: \(a : A) -&gt; (p a) @ 0 = f a to rewrite (let's give names to the left and right side) fpa = \(a : A) -&gt; (p a) @ 0 into fa = \(a : A) -&gt; f a. But isn't this by itself using function extensionality with f = fpa, g = fa?

If I am not mistaken, this argument is circular. Can anyone clarify?
The expression:

\(a : A) -&gt; (p a) @ 0


parses as:

\(a : A) -&gt; ((p a) @ 0)


So this is applying p a : Path B (f a) (g a) to the 0 point. This reduces to f a, because it is the beginning point of the path. It's essentially doing the same thing as the earlier step, which beta reduced the (&lt;i&gt; ...) @ 0 to (...)[i := 0], except p a looks abstract to us, but that doesn't matter, because we know what it reduces to when applied to 0 (or 1) based only on its type.

So, it's not using function extensionality to prove extensionality. What it's doing is taking advantage of the fact that Path types are similar to function types, and that the two Path types in funExt are 'just' functions with different argument order (so it flips them).