当前位置: 首页 > news >正文

译米田引理

上一篇:可表函子

原文地址:https://bartoszmilewski.com/2...

范畴论中的大多数构造都是其他具体数学领域的泛化。诸如积、余积、幺半群和指数等等,早都在范畴论以前被了解了。在不同的数学分支中,它们也许有不同的名字。集合论中的笛卡儿积,序数理论的下确界,逻辑中的连词——他们都是范畴积这样一个抽象观点的具体例子。

但作为一个有关范畴的一般陈述,米田引理却完全不同。它少有或没有其他数学分支中的先例。有些人说与它最靠近的类比是群论中的凯莱定理(每个群都同构于某个集合的置换群)。

米田引理的设定是一个任意范畴C和一个从CSet的函子F。我们已经在之前的部分看到过一些指向Set的函子是可表的,也就是同构于一个hom函子。米田引理是说所有指向Set的函子都能通过自然变换从hom函子获得,而且米田引理精确的列举了所有这样的变换。

在讨论自然变换的时候,我曾说过自然性条件可能非常严格。当你定义一个自然变换在一个对象上的分量的时候,自然性得强到可以把这个分量“搬”到另一个对象的分量上,而这另一个对象和原对象有态射连接。源范畴和靶范畴的箭头越多,你要搬运自然变换的分量的限制就越多。Set碰巧就是一个箭头非常多的范畴。

米田引理告诉我们,一个hom函子和任意其他函子F间的自然变换被它的单个分量在一个点的取值完全决定!这个自然变换剩下的部分仅仅遵循自然性条件。

所以让我们再来看看米田引理所用到的两个函子间的自然性条件吧。第一个函子是hom函子。它把C的任意对象x映为态射的集合C(a, x)——aC中的一个固定对象。我们也已经看到过它把任意xy的态射f映为C(a, f)

第二个函子是任意指向Set的函子F

让我们把这两个函子间的自然变换称作α。因为我们是在Set中操作,像α_xα_y这样的自然变换分量就只是常规的集合间的函数:

α_x :: C(a, x) -> F x
a_y :: C(a, y) -> F y

yoneda1

而因为这些都是函数,我们就可以看看它们在具体点上的值。但集合C(a, x)里的点是什么?这就是关键的观察了:集合C(a, x)的每个点也是个从ax的态射h

所以α的自然性四方图:

α_y ∘ C(a, f) = F f ∘ α_x

逐点作用在h上时,就变成了:

α_y (C(a, f) h) = F f (α_x h)

你可以从之前的部分回想起hom函子C(a, -)在态射f上的行为就被定义为前复合:

C(a, f) h = f ∘ h

这就导出了:

α_y (f ∘ h) = (F f) (α_x h)

这个条件究竟有多强看看让x等于a的情形就知道了。

yoneda2

这时h变成了一个从aa的态射。我们知道至少存在一个这样的态射,h = id_a。让我们把它带入:

α_y f = (F f) (α_a id_a)

注意发生了什么:左边是α_yC(a, y)的任意元素f上的作用。并且它由α_aid_a的这单单一个值所完全决定。我们可以任意选取这样的值,这样就生成了一个自然变换。因为α_a的值落在集合F a中,所以F a的任意点都定义了某个α

反过来,给定任意从C(a, -)F的自然变换α,你可以计算出它在id_a的值,从而得到一个F a的点。

这样我们就证明了米田引理:

C(a, -)F的自然变换和 F a的元素是一一对应的。

换句话说,

Nat(C(a, -), F) ≅ F a

或者说,如果我们用记号[C, Set]表示CSet间的函子范畴,自然变换的集合就只是这个范畴的一个hom集了,并且我们可以写成:

[C, Set](C(a, -), F) ≅ F a

这个对应实际上是个自然同构,我之后会解释这是怎么回事。

现在让我们试着直观感受下这个结果。最让人惊讶的莫过于整个自然变换从一个凝结点开始结晶了:凝结点就是自然变换作用于id_a的值。在自然性条件下,自然变换从该点向外延伸。它覆盖了Set中所有C的像。所以我们首先考虑下CC(a, -)的像。

