With the following definition of equality, we have refl as constructor
data _≡_ {a} {A : Set a} (x : A) : A → Set a where
refl : x ≡ x
and we can prove that function are congruent on equality
cong : ∀ { a b} { A : Set a } { B : Set b }
(f : A → B ) {m n} → m ≡ n → f m ≡ f n
cong f refl = refl
I am not sure I can parse what is going on exactly here. I think we are pattern matching refl on hidden parameters : if we replace the first occurence by refl by another identifier, we get a type error. after pattern matching, I imagine that m and n are the same by the definition of refl. then magic occurs (a definition of functionality of a relation is applied ? or is it build in ?)
Is there an intuitive description on what is going on ?
Yes, the arguments in curly braces
{}are implicit and they only need to be supplied or matched if agda cannot figure them out. It is necessary to specify them, since dependent types needs to refer to the values they depend on, but dragging them around all the time would make the code rather clunky.The expression
cong f refl = reflmatches the explicit arguments (A → B) and (m ≡ n). If you wanted to match the implicit arguments, you'd need to put the matching expression in{}, but here there is no need for that. Then on the right hand side it is indeed the construction of (f m ≡ f n) usingrefl, and it works "by magic". Agda has a built-in axiom that proves this to be true. That axiom is similar (but stronger than)J-axiom - the induction axiom: if somethingC : (x y : A) → (x ≡ y) → Setis true forC x x refl, then it is also true for anyx y : Aandp : x ≡ y.(In this last line we: match explicit arguments
fandp, and also the implicit argumentsm=xandn=y. Then we pass toJone implicit argument, but it is not the first positional implicit, so we tell agda that it isCin the definition - without doing that, Agda won't see what type is meant byreflin\_ → refl)