Formalizando a teoria básica das categorias em Coq

7

Sou totalmente iniciante na Coq e estou tentando implementar algumas coisas da teoria das categorias como um exercício.

Naveguei um pouco entre os repositórios git das muitas implementações disponíveis (HoTT, companhia de Awodey's Coq etc.), parece que todo projeto implementa algo assim

Record Category : Type :=
  mkCategory{
    ob : Type ;
    mor : ob -> ob -> Type ;
    compose : forall x y z : ob,
                mor x y -> mor y z -> mor x z ;
    identity : forall x, mor x x ;
    (* ... axioms ... *)
  }.

É meio natural, considerando a maioria das definições de categorias em livros modernos. No entanto, acho que seria mais fácil implementá-lo internamente (se não estiver enganado, era a definição comum na época de Grothendieck):

Definição. Uma categoria são os dados de

  • um conjunto / classe Ob de objetos
  • um conjunto / classe de morfismos,Mor
  • funções , e ( representa fonte , por alvo , e para identidade )s,t:MorObi:ObMorsti
  • uma função cujo domínio é o produto de fibra de:Mor×s,tMorMor
    MorsObtMor

satisfazendo alguns axiomas ...

A vantagem dessa definição é que ela generaliza diretamente, substituindo "conjunto / classe" por "objetos de alguma categoria" e "funções" por "morfismos dessa categoria", levando ao conceito de categoria interna . (Então você pode falar de categorias topológicas / diferenciais ou categorias dentro de um topos, etc.)

Meu problema é formalizar o produto de fibra na Coq. Minha primeira tentativa seria fazer algo como

Record Category : Type :=
  mkCategory{
    ob : Type ;
    mor : Type ;
    s : mor -> ob ;
    t : mor -> ob ;
    compose : mor -> mor -> option mor ;
    i : ob -> mor ;

    adequacy : forall f g : mor, 
                 (exists h, (compose f g) = (some h)) -> (t f = s g) ;
    (* ... axioms ... *)
  }.

Mas acho que isso poderia levar a algum código mais tarde. Por exemplo, seria difícil ler composições encadeadas.

Existe um projeto com uma implementação baseada na definição interna? Existe uma maneira rápida de definir o produto de fibra que preciso no Coq?

Editar. A propósito, eu vejo muitos

Ob :> Type

em vez de

Ob : Type

Qual é o significado do ">" extra? Pelo documento, parece que é algum tipo de coerção . O que exatamente isso significa?

Pece
fonte
Apenas para responder rapidamente à pergunta extra, uma coerção é um dispositivo que permite que um tipo seja tratado de alguma maneira como outro tipo, isso é um bom exemplo. Eu não vi essa sintaxe exata antes, no entanto, portanto, deve ser um tipo de coerção "especial" (provavelmente trivial, ou seja, qualquer coisa pode ser Ob)?
Luke Mathieson
Veja também coq.inria.fr/refman/Reference-Manual021.html (embora isso pode apenas turvar as águas)
Luke Mathieson
Apenas como uma observação, você deve saber que os tipos dependentes estão muito disponíveis no coq e capturam exatamente essa noção de produto de fibra! Uma maneira natural para escrever este seria ter mor dependem em se t, por exemplo mor: forall s t : ob, Type.
Cody
@ Cody Não é esta a primeira abordagem (que eu não quero)? O símbolos e tnão deve representar objetos, mas a origem e o destino da função . Imagine gráficos em vez de categorias: a primeira abordagem define um gráfico como um conjunto de vértices e para cada par (classificado) um conjunto de arestas, enquanto a segunda abordagem define um gráfico como dois conjuntos V e E (V para os vértices, E para todos os egdes) com duas aplicaçõess,t:EVdesignando a origem e o destino de cada aresta.
Pece 15/05
Oh certo, desculpe, eu perdi seu primeiro ponto. Parece, no entanto, que você está argumentando contra o próprio argumento que está tentando fazer: que as definições "internas" são mais naturais, mas, como você está observando, é mais difícil anotá-las ...
cody

Respostas:

4

Uma maneira natural de escrever o que você quer é restringir o tipo de composição apenas aos morfismos "composíveis":

compose:f g:mor,t(f)=s(g)mor

adicionando, é claro, as condições:

s(compose f g e)=s(f)
t(compose f g e)=t(g)

Isso funciona, pois agora permite apenas funções de composição comprovadamente composíveis. Isso corresponde aproximadamente ao produto com fibra na teoria das categorias que você estava mencionando.

No entanto, é um pouco estranho, pois adiciona obrigações de prova a todas as aplicações do composeque podem rapidamente se tornar incontroláveis ​​(até mesmo expressar a associatividade é difícil!). Também impede um pouco a adição da notação , uma vez que leva 3 argumentos.=composecompose

Esse é um problema um tanto comum na teoria dos tipos, que resulta da tensão fundamental de ter funções parciais em uma linguagem total.

Outra solução menos elegante é definir composição a ser definida em todos os lugares : e proteger todos os teoremas que envolvem composição com boa definição condições:

compose:mormormor

umassoc:fgh:mor,t(f)=s(g)t(g)=s(h)compose f (compose g h)=compose (compose f g) h
Isso significa essencialmente:

composeé definido em qualquer lugar, mas a definição é significativa apenas se aplicada a morfismos composíveis.

Essa abordagem também apresenta desvantagens, principalmente a quantidade gigantesca de obrigações de prova que seguem todas as aplicações dos axiomas básicos.

Receio que você tenha que escolher seu veneno nesse caso, ou inventar uma maneira inteligente de fazer melhor ...

cody
fonte
Você também pode precisar adicionar uma hipótese irrelevância prova: certamente o resultado de compor fe gnão deve depender da prova eque t(f)=s(g)...
Gallais
Eu acho que, embora esse problema não deva surgir na maioria dos contextos em que há apenas uma prova de t(f) = s(g)estar por aí (por exemplo, se a igualdade em objetos é decidível).
cody
0

Depois de alguma luta, acho que a melhor maneira de fazer o que eu quero é realmente codificar o produto de fibra do tipo através de sua propriedade universal.

Ele segue esse tipo de linha:

Class FiberProduct (A B C : Type) (f : A -> C) (g : B -> C) : Type :=
  {
    FiberProductCarrier : Type ;
    FiberProductProj_1 : FiberProductCarrier -> A ;
    FiberProductProj_2 : FiberProductCarrier -> B ;
    FiberProductCommutativity :
      forall x : FiberProductCarrier,
        f (FiberProductProj_1 x) = g (FiberProductProj_2 x) ;
    FiberProductUniversalExistence :
      forall X : Type, forall (p_1 : X -> A) (p_2 : X -> B),
        (forall x : X, f (p_1 x) = g (p_2 x)) ->
        (exists h : X -> FiberProductCarrier,
           (forall x : X, FiberProductProj_1 (h x) = p_1 x
                          /\ FiberProductProj_2 (h x) = p_2 x)) ;
    FiberProductUniversalUniqueness :
      forall X : Type, forall (p_1 : X -> A) (p_2 : X -> B),
        (forall x : X, f (p_1 x) = g (p_2 x)) ->
        (forall k l : X -> FiberProductCarrier,
           (forall x : X, FiberProductProj_1 (k x) = p_1 x
                          /\ FiberProductProj_2 (k x) = p_2 x
                          /\ FiberProductProj_1 (l x) = p_1 x
                          /\ FiberProductProj_2 (l x) = p_2 x)
           -> k = l)
  }.

Então a versão interna da noção de categoria é dada por:

Class InternalCategory : Type :=
  {
    ob : Type ;
    mor : Type ;
    s : mor -> ob ;
    t : mor -> ob ;
    i : ob -> mor ;
    comp_domain : FiberProduct mor mor ob s t ;
    comp : FiberProductCarrier  -> mor  ;
    (* axioms *)
    asso :
      forall fg_h f_gh : FiberProductCarrier,
        (exists fg gh : FiberProductCarrier,
           FiberProductProj_1 fg_h = comp fg /\
           FiberProductProj_2 f_gh = comp gh /\
           FiberProductProj_1 fg = FiberProductProj_1 f_gh /\
           FiberProductProj_2 fg = FiberProductProj_1 gh /\
           FiberProductProj_2 gh = FiberProductProj_2 fg_h) ->
        (comp fg_h = comp f_gh) ;
    id_right :
      forall fid : FiberProductCarrier,
      forall f : mor,
        (FiberProductProj_1 fid = f) ->
        (exists x : ob, FiberProductProj_2 fid = i x) ->
        (comp fid = f) ;
    id_left :
      forall idf : FiberProductCarrier,
      forall f : mor,
        (FiberProductProj_2 idf = f) ->
        (exists x : ob, FiberProductProj_1 idf = i x) ->
        (comp idf = f) ;
    id_s :
      forall x, s (i x) = x ;
    id_t :
      forall x, t (i x) = x          
  }.
Pece
fonte