Teoría Homotópica de Tipos

Tipos Inductivos

Los tipos inductivos son tipos libremente generados por sus términos canónicos (constructores). Para definir una función (dependiente) a partir de un tipo inductivo, basta definirla en sus elementos canónicos.

Ideas generales

Los formadores de tipos son las reglas que definen Π\Pi, \to, /×\land/\times, los tipos inductivos, etc. Cuando estudiamos teoría de tipos, elegimos cuáles formadores incluir. Cuando se habla de HoTT, generalmente se refiere a una teoría de tipos con formadores particulares (los de este curso) más un axioma (univalencia).

Comparado con ZF: en la teoría de conjuntos, productos, funciones, etc. deben ser codificados dentro de ZF. En la teoría de tipos, postulamos que productos, funciones, etc. existen directamente. Así, la matemática cotidiana está más cerca de los fundamentos en teoría de tipos.

Los booleanos

Definición 1 — bool\text{bool}

bool\text{bool} es generado por dos términos canónicos: true\text{true} y false\text{false}.

Formación:

bool  type\frac{}{\vdash \text{bool} \;\text{type}}

Introducción:

true:boolfalse:bool\frac{}{\vdash \text{true} : \text{bool}} \qquad \frac{}{\vdash \text{false} : \text{bool}}

Eliminación: Dados:

  • Γ,x:boolD  type\Gamma, x : \text{bool} \vdash D \;\text{type}
  • Γa:D[true/x]\Gamma \vdash a : D[\text{true}/x]
  • Γb:D[false/x]\Gamma \vdash b : D[\text{false}/x]

Entonces: Γ,x:boolind-boola,b:D\Gamma, x : \text{bool} \vdash \text{ind-bool}_{a,b} : D

Es decir: para construir algo de tipo DD para cualquier booleano, basta dar un valor para el caso true\text{true} y otro para el caso false\text{false}.

Computación:

ind-boola,b[true/x]a:D[true/x]\text{ind-bool}_{a,b}[\text{true}/x] \doteq a : D[\text{true}/x] ind-boola,b[false/x]b:D[false/x]\text{ind-bool}_{a,b}[\text{false}/x] \doteq b : D[\text{false}/x]

En Agda/Rocq:

data Bool : Type where
  true false : Bool
Ejemplo 1 — not:boolbool\text{not} : \text{bool} \to \text{bool}

Definimos la negación como not:=λx.ind-boolfalse,true:boolbool\text{not} := \lambda x.\, \text{ind-bool}_{\text{false}, \text{true}} : \text{bool} \to \text{bool}.

En la derivación, usamos la regla de formación debilitada de bool\text{bool} (en un contexto x:boolx : \text{bool}), y los hechos de que false:boolbool[true/x]\text{false} : \text{bool} \doteq \text{bool}[\text{true}/x] y true:boolbool[false/x]\text{true} : \text{bool} \doteq \text{bool}[\text{false}/x].

Coproductos

Definición 2 — Coproducto P+QP + Q

Formación: Si ΓP  type\Gamma \vdash P \;\text{type} y ΓQ  type\Gamma \vdash Q \;\text{type}, entonces ΓP+Q  type\Gamma \vdash P + Q \;\text{type}.

Introducción: Si Γp:P\Gamma \vdash p : P, entonces Γinl(p):P+Q\Gamma \vdash \text{inl}(p) : P + Q. Si Γq:Q\Gamma \vdash q : Q, entonces Γinr(q):P+Q\Gamma \vdash \text{inr}(q) : P + Q.

Eliminación: Dados:

  • Γ,x:P+QD  type\Gamma, x : P + Q \vdash D \;\text{type}
  • Γ,p:Pa:D[inl(p)/x]\Gamma, p : P \vdash a : D[\text{inl}(p)/x]
  • Γ,q:Qb:D[inr(q)/x]\Gamma, q : Q \vdash b : D[\text{inr}(q)/x]

Entonces: Γ,x:P+Qind-+a,b:D\Gamma, x : P + Q \vdash \text{ind-}+_{a,b} : D

Es decir: para construir algo a partir de P+QP + Q, basta manejar el caso en que viene de PP (vía inl\text{inl}) y el caso en que viene de QQ (vía inr\text{inr}).

Computación:

