2度目のCubical

Thierry Coquandが、cubical interpreterでHigher Inductive Typeが使えるようになったとアナウンスしていた。理論的な面で進歩があったわけではないようだけど、cubical interpreterの実装が少し進歩したらしい。
https://github.com/mortberg/cubicaltt


基本的には、以前の実装を踏襲しているけど、primitive扱いだったreflとかmapOnPathが

refl (A : U) (a : A) : Id A a a = <i> a

みたいな形で定義できるようになっている。前も、内部的には、こういう形で扱われていた(実装上はTermとValueの区別が、あんまりなくなった?)のだけど、明示的に書けるようになったので、cubical type theoryを理解するのに便利になった。この変更のおかげで、実装も以前より、すっきりしたように見える。


<i> aは直感的には、i=0とi=1にaを対応させるintervalのことと思う(一次元"cube")。
Variation on Cubical sets
http://www.cse.chalmers.se/~coquand/comp.pdf
の13節に、operational semanticsとかがある。一般に、p : Id A x yは、i=0にx、i=1にyを対応させる"関数のようなもの"と解釈されて、新しいcubical interpreterでは、p@0とp@1で、それぞれx,yを取り出せる。直感的には、iは区間[0,1]のことであるが、p@0.5とかはできない


Syntaxとかも少し変更されているようなので、
はじめてのCubical
http://d.hatena.ne.jp/m-a-o/20131227#p1
の後半の例を書き直してみた(Syntaxは、また変わるかもしれないが)

module firsttest where

-- definitions from examples/prelude.ctt
-- -- "IdP P a b" is a built-in notion where P : Id U A B, a : A and b : B
-- "<a>" abstracts the name/color/dimension a.
Id (A : U) (a0 a1 : A) : U = IdP (<a> A) a0 a1

refl (A : U) (a : A) : Id A a a = <i> a

mapOnPath (A B : U) (f : A -> B) (x y : A)
          (p : Id A x y) : Id B (f x) (f y) = <a> f (p @ a)

funExt (A : U) (B : A -> U) (f g : (x : A) -> B x)
       (p : (x : A) -> Id (B x) (f x) (g x)) :
       Id ((y : A) -> B y) f g = <i> \(a : A) -> (p a) @ i

subst (A : U) (P : A -> U) (a b : A) (p : Id A a b) (e : P a) : P b =
  transport (mapOnPath A U P a b p) e


-- end of quote


ext (A B:U) (f g:A->B) (p : (x:A) -> Id B (f x) (g x)) : Id (A->B) f g = funExt A (\(a:A) -> B) f g p

data Nat = zero | succ (n:Nat)

add : Nat -> Nat -> Nat = split
  zero -> \(y:Nat) -> y
  succ n -> \(y:Nat) -> succ (add n y)

add0 : Nat -> Nat = \(n:Nat) -> add zero n

id (A:U) (a:A) : A = a

add0 : Nat -> Nat = \(n:Nat) -> add zero n

add0_eq_id : Id (Nat->Nat) add0 (id Nat) = 
   ext Nat Nat add0 (id Nat) p
      where
         p (n:Nat) : (Id Nat (add0 n) (id Nat n)) = refl Nat n

test : Nat = subst (Nat->Nat) f add0 (id Nat) add0_eq_id  zero
  where
    f (x:Nat -> Nat) : U = Nat 

前半部分は、prelude.cttから取ってきたので、import preludeで済む(transportとIdPはprimitive)。ファイルをloadして、testを評価すると、これが、ちゃんとzeroであることが分かる


以前は、内部的に扱われていたKan compositionも明示的に書けるようになった(Variation on Cubical setsの4節に説明がある)。例えば

module kantest where

Id (A : U) (a0 a1 : A) : U = IdP (<a> A) a0 a1
kan (A : U) (a b c d : A) (p : Id A a b) (q : Id A a c)
                          (r : Id A b d) : Id A c d =
  <i> comp A (p @ i) [ (i = 0) -> q , (i = 1) -> r ]

これは
A model of type theory in cubical sets
http://www.cse.chalmers.se/~coquand/mod1.pdf
の操作$X^{+}$に対応している。<i> comp A (p @ i) [ (i = 0) -> q , (i = 1) -> r ]は、i=0の時
(<i> comp A (p @ i) [ (i = 0) -> q , (i = 1) -> r ])@0 = comp A a [(i=0)->q]
で、qの型はq : Id A a cであるけど、compは点a=q@0をq : Id A a cをc=q@1に"繋ぐ"ような働きをして、
(<i> comp A (p @ i) [ (i = 0) -> q , (i = 1) -> r ])@0 = c
となる。同様に、i=1の時は
(<i> comp A (p @ i) [ (i = 0) -> q , (i = 1) -> r ])@1 = d
で、<i> comp A (p @ i) [ (i = 0) -> q , (i = 1) -> r ]自体の型は、Id A c dとなる。これを使えば、Idの推移律を示すことができる。対称律も、本来は、Kan filling/Kan compositionを使って作るのだけど、もっと単純に

