弄清楚类别理论

时间:2017-07-23 11:03:31

标签: coq

动机:我正在尝试研究范畴理论,同时创建一个Coq形式化的概念,我发现在我遵循的任何教科书中。为了使这种形式化尽可能简单,我想我应该使用它们的标识箭头来标识对象,因此可以将一个类别缩减为具有源映射{{1}的箭头X的集合(类,类型) },目标映射s:X->X和组合映射t:X->X,它是为product : X -> X -> option X定义的部分映射。显然,结构t f = s g应遵循各种属性。为了清楚起见,我正在阐述我在下面选择的形式化,但我认为没有必要遵循它来阅读我的问题:

(X,s,t,product)

我不知道这是多么实用,以及我需要走多远。我认为这是一个同时学习类别理论和Coq的机会。

问题:我的第一个目标是创建一个尽可能类似Record Category {A:Type} : Type := category { source : A -> A ; target : A -> A ; product: A -> A -> option A ; proof_of_ss : forall f:A, source (source f) = source f ; proof_of_ts : forall f:A, target (source f) = source f ; proof_of_tt : forall f:A, target (target f) = target f ; proof_of_st : forall f:A, source (target f) = target f ; proof_of_dom: forall f g:A, target f = source g <-> product f g <> None ; proof_of_src: forall f g h:A, product f g = Some h -> source h = source f ; proof_of_tgt: forall f g h:A, product f g = Some h -> target h = target g ; proof_of_idl: forall a f:A, a = source a -> a = target a -> a = source f -> product a f = Some f ; proof_of_idr: forall a f:A, a = source a -> a = target a -> a = target f -> product f a = Some f ; proof_of_asc: forall f g h fg gh:A, product f g = Some fg -> product g h = Some gh -> product fg h = product f gh } . 类别的“类别”。在集合理论框架中,我可能会考虑三元组Set类,其中(a,b,f)是具有域f的映射,并且范围是a的子集。考虑到这一点,我试过:

b

这样Record Arrow : Type := arrow { dom : Type ; cod : Type ; arr : dom -> cod } . 成为我可以尝试构建类别结构的基本类型。我开始将Type嵌入到Arrow中:

Arrow

允许我定义源映射和目标映射:

Definition id (a : Type) : Arrow := arrow a a (fun x => x).

然后我继续在Arrow上定义一个合成:

Definition domain (f:Arrow) : Arrow := id (dom f).
Definition codomain (f:Arrow) : Arrow := id (cod f). 

但是,当我收到错误时,此代码是非法的:

Definition compose (f g: Arrow) : option Arrow :=
    match f with
        | arrow a b f' => 
            match g with
                | arrow b' c g' =>
                    match b with 
                        | b'    => Some (arrow a c (fun x => (g' (f' x))))
                        | _     => None
                    end
            end
    end.

问题:我觉得我不会侥幸逃脱这一点,我天真地使用The term "f' x" has type "b" while it is expected to have type "b'". 会带我去某种Russel悖论,Coq不允许我这样做做。但是,为了以防万一,有没有办法在Type上定义compose

1 个答案:

答案 0 :(得分:3)

由于理论的建设性,你的编码在普通Coq中不起作用:不可能比较两组的相等性。如果您绝对想要遵循这种方法,Daniel的评论草拟了一个解决方案:您需要假设一个强大的经典原则,以便能够检查两个箭头的端点是否匹配,然后操纵相等证明以使Coq接受定义。 / p>

另一种方法是为箭头和对象分别设置类型,并使用类型依赖关系来表示箭头端点的兼容性要求。这个定义只需要三个公理,大大简化了类别的构建:

Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.

Record category : Type := Category {
  obj   : Type;
  hom   : obj -> obj -> Type;
  id    : forall {X}, hom X X;
  comp  : forall X Y Z, hom X Y -> hom Y Z -> hom X Z;
  (* Axioms *)
  idL   : forall X Y (f : hom X Y), comp id f = f;
  idR   : forall X Y (f : hom X Y), comp f id = f;
  assoc : forall X Y Z W 
                 (f : hom X Y) (g : hom Y Z) (h : hom Z W),
            comp f (comp g h) = comp (comp f g) h
}.

我们现在可以定义集合的类别,并要求Coq自动为我们证明公理。

Require Import Coq.Program.Tactics.

Program Definition Sets : category := {|
  obj := Type;
  hom X Y := X -> Y;
  id X := fun x => x;
  comp X Y Z f g := fun x => g (f x)
|}.

(由于Coq的Universe机制,这不会导致任何循环悖论:Coq理解此定义中使用的Type实际上小于用于定义category的{​​{1}}。)

由于Coq理论缺乏可扩展性,这种编码有时不方便,因为它阻止了某些公理的存在。考虑组的类别,例如,态射是与群组操作通勤的功能。这些态射的合理定义可以如下(假设有一些类型group代表组,*表示乘法而1表示中性元素。)

Record group_morphism (X Y : group) : Type := {
  mor   : X -> Y;
  mor_1 : mor 1 = 1;
  mor_m : forall x1 x2, mor (x1 * x2) = mor x1 * mor x2
}.

问题是,属性mor_1mor_m会干扰group_morphism元素的相等概念,从而使Sets的关联性和身份证明成为可能打破。有两种解决方案:

  1. 在理论中采用额外的公理,以便所需的属性仍然存在。在上面的例子中,您需要证明不相关:

    proof_irrelevance:forall(P:Prop)(p q:P),p = q。

  2. 更改类别公理,使标识有效,直至某个特定于该类别的等价关系,而不是普通的Coq相等。例如,此方法遵循here