A type theory based on indexed equality - Implementation

In this post I would like to present the type theory I have been working on, where the usual equality is replaced by an equality type indexed by the homotopy interval. This results in ideas very similar to those from the cubical system. I have a prototype implementation of this system in Haskell, which you can find on github. The system is unimaginatively called TTIE, a type theory with indexed equality. In this post I will focus on the introducing the type system and its implementation. I save the technical details for another post.

To recap: I have previously written about the 'indexed equality' type. The idea is that if we have the homotopy interval type with two points and a path between them,

data Interval : Type where 0 : Interval 1 : Interval 01 : Eq _ 0 1

then we can then define a type of equality, 'indexed' by the interval:

data Eq (A : Interval → Type ) : A 0 → A 1 → Type where refl : ( x : ( i : Interval ) → A i ) → Eq A ( x 0 ) ( x 1 )

Rather than using lambdas all the time in the argument of Eq and refl , in TTIE I write the bound variable in a subscript. So refl i (x i) means refl (\i → x i) and Eq i (A i) x y means Eq (\i → A i) x y . If we represent all paths with this indexed equality type, then we can actually take 01 = refl i i .

Now the (dependent) eliminator for the interval is

iv : ∀ {A} → { x : A 0 } → { y : A 1 } → ( xy : Eq i (A i ) x y ) → ( i : Interval ) → A i iv {A} { x } { y } xy 0 = x iv {A} { x } { y } xy 1 = y iv {A} { x } { y } ( refl i ( xy i )) i = xy i refl i ( iv {A} { x } { y } xy i ) = xy

For readability, I write iv xy i as xyi . This combination already makes it possible to prove, for instance, congruence of functions without needing to use substitution (the J rule):

cong : ∀ {A B x y } → ( f : A → B) → Eq i A x y → Eq i B ( f x ) ( f y ) cong f xy = refl i ( f xyi)

this can be generalized to dependent types

cong : ∀ {A B x y } → ( f : ( x : A) → B x ) → ( xy : Eq i A x y ) → Eq i (B xyi) ( f x ) ( f y ) cong f xy = refl i ( f xyi)

And we also get extensionality up to eta equality:

ext : ∀ {A B f g } → (( x : A) → Eq i (B x ) ( f x ) ( g x )) → Eq i (( x : A) → B x ) ( \ x → f x ) ( \ x → g x ) ext fg = refl i ( \ x → ( fg x )i)

So far, however, we can not yet represent general substitution. I have found that the most convenient primitive is

cast : (A : I → Type ) → ( i : Interval ) → ( j : Interval ) → A i → A j

where cast i A 0 0 x = x and cast i A 1 1 x = x .

This generalized cast makes all kinds of proofs really convenient. For instance, we would like that cast A 1 0 ∘ cast A 0 1 = id . But it is already the case that cast A 0 0 ∘ cast A 0 0 = id . So we just have to change some of those 0s to 1s,

lemma : ∀ {A : Type } { x } → Eq _ ( cast i A 1 0 ( cast i A 0 1 x )) x lemma {A} { x } = cast j ( Eq _ ( cast i A j 0 ( cast i A 0 j x )) x ) 0 1 ( refl i x )

As another example, most type theories don't come with a built in dependent or indexed equalty type. Instead, a common approach is to take

Eq i (A i ) x y = Eq (A 0 ) x ( cast i (A i ) 1 0 y )

or

Eq i (A i ) x y = Eq (A 1 ) ( cast i (A i ) 0 1 x ) y

We can prove that these are equivalent:

lemma' : ∀ {A} { x y } → Eq Type ( Eq (A 0 ) x ( cast i (A i ) 1 0 y )) ( Eq i (A i ) x y ) lemma' {A} { x } { y } = refl j ( Eq k (A ( j && k )) x ( cast i (A i ) 1 j y ))

where i && j is the and operator on intervals, i.e.

_ && _ : Interval → Interval → Interval 0 && j = 0 1 && j = j i && 0 = 0 i && 1 = i

We can even go one step further to derive the ultimate in substitution, the J axiom:

J : ∀ {A : Type } { x : A} → (P : ( y : A) → Eq A x y → Type ) → ( y : A) → ( xy : Eq A x y ) → P x ( refl x ) → P y xy J P y xy pxy = cast i (P xyi ( refl j (xy ^ ( j && i )))) 0 1 pxy

With the TTIE implementation, you can type check the all of the above examples. The implementation comes with a REPL, where you can ask for types, evaluate expressions, and so on. Expressions and types can have holes, which will be inferred by unification, like in Agda.