eqsym (A:U) (x y:A) (p:Id A x y) : Id A y x= <i> p @ -i

と書ける。-iは、0を1に、1を0にする



compはintervalだけじゃなく、squareとか、任意のn-cubeも作れる。

module sqtest where
Id (A:U) (x y:A) : U = IdP (<i> A) x y
prop (A : U) : U = (a b : A) -> IdP (<i> A) a b
--         u
--    a0 -----> a1
--    |         |
-- r0 |         | r1
--    |         |
--    V         V
--    b0 -----> b1
--         v

Square (A : U) (a0 a1 : A) (u : Id A a0 a1)
               (b0 b1 : A) (v : Id A b0 b1)
               (r0 : Id A a0 b0) (r1 : Id A a1 b1) : U
  = IdP (<i> (IdP (<j> A) (u @ i) (v @ i))) r0 r1

propSquare  (A:U) (H:prop A) (a a0 a1 b0 b1:A) (r0 : Id A a0 b0) (r1 : Id A a1 b1) (u : Id A a0 a1) (v : Id A b0 b1) 
  : Square A a0 a1 u b0 b1 v r0 r1
  = <i j> comp A a [(i=0)-> H a (r0@j) ,(i=1) -> H a (r1@j) , (j=0) -> H a (u@i) , (j=1) -> H a (v@i)]

とか。<i j> comp A a [(i=0)-> H a (r0@j) ,(i=1) -> H a (r1@j) , (j=0) -> H a (u@i) , (j=1) -> H a (v@i)]は、頂点(i,j)=(0,0)に於いては、
comp A a [(i=0) -> H a (r0@0)]
と同じで、これはa0である。または
comp A a [(j=0) -> H a (u@0)]
でもあり、やっぱり、a0である。これは、当然ながら、ちゃんとcompatibleでないといけない。[]の中は空でもよくて(0-cube相当?)、comp A a [ ]は、aになる。


glueingもあるけど略


Higher Inductive Typeの作り方は,circle.cttとかsusp.cttとかinterval.cttとかにある

data S1 = base
        | loop_ @ base ~ base

loop : Id S1 base base = <i> loop_{S1} @ i

みたいにやる。なんでだかよく分からないけど、コンストラクタloop_の型は、Id S1 base baseでなく、上のような形で作る必要がある。それ以外は、普通



Quotients of sets
http://ncatlab.org/nlab/show/higher+inductive+type#QuotientsOfSets
を真似て、HITを使ってquotient typeを作ろうと思ったのだけど、書いてある定義は出来ない気がする

module quotient where
import prelude

rel (A:U) : U = A -> A -> U

prop (A:U) : U = (x y:A) -> Id A x y

propRel (A:U) (R:rel A) : U = (x y : A) -> prop (R x y)

{-
data quotient (A:U) (R:rel A) (p:propRel A R) 
  = proj (x:A) 
  | relate (x y:A) (r:R x y) @ proj x ~ proj y
  | contr1 (x y:quotient A R p) (u v : Id (quotient A R p) x y) @ u ~ v
-}

data quotient (A:U) (R:rel A) 
  = proj (x:A) 
  | relate (x y:A) @ proj x ~ proj y

よく考えてみると、contr1は、商をhSetにするために必要なのだと思うけど、そもそも、AがhSetでない場合、商もhSetであるとは限らないで、contr1が定義出来てしまうと、矛盾してしまう気がするけど、どうなんだろう。
quotient type in cubical type theory
http://d.hatena.ne.jp/m-a-o/20140825#p1
で定義したquotと同等な定義は上の形でいいんじゃないかという気がする。推測では、これだけで、(RがpropRelかつequivalenceの時)、商の普遍性が言え("inductive"なんだから普遍性は満たすだろうと思うけど)て、HITを使わないquotient typeと等しいことが言えると思う(けど、証明は書いていない。そのうち書く)


あと、こういう↓感じで、assocを定義しようとすると無理っぽい。2回addが出てきているので、だめっぽい

module testdat where

-- type constructor "assoc" is invalid
data TestAlg (A:U)
  = empty
  | lift (x:A)
  | add (x:TestAlg A) (y:TestAlg A)
  | comm (x y:TestAlg A) @ add x y ~ add y x
--  | assoc (x y z:TestAlg A) @ add (add x y) z ~ add x (add y z)


homotopy groups of spheres
http://ncatlab.org/homotopytypetheory/show/homotopy+groups+of+spheres

Guillaume has proved that there exists an $n$ such that $\pi_4(S^3)$ is $\mathbb{Z}_n$. Given a computational interpretation, we could run this proof and check that $n$ is 2.

という一文があるのだけど、cubical interpreterは、univalence axiomのcomputational interpretationを与えていると(予想)され、かつHITを使えるようになった(Suspensionがあるので、S^3は定義できる)ので、試金石として試すことができるはず