ind-+a,b[inl(p)/x]a:D[inl(p)/x]\text{ind-}+_{a,b}[\text{inl}(p)/x] \doteq a : D[\text{inl}(p)/x] ind-+a,b[inr(q)/x]b:D[inr(q)/x]\text{ind-}+_{a,b}[\text{inr}(q)/x] \doteq b : D[\text{inr}(q)/x]

Interpretación lógica: Podemos probar (producir un término de) P+QP + Q si podemos probar PP o probar QQ. Para probar algo a partir de P+QP + Q hacemos una prueba por casos. Así, ++ se comporta como la disyunción (o).

Ejemplo 2 — A×B+A×CA×(B+C)A \times B + A \times C \to A \times (B + C)

Para cualesquiera tipos A,B,CA, B, C, existe una función A×B+A×CA×(B+C)A \times B + A \times C \to A \times (B + C).

Dado x1:A×Bx_1 : A \times B, construimos (pr1x1,inl(pr2x1)):A×(B+C)(\text{pr}_1\, x_1, \text{inl}(\text{pr}_2\, x_1)) : A \times (B + C).

Dado x2:A×Cx_2 : A \times C, construimos (pr1x2,inr(pr2x2)):A×(B+C)(\text{pr}_1\, x_2, \text{inr}(\text{pr}_2\, x_2)) : A \times (B + C).

Luego por eliminación del coproducto obtenemos la función deseada.

Pares dependientes (Σ\Sigma-tipos)

Definición 3 — Σ\Sigma-tipos

Formación: Si Γ,x:PQ  type\Gamma, x : P \vdash Q \;\text{type}, entonces Γx:PQ  type\Gamma \vdash \sum_{x:P} Q \;\text{type}.

Introducción: Si Γp:P\Gamma \vdash p : P y Γq:Q[p/x]\Gamma \vdash q : Q[p/x], entonces Γpair(p,q):x:PQ\Gamma \vdash \text{pair}(p, q) : \sum_{x:P} Q.

Eliminación: Dados:

  • Γ,y:x:PQD  type\Gamma, y : \sum_{x:P} Q \vdash D \;\text{type}
  • Γ,x:P,z:Qa:D[pair(x,z)/y]\Gamma, x : P, z : Q \vdash a : D[\text{pair}(x,z)/y]

Entonces: Γ,y:x:PQindΣ(a,y):D\Gamma, y : \sum_{x:P} Q \vdash \text{ind}_\Sigma(a, y) : D

Es decir: para construir algo a partir de un par dependiente, basta decir qué hacer dado el primer componente x:Px : P y el segundo z:Qz : Q.

Computación: indΣ(a,pair(x,z))a:D[pair(x,z)/y]\text{ind}_\Sigma(a, \text{pair}(x, z)) \doteq a : D[\text{pair}(x,z)/y].

Interpretación lógica: Para probar x:PQ\sum_{x:P} Q (pensando en PP como un conjunto y QQ como un predicado sobre PP), necesitamos producir un término p:Pp : P y probar Q[p/x]Q[p/x]. Así, se comporta como el cuantificador existencial x:PQ(x)\exists_{x:P} Q(x).

Interpretación conjuntista: Los términos canónicos son pares (p,q)(p, q). Se comporta como la unión disjunta x:PQ(x)\bigsqcup_{x:P} Q(x).

Ejemplo 3 — Función de proyección

Para cualquier tipo dependiente x:PQx : P \vdash Q, existe una función de proyección π:x:PQP\pi : \sum_{x:P} Q \to P definida por π(pair(x,z))=x\pi(\text{pair}(x, z)) = x.

Ejemplo 4 — n:NVect(n)\sum_{n:\mathbb{N}} \text{Vect}(n)

Si Vect(n)\text{Vect}(n) denota el tipo de vectores de longitud nn, entonces n:NVect(n)\sum_{n:\mathbb{N}} \text{Vect}(n) es el tipo de todos los vectores (de cualquier longitud). La proyección n:NVect(n)N\sum_{n:\mathbb{N}} \text{Vect}(n) \to \mathbb{N} retorna la longitud del vector.

Los números naturales

Definición 4 — N\mathbb{N}

Formación: N  type\vdash \mathbb{N} \;\text{type}.

Introducción: 0:N\vdash 0 : \mathbb{N}, y si Γn:N\Gamma \vdash n : \mathbb{N}, entonces ΓSn:N\Gamma \vdash S\, n : \mathbb{N}.