让我们从a自己的像开始。在hom函子C(a, -)下,a被映为集合C(a, a)。另一方面,在函子F下,它被映为集合F a。自然变换的分量α_a是某个从C(a, a)F a的函数。让我们仅仅关注C(a, a)的一个点,也就是那个对应于态射id_a的点。为了强调它只是集合中的一个点,我们把它叫做p。分量α_a应当把p映为F a的某个点q。我将给你证明任意q的选择会导出唯一的自然变换。

yoneda3

第一个断言是q的选择会唯一决定函数α_a的剩余部分。真的,让我们任选C(a, a)的另一个点p',它对应某个从aa的态射g。接下来就是米田引理的魔法时刻了:g可以被看成集合C(a, a)的某个点p',同时它还对应着两个集合间的函数。确实,在hom函子下,态射g被映为函数C(a, g);在F下它被映为F g

yoneda4

现在我们考虑C(a, g)在我们原始的p上的作用,p就是对应着id_a的那个家伙。这定义成前复合,g∘id_a,它就是g,也对应着我们的点p'。所以态射g被映为了一个把p映为p'的函数,而p'就是g。我们整整兜了一圈!

现在考虑F gq上的作用。这会是某个q'F a的一个点。为了补全自然四方图,p'必须在α_a下被映为q'。我们选取了任意的p'(也就是任意的g)然后得到了它在α_a下的像,因此函数α_a完全确定了。

第二个断言是对于C中的任意和a有连接的对象xα_x会被唯一决定。原因是类似地,只不过现在我们多了两个集合C(a, x)F x,并且从ax的态射g在hom函子下被映为了:

C(a, g) :: C(a, a) -> C(a, x)

而在F下被映为:

F g :: F a -> F x

同样地,C(a, g)在我们的p上的作用由前复合给出:g ∘ id_a,这对应了C(a, x)的一个点p'。自然性决定了α_x作用在p'上的值会是:

q' = (F g) q

因为p'是任取的,所以因此整个α_x被确定了。

yoneda5

如果C中有和a没有连接的对象呢?它们在C(a, -)下会统统被映为一个集合——空集。回忆一下,空集是集合范畴的初始对象。这意味着从它到任意其他集合只有一个函数。我们曾把它叫做absurd。所以同样地,我们仍然没有选择自然变换分量的余地:它只能是absurd

一个理解米田引理的方法是把指向Set的函子间的自然变换们就看作一堆函数族,而函数通常是会损失信息的。一个函数可能会坍缩信息,并且它可能只覆盖上域的一部分。那些仅有的不会损失信息的函数就是那些可逆函数——同构。因此呢,最好的保持结构的指向Set的函子就是那些可表的。它们或者是hom函子,或者和hom函子自然同构。任何其他从hom函子得到函子F的过程都损失了信息。这样的变换可能不止损失了信息,它也可能只覆盖了函子FSet上像的一小部分。

Hasekll中的米田引理

我们已经遇到过Haskell中伪装成reader函子的hom函子了:

type Reader a x = a -> x

reader通过前复合映射态射(这里就是函数):

instance Functor (Reader a) where
    map f h = f . h

米田引理告诉我们reader函子可以被自然地映为其他函子。

一个自然变换就是一个多态函数。所以给定一个函子F,我们就有一个由reader函子到它的映射:

alpha :: forall x . (a -> x) -> F x

通常来说,forall是可以省略的,但我想把它明确地写出来以强调自然变换的参数化多态性质。

米田引理告诉我们这些自然变换和F a的元素们一一对应:

forall x . (a -> x) -> F x ≅ F a

这个等价的右边一般被看作一个数据结构。还记得把函子看作容器的推广的解释吗?F a是一个a的容器。但左边是个以一个函数作为参数的多态函数。米田引理说这两种表达等价——它们包含了同样地信息。

另一个说法是:给我一个这种类型的多态函数:

alpha :: forall x . (a -> x) -> F x

我就能得到一个a的容器。技巧就是我们之前在米田引理的证明中用到过的:我们用id调用这个函数就得到了F a的一个元素:

alpha id :: F a

反过来也对。给定一个F a的值:

fa :: F a

就可以定义一个恰当类型的多态函数:

alpha h = fmap h fa

你可以轻易地在这两种表达间来回切换。

多种表达的好处是其中一种可能比另一种易于复合,或者某些应用中一种可能比另一种更有效率。

这个原理地最简单示例就是经常用在编译器构造中地编码转换:延继传递风格或CPS。这是米田引理在恒等函子上最简单的应用。把F换成恒等函子就得到了:

