I'd like to define a function with two, higher inductive typed, arguments in Cubical mode. I am using the cubical package as my "prelude" library.

I first define a quotient type for integers as a HIT:

{-# OPTIONS --cubical #-} module _ where open import Data.Nat renaming (_+_ to _+̂_) open import Cubical.Core.Prelude data ℤ : Set where _-_ : (x : ℕ) → (y : ℕ) → ℤ quot : ∀ {x y x′ y′} → (x ℕ+ y′) ≡ (x′ ℕ+ y) → (x - y) ≡ (x′ - y′)

I can then define a unary function using pattern matching:

_+1 : ℤ → ℤ (x - y) +1 = suc x - y quot {x} {y} prf i +1 = quot {suc x} {y} (cong suc prf) i

So far, so good. But what if I want to define a binary function, such as addition?

First, let's get the boring arithmetic proofs out of the way:

import Data.Nat.Properties open Data.Nat.Properties.SemiringSolver using (prove; solve; _:=_; con; var; _:+_; _:*_; :-_; _:-_) open import Relation.Binary.PropositionalEquality renaming (refl to prefl; _≡_ to _=̂_) using () fromPropEq : ∀ {ℓ A} {x y : A} → _=̂_ {ℓ} {A} x y → x ≡ y fromPropEq prefl = refl open import Function using (_$_) reorder : ∀ x y a b → (x +̂ a) +̂ (y +̂ b) ≡ (x +̂ y) +̂ (a +̂ b) reorder x y a b = fromPropEq $ solve 4 (λ x y a b → (x :+ a) :+ (y :+ b) := (x :+ y) :+ (a :+ b)) prefl x y a b inner-lemma : ∀ x y a b a′ b′ → a +̂ b′ ≡ a′ +̂ b → (x +̂ a) +̂ (y +̂ b′) ≡ (x +̂ a′) +̂ (y +̂ b) inner-lemma x y a b a′ b′ prf = begin (x +̂ a) +̂ (y +̂ b′) ≡⟨ reorder x y a b′ ⟩ (x +̂ y) +̂ (a +̂ b′) ≡⟨ cong (x +̂ y +̂_) prf ⟩ (x +̂ y) +̂ (a′ +̂ b) ≡⟨ sym (reorder x y a′ b) ⟩ (x +̂ a′) +̂ (y +̂ b) ∎ outer-lemma : ∀ x y x′ y′ a b → x +̂ y′ ≡ x′ +̂ y → (x +̂ a) +̂ (y′ +̂ b) ≡ (x′ +̂ a) +̂ (y +̂ b) outer-lemma x y x′ y′ a b prf = begin (x +̂ a) +̂ (y′ +̂ b) ≡⟨ reorder x y′ a b ⟩ (x +̂ y′) +̂ (a +̂ b) ≡⟨ cong (_+̂ (a +̂ b)) prf ⟩ (x′ +̂ y) +̂ (a +̂ b) ≡⟨ sym (reorder x′ y a b) ⟩ (x′ +̂ a) +̂ (y +̂ b) ∎

I now try to define _+_ using pattern matching, but I have no idea how to handle the "points in the center of the face", so to speak:

_+_ : ℤ → ℤ → ℤ (x - y) + (a - b) = (x +̂ a) - (y +̂ b) (x - y) + quot {a} {b} {a′} {b′} eq₂ j = quot {x +̂ a} {y +̂ b} {x +̂ a′} {y +̂ b′} (inner-lemma x y a b a′ b′ eq₂) j quot {x} {y} {x′} {y′} eq₁ i + (a - b) = quot {x +̂ a} {y +̂ b} {x′ +̂ a} {y′ +̂ b} (outer-lemma x y x′ y′ a b eq₁) i quot {x} {y} {x′} {y′} eq₁ i + quot {a} {b} {a′} {b′} eq₂ j = ?

So basically what I have is the following situation:

p Xᵢ X ---------+---> X′ p₀ i A X+A --------\---> X′+A | | | q| q₀ | | qᵢ | | | Aⱼ + j+ [+] <--- This is where we want to get to! | | | V V p₁ | A′ X+A′ -------/---> X′+A′ i

with

X = (x - y) X′ = (x′ - y′) A = (a - b) A′ = (a′ - b′) p : X ≡ X′ p = quot eq₁ q : A ≡ A′ q = quot eq₂ p₀ : X + A ≡ X′ + A p₀ = quot (outer-lemma x y x′ y′ a b eq₁) p₁ : X + A′ ≡ X′ + A′ p₁ = quot (outer-lemma x y x′ y′ a′ b′ eq₁) q₀ : X + A ≡ X + A′ q₀ = quot (inner-lemma x y a b a′ b′ eq₂) q₁ : X′ + A ≡ X′ + A′ q₁ = quot (inner-lemma x′ y′ a b a′ b′ eq₂)

I am using this construction to push out q₀ horizontally by i :

slidingLid : ∀ {ℓ} {A : Set ℓ} {a b c d} (p₀ : a ≡ b) (p₁ : c ≡ d) (q : a ≡ c) → ∀ i → p₀ i ≡ p₁ i slidingLid p₀ p₁ q i j = comp (λ _ → A) (λ{ k (i = i0) → q j ; k (j = i0) → p₀ (i ∧ k) ; k (j = i1) → p₁ (i ∧ k) }) (inc (q j))

and using this, my attempt at + is as follows:

quot {x} {y} {x′} {y′} eq₁ i + quot {a} {b} {a′} {b′} eq₂ j = Xᵢ+Aⱼ where X = (x - y) X′ = (x′ - y′) A = (a - b) A′ = (a′ - b′) p : X ≡ X′ p = quot eq₁ q : A ≡ A′ q = quot eq₂ p₀ : X + A ≡ X′ + A p₀ = quot (outer-lemma x y x′ y′ a b eq₁) p₁ : X + A′ ≡ X′ + A′ p₁ = quot (outer-lemma x y x′ y′ a′ b′ eq₁) q₀ : X + A ≡ X + A′ q₀ = quot (inner-lemma x y a b a′ b′ eq₂) qᵢ : ∀ i → p₀ i ≡ p₁ i qᵢ = slidingLid p₀ p₁ q₀ q₁ : X′ + A ≡ X′ + A′ q₁ = quot (inner-lemma x′ y′ a b a′ b′ eq₂) Xᵢ+Aⱼ = qᵢ i j

But this fails with the following type error:

quot (inner-lemma x′ y′ a b a′ b′ eq₂) j != hcomp (λ { i ((~ i1 ∨ ~ j ∨ j) = i1) → transp (λ j₁ → ℤ) i ((λ { i₁ (i1 = i0) → q₀ eq₁ i1 eq₂ j j ; i₁ (j = i0) → p₀ eq₁ i1 eq₂ j (i1 ∧ i₁) ; i₁ (j = i1) → p₁ eq₁ i1 eq₂ j (i1 ∧ i₁) }) (i ∨ i0) _) }) (transp (λ _ → ℤ) i0 (ouc (inc (q₀ eq₁ i1 eq₂ j j)))) of type ℤ

One hint to what might be going wrong is that while these three sides degenerate nicely:

top : ∀ i → qᵢ i i0 ≡ p i + q i0 top i = refl bottom : ∀ i → qᵢ i i1 ≡ p i + q i1 bottom i = refl left : qᵢ i0 ≡ q₀ left = refl

the rightmost side doesn't:

right : qᵢ i1 ≡ q₁ right = ? -- refl fails here

I guess because qᵢ is pulled from the left side, so there could still be a hole between the right side and the pushed-all-the-way qᵢ , i.e. this would still be possible, with a hole at O between qᵢ i1 and q₁ :

p₀ X+A ------------> X′+A | /| q₀ | / | q₁ | | | | | O| | \ | V p₁ \| X+A′ -----------> X′+A′