Eliminación (inducción): Dados:

  • Γ,x:ND  type\Gamma, x : \mathbb{N} \vdash D \;\text{type}
  • Γa:D[0/x]\Gamma \vdash a : D[0/x]
  • Γ,x:N,y:Db:D[Sx/x]\Gamma, x : \mathbb{N}, y : D \vdash b : D[Sx/x]

Entonces: Γ,x:NindN(a,b,x):D\Gamma, x : \mathbb{N} \vdash \text{ind}_{\mathbb{N}}(a, b, x) : D

Es decir: para construir algo para todo natural, basta dar el caso base (00) y el paso inductivo (de xx a SxSx). Esto es el principio de inducción.

Computación:

indN(a,b,0)a:D[0/x]\text{ind}_{\mathbb{N}}(a, b, 0) \doteq a : D[0/x] indN(a,b,Sx)b:D[Sx/x]\text{ind}_{\mathbb{N}}(a, b, Sx) \doteq b : D[Sx/x]

Ejemplo 5 — add:NNN\text{add} : \mathbb{N} \to \mathbb{N} \to \mathbb{N}

Definimos la suma por recursión en el segundo argumento:

add(x,0)x\text{add}(x, 0) \doteq x add(x,Sy)S(add(x,y))\text{add}(x, Sy) \doteq S(\text{add}(x, y))

Es decir, add:=λx.λy.indN(x,λz.Sz,y)\text{add} := \lambda x.\, \lambda y.\, \text{ind}_{\mathbb{N}}(x, \lambda z.\, S z, y).

Análogamente, mult:=λx.λy.indN(0,λz.add(x,z),y)\text{mult} := \lambda x.\, \lambda y.\, \text{ind}_{\mathbb{N}}(0, \lambda z.\, \text{add}(x, z), y).

El tipo identidad

Igualdad judgmental vs proposicional

Tenemos una noción de igualdad judgmental (\doteq) que surge de las reglas de computación. Por ejemplo:

add(x,0)xadd(x,Sy)Sadd(x,y)\text{add}(x, 0) \doteq x \qquad \text{add}(x, Sy) \doteq S\,\text{add}(x, y)

Pero no todas las igualdades que queremos son judgmentales. Por ejemplo, add(0,x)x\text{add}(0, x) \doteq x no se obtiene directamente — necesitamos inducción. La igualdad proposicional internaliza la igualdad como un tipo.

Definición 5 — Tipo identidad ==

Formación: Si ΓA  type\Gamma \vdash A \;\text{type}, Γa:A\Gamma \vdash a : A y Γb:A\Gamma \vdash b : A, entonces Γa=Ab  type\Gamma \vdash a =_A b \;\text{type}.

Introducción (reflexividad): Si Γa:A\Gamma \vdash a : A, entonces Γra:a=Aa\Gamma \vdash r_a : a =_A a.

Eliminación (inducción de caminos): Dados:

  • x:A,y:A,z:x=AyD(x,y,z)  typex : A, y : A, z : x =_A y \vdash D(x, y, z) \;\text{type}
  • x:Ad:D(x,x,rx)x : A \vdash d : D(x, x, r_x)

Entonces: x:A,y:A,z:x=Ayind=(d,x,y,z):D(x,y,z)x : A, y : A, z : x =_A y \vdash \text{ind}_=(d, x, y, z) : D(x, y, z)

Es decir: para demostrar algo sobre cualquier igualdad z:x=Ayz : x =_A y, basta demostrarlo para el caso reflexivo rx:x=Axr_x : x =_A x. El resto se propaga por inducción.

Computación: x:Aind=(d,x,x,rx)d:D(x,x,rx)x : A \vdash \text{ind}_=(d, x, x, r_x) \doteq d : D(x, x, r_x).

La reflexividad (rr) convierte igualdades judgmentales en proposicionales: si ab:Aa \doteq b : A, entonces (a=Ab)(a=Aa)(a =_A b) \doteq (a =_A a), y ra:a=Abr_a : a =_A b.

Los constructores de tipos internalizan estructura

Los constructores de tipos frecuentemente internalizan nociones externas:

  • bool\text{bool}, N\mathbb{N}, \emptyset, 1\mathbb{1} internalizan nociones externas como la elección, la recursión, la falsedad y la verdad trivial.
  • El tipo universo U\mathcal{U} internaliza el juicio "A  typeA \;\text{type}".
  • El tipo identidad internaliza la igualdad judgmental ab:Aa \doteq b : A.