forall x . (a -> r) -> r ≅ a
关于延继传递风格(Continuation-passing style,CPS),网上的叫法不一,但大多把continuation译为“延续”,我觉得不妥。因为在CPS中,把需要传递的类型为 (a -> r)的函数就叫the continuation。称呼一个函数为延续毕竟有些口语,不符合数学的习惯,于是我就自作主张的译为“延继”了。译者注。

这个公式的解释是任意类型a可以被代替成一个以一个a的“处理器”为参数的函数。一个处理器就是一个接受a为参数并执行后续计算的函数——延继。(类型r通常封装成某种类型的状态码)

这种编程风格在用户界面编程、异步系统和并行编程中都非常普遍。CPS的缺点是它设计了控制的反向。开发端和用户(处理器端)的代码是分离的,这就不易于复合。谁要是做过些一般的web编程,就会了解交互式状态处理程序的面条代码的噩梦了。就像我们之后会看到的,如果函子和单子使用得当,就能存储一些CPS的可复合性质了。

逆米田引理

就像以往一样,我们通过将箭头反向得到了额外的构造。米田引理可以应用到反范畴C_op从而给出逆变函子间的映射。

等价的说,我们通过固定hom函子的靶对象而不是源对象得到了逆米田引理。我们得到从CSet的逆变hom函子:C(-, a)。米田引理的这个逆变版本构建了这个函子到其他任意逆变函子F间的自然变换与集合F a的元素之间的一一对应:

Nat(C(-, a), F) ≅ F a

这儿是逆米田引理Haskell版本:

forall x . (x -> a) -> F x ≅ F a

注意,有些文献中把这个逆变版本就叫米田引理。

挑战

  1. 证明这两个在Haskell中组成米田同构的函子phipsi互逆。

    phi :: (forall x . (a -> x) -> F x) -> F a
    phi alpha = alpha id
    psi :: F a -> (forall x . (a -> x) -> F x)
    psi fa h = fmap h fa
  2. 所谓离散范畴就是指有一些对象,但除了恒等态射外没有别的态射的范畴。米田引理是如何处理从这个范畴出发的函子的?
  3. unit的列表[()]除了它的长度不包含任何其他信息。所以,作为一个数据类型,它可以视为整数的一个编码方式。空列表代表0,单例列表[()](这是一个值,并不是类型)表示1,等等。请使用米田引理构造出这个列表函子的另一种表示。

参考文献

  1. Catsters video

致谢

感谢Gershom Bazerman检查我的数学和逻辑,以及André van Meulebrouck在整个系列中的编辑上的帮助。

下一篇:米田嵌入

相关文章:

  • Docker中mysql大小写敏感配置不起作用的问题排查
  • 一份运维监控的终极秘籍!监控不到位,宕机两行泪
  • leetcode386. Lexicographical Numbers
  • 30秒的PHP代码片段(1)数组 - Array
  • docker-2-安装
  • 使用 QuickBI 搭建酷炫可视化分析
  • 使用rsyslog收集日志
  • 日剧·日综资源集合(建议收藏)
  • 码农张的Bug人生 - 见面之礼
  • Java求两个数平均值
  • 01炼数成金TensorFlow基本概念
  • Spark调度模块
  • 封装dialog弹窗
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • CentOS6 Shell脚本/bin/bash^M: bad interpreter错误解决方法
  • FastReport在线报表设计器工作原理
  • Java深入 - 深入理解Java集合
  • js如何打印object对象
  • laravel 用artisan创建自己的模板
  • Redis学习笔记 - pipline(流水线、管道)
  • select2 取值 遍历 设置默认值
  • storm drpc实例
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 来,膜拜下android roadmap,强大的执行力
  • 码农张的Bug人生 - 见面之礼
  • 前端相关框架总和
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 在weex里面使用chart图表
  • 正则表达式小结
  • HanLP分词命名实体提取详解
  • 回归生活:清理微信公众号
  • 我们雇佣了一只大猴子...
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (离散数学)逻辑连接词
  • (十六)串口UART
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转)Oracle 9i 数据库设计指引全集(1)
  • 、写入Shellcode到注册表上线
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .net 后台导出excel ,word
  • .NET 中使用 Mutex 进行跨越进程边界的同步