The two SO questions that answer this are this one for comm
and this one for trunc
. Like you, I've struggled with the same frustration: if all these types are Set
s, why do I need to write ANYTHING, let alone something complicated, to prove some 2-paths?!?!
So, first of all, from the first linked answer, let's start at
comm x y xs i ++ ys = ?
and ask Agda what is the type of the hole.
Goal: comm x y (xs ++ []) i ≡ comm x y xs i
Well that sounds promising because we know that comm x y (xs ++ []) ≡ comm x y xs
simply by xs + [] ≡ xs
inductively. So, let's ask what exactly that would buy us. Put cong (comm x y) (unitr-++ xs)
in the hole and ask for its type:
Have:
PathP
(λ i → x ∷ y ∷ unitr-++ xs i ≡ y ∷ x ∷ unitr-++ xs i)
(comm x y (xs ++ [])) (comm x y xs)
Then @Saizan's answer instructs us to produce the Square
with exactly these faces:
isSet→isSet' trunc
(comm x y (xs ++ []))
(comm x y xs)
(λ j → x ∷ y ∷ unitr-++ xs i)
(λ j → y ∷ x ∷ unitr-++ xs i)
and choose the right internal point on it, giving us the filling of our hole:
unitr-++ (comm x y xs i) j = isSet→isSet' trunc
(comm x y (xs ++ []))
(comm x y xs)
(λ j → x ∷ y ∷ unitr-++ xs j)
(λ j → y ∷ x ∷ unitr-++ xs j)
j i
For the second missing clause, i.e. in
unitr-++ (trunc xs1 xs2 p q i j)
following the linked answer's recommendation, we can ask Agda for the faces of the cube we want to construct:
r : Cube ? ? ? ? ? ?
r = cong (cong unitr-++) (trunc xs1 xs2 p q)
By using C-c C-s
in all six face holes, Agda tells us:
r : Cube (λ i j → trunc xs1 xs2 p q i j ++ [])
(λ i j → unitr-++ xs1 j)
(λ i j → unitr-++ xs2 j)
(λ i j → trunc xs1 xs2 p q i j)
(λ i j → unitr-++ (p i) j)
(λ i j → unitr-++ (q i) j)
so now we know exactly which cube to construct (using the fact that Set
s are also Groupoid
s, as witnessed by hLevelSuc 2 _
):
unitr-++ (trunc xs1 xs2 p q i j) = isGroupoid→isGroupoid' (hLevelSuc 2 _ trunc)
(λ i j → trunc xs1 xs2 p q i j ++ [])
(λ i j → unitr-++ xs1 j)
(λ i j → unitr-++ xs2 j)
(λ i j → trunc xs1 xs2 p q i j)
(λ i j → unitr-++ (p i) j)
(λ i j → unitr-++ (q i) j)
i
j
By now, on one hand, we can be happy that we're done, but on the other hand, we are pissed off because this answer was all "look at this other answer and do exactly that", "look at this other answer and do exactly that", but surely if you can do EXACTLY that, even though your type, and your function, and your function property, are NOT the same as mine was when I asked my original question, then there is something that should be abstracted away here, right?
And that is what FMSetElimProp
does. It implements ALL this machinery above, for FMSet
specifically, but for all functions and all properties of those functions, in one fell swoop. So you DON'T have to look at this answer and the two linked ones and do all this OVER and OVER and OVER again, when in fact at the end it shouldn't make a difference anyway since all the constructed paths are path-equivalent anyway.
FMSet
is a set (i.e. homotopy level 0), so all equalities are equal (all paths have paths between them).FMSetElimProp
is a proof of this fact. So you can use it anywhere you need an equality between equalities ofFMSet
s. – FlatwormFMSetElimProp.f
is very impressive! Unfortunately, I must be very stupid because I only see a complicated statement there. Could you elaborate in an answer how you arrive at this interpretation? – Neopythagoreanismcomm
clause of theunitr-++
function, you need to provide an equality of equalities. You can prove this manually (as far as I know), but since you've already specified thatFMSet
is h-level 0 (that's what adding thetrunc
constructor to the type does), you don't have to, since all equalities of h-level 0 types are automatically equal. So you just provide a proof of that fact (which is proven already in the cubical library), which is calledFMSetElimProp
. – Flatworm