范畴论对学习函数式编程有用吗?


118

我正在学习Haskell,并且对语言很着迷。但是我没有认真的数学或CS背景。但是我是一位经验丰富的软件程序员。

我想学习类别理论,以便在Haskell变得更好。

我应该学习类别理论中的哪些主题,以便为理解Haskell提供良好的基础?



1
我感谢您区分编程和CS。
jmite

4
“学习类别理论在Haskell中变得更好”有点像“学习物理学在网球中变得更好”
user26756 2015年

Answers:


115

“理论计算机科学”站点先前答案中,我说过类别理论是类型理论的“基础”。在这里,我想说点更强烈的话。 范畴理论是类型理论。相反,类型理论就是范畴理论。让我扩展这些观点。

范畴论就是类型论

在任何类型的正式语言,即使在使用不正规的表示正常的数学,我们最终类型声明函数。书面上的隐含想法是,和是一些称为“类型”的事物,而是从一种类型到另一种类型的“功能”。范畴理论是这类“类型”和“功能”的代数理论。(正式地,范畴论称它们为“对象”和“态射”,以避免踩踏传统主义者的设定论脚趾,但是越来越多的我看到,范畴论者对风吹牛打,并使用更直观的术语:“类型“和”功能。但是,f:ABABf

从高中开始,我们都已经接受了集合论。因此,我们习惯于将诸如和之类的类型视为集合,而将诸如类的视为集合理论映射。如果您从未那样想过它们,那么您的状态就很好。您已经摆脱了集合论理论的洗脑。范畴理论说,类型很多,功能也很多。因此,将类型作为集合的想法是有限的。相反,范畴论以代数方式公理化类型和功能。基本上,这就是范畴论。类型和功能的理论。它确实变得非常复杂,涉及较高的抽象水平。但是,如果您可以学习它,您将对类型和功能有深刻的了解。ABf

类型理论就是范畴理论

“类型理论”是指基于严格的术语形成规则的任何类型的形式化语言,这些规则可确保对所有类型进行检查。事实证明,每当我们使用这种语言工作时,我们都在类别理论结构中工作。即使我们使用集合理论符号并从集合理论上进行思考,我们最终仍会写出绝对有意义的东西。这是一个了不起的事实

从历史上看,达娜·斯科特(Dana Scott)可能是第一个意识到这一点的人。他致力于基于类型化(和非类型化)lambda演算的编程语言语义模型的产生。传统的集合论模型不足以实现此目的,因为编程语言涉及不受限制的递归,而集合论缺乏这种递归。斯科特(Scott)发明了一系列语义模型,这些语义模型捕获了编程现象,并意识到类型化的lambda演算正好代表了一个称为笛卡尔封闭类别的类别。有许多笛卡尔封闭类别不是“集合论”的。但是类型化lambda演算同样适用于所有这些。斯科特(Scott)撰写了一篇不错的文章,名为“ 有关lambda微积分的理论解释发生了什么,部分内容似乎可以在网络上获得。原始文章发表在名为“致HB Curry:组合逻辑论文,Lambda微积分和形式主义的论文”中,Academic Press,1980。Berry和Curien可能是独立地实现了相同的实现,他们定义了一种分类抽象机(CAM),以在实现功能语言时使用这些思想,它们所实现的语言称为“ CAML”,它是Microsoft F#的基础框架。

标准类型的构造函数,例如,,等都是函子。这意味着它们不仅将类型映射到类型,而且将类型之间的功能映射到类型之间的功能。 多态函数保留了函子动作产生的所有此类函数。范畴论是1950年代由Eilenberg和MacLane发明的×List正是为了规范多态函数的概念。他们称它们为“自然转换”,“自然”,因为它们是您可以使用类型变量以类型正确的方式编写的唯一代码。因此,也许有人会说,甚至在编程语言出现之前,范畴理论就是为了将多态编程语言形式化而精确发明的!

集合理论的传统主义者不了解使用集合理论符号的表面上正在发生的函子和自然变换。但是,只要他忠实地使用类型系统,他实际上就是在进行分类构造而没有意识到它们。


总而言之,范畴论是类型和函数的典型数学理论。因此,所有程序员,特别是函数式程序员,都可以从学习一些类别理论中受益。不幸的是,似乎没有专门针对程序员的有关范畴论的教科书。“计算机科学的类别理论”书籍通常针对理论计算机科学的学生/研究人员。本杰明·皮尔斯(Benjamin Pierce)所著的《计算机科学家的基本范畴论》也许是其中最易读的书。

但是,网络上有很多资源是针对程序员的。该Haskellwiki页面可以是一个很好的起点。在Midlands研究生院,我们举办了类别理论讲座(其中包括)。格雷厄姆·赫顿(Graham Hutton)的课程被列为“入门”课程,而我的课程被列为“高级”课程。但是它们两者基本上涵盖了相同的内容,而且深度不同。查默斯大学(University of Chalmers)的网页上有来自世界各地的书籍和讲义,内容丰富。从程序员的角度来看,热情洋溢的“ sigfpe”博客网站还提供了许多很好的直觉。

您想学习的基本主题是:

  • 类别的定义,以及类别的一些示例
  • 函子及其示例
  • 自然转变及其例子
  • 产品,副产品和指数(功能空间),初始和最终对象的定义。
  • 附加语
  • 单子,代数和克莱斯里类别

我在Midlands研究生院演讲笔记涵盖了所有这些主题,除了最后一个主题(单子)。这些天,还有很多其他资源可用于monad。因此,这不是很大的损失。

您知道的数学越多,学习类别理论就越容易。由于类别理论是数学结构的一般理论,因此了解一些示例以了解定义的含义将很有帮助。(当我学习类别理论时,我不得不使用我的编程语言语义知识来编写自己的示例,因为标准教科书仅包含数学示例,而我对此一无所知。)然后是兰贝克的精彩著作斯科特(Scott)称“ 分类逻辑导论 ”。“将类别理论与类型系统相关联(它们称为“逻辑”)。现在,即使不了解很多示例,也可以通过将类别理论与类型系统相关联来理解类别理论。我上面提到的许多资源都使用了这一点。解释类别理论的方法。


3
@UdayReddy我非常不同意您对类型理论和类型理论的认同。现代类型理论必然涉及并发过程的类型,例如会话类型的理论传统。据我所知,对这种打字系统没有绝对的了解。
2013年

6
@MartinBerger我认为您对“类型论”的解释有点狭窄。但是,我同意对会话类型进行正确的类型理论和类别理论的理解目前是一个很好的研究挑战,我打算花时间在上面。
Uday Reddy

2
@MartinBerger。为了了解类别理论如何应用于更丰富的计算概念,我邀请您研究一下类别理论如何应用于命令式编程理论和游戏语义(同样可以很好地编码命令式计算)。因此,我不认为函数式编程会垄断类别理论。
Uday Reddy 2013年

1
@nicolas,纤维化是建立索引类别的一种方法,该模型对依赖类型进行建模。纤维化也可以看作是程序逻辑的一种非常通用的形式,其中表示将满意值映射到满意值。f:PQfPQ
Uday Reddy

2
“不幸的是,似乎没有专门针对程序员的有关范畴论的教科书。” 这样的“教科书”现在或多或少地存在于Bartosz Milewski的“程序员分类理论”中。Bartosz还创建了一个附带的讲座系列
alx9r

30

我将尝试使其简短而有趣。Haskell程序与某些类别的类别之间存在非正式的往来关系,可以通过一些工作使其更加正式。该对应关系被称为Curry-Howard-Lambek对应关系,并且与以下内容相关:

  1. 具有类别对象的Haskell 类型
  2. 术语类型的与态射(注意类似的符号)AB f:AB
  3. 具有初始对象的代数数据类型
  4. 具有函子的类型构造函数
  5. 等等

清单还在不断增加,但关键一点是,您可以在类别理论中定义诸如monads代数之类的东西,并提出对数学家有用但在Haskell编程实践中普遍存在的概念。

我不确定要推荐哪本书,因为我还没有找到关于计算机科学家类别的完全令人满意的入门书。您可以尝试Asperti和Longo的类别,类型和结构。这个想法是学习基本的附加概念,然后尝试阅读一些出色的博客来尝试理解这些概念。


1
“提出对数学家来说既有用又在Haskell编程实践中普遍存在的概念” –您可以举一个例子,还是需要太多的先验知识?
拉斐尔

7
@Raphael:单子。箭头。代数 Coalgebras。
戴夫·克拉克

6
函子,对偶,该Kleisli类,米田引理...
科迪

4
封闭类。咖喱。
戴夫·克拉克

2
“软件工程师类别理论导论”,cs.toronto.edu
〜sme / presentations /

29

回应@AJed的建议,我建议你转述一下

I want to learn category theory so I can become better at Haskell.

在其头上:根据您的编程直觉来学习Haskell。一旦成为FP专家,可能会更容易理解类别理论(如果您仍然在意的话)。

对于具有广泛数学知识(组,环,模块,向量空间,拓扑等)的人员而言,类别理论很简单。缺乏这种背景,范畴理论几乎是不可理解的。范畴论的美丽在于它统一了许多看似无关的事物(例如,健忘函子的左伴随包括自由群,通用包络代数,Stone-Cech压缩,群的阿贝尔化等),从而降低了复杂性。但是,如果您不熟悉类别理论所结合的多个示例,则类别理论只是增加了一层复杂性,使您的生活更加艰难。

以我的经验,在已有知识的基础上进行学习会更容易。作为软件开发人员,您对编程了解很多,并且Haskell编程与其他编程没有什么不同,因此我的建议是从实用的编程角度着手处理Haskell,而忽略类别理论。Haskell中的类别理论(例如对monad的一些支持)有点使程序员更容易掌握,而无需绕过类别理论。毕竟,monad仅仅是广义组合(并且您已经在编程实践中使用过monad -尽管您不知道这样做了),并且Haskell并不真正支持monad的实物,因为它不执行monadic法则。


7
不,说实话真的哈斯克尔从大多数其他编程语言不同,到如此地步,让过去的成见往往是最大的挑战。经验丰富的软件开发人员似乎比从未编程的人遇到更多的麻烦。
CA McCann 2013年

5
@CAMcCann我同意某些经验丰富的程序从Java或C#迁移到Haskell似乎很难,但是我不认为这是因为Haskell根本不同。我认为部分原因是因为它似乎有所不同。您需要学习类别理论以欣赏Haskell的想法可能阻止了很多有经验的软件开发人员掌握Haskell。(参见为什么F#没有monad。)我当然很难想到许多Haskell功能,它们在其他语言中也没有相似之处。
Martin Berger 2013年

5
了解类别理论可能会有所帮助,但并不是全部,而且学习肯定比学习Haskell困难得多。与大多数语言(纯度,非严格评估,类型系统)相比,存在根本的区别,并且删除所有CT术语并不会使它们更加熟悉。另一方面,学习Haskell会激励一些人学习一些CT,因为借来的想法很有用。F#的有限类型系统和对现有术语的完美避免是缺陷而不是功能。
CA McCann 2013年

1
除了Scala之外,我不知道其他语言具有与Haskell相当的类型系统。从经验观察,纯度不能立即掌握,非严格的评估(您跳过的评估)就更加困难。最后,我一个正在工作的程序员,并且我怀疑该领域的任何人都会被name吓倒。软件开发行业已经充满了不透明的行话。同样,F#的类型系统不能直接表达单子-计算表达式不是一流的,这大大限制了它们的使用。
CA McCann

2
CBN在概念上也很容易,例如,与thunk相似,这是大多数工作程序员以前都会使用的概念。纯度是每个工作程序员都可以理解的东西。Haskell在英国用于本科教育。当我的学生问我如何进入函数式编程时,我通常建议先学习Haskell,但学生和它的发起人一样被它的声誉所吓倒。我相信主要原因是Haskell与类别理论的联系。
Martin Berger

13

一个简短的答案:否[但这只是一个意见]

不要去类别理论或任何其他理论领域来成为Haskell的佼佼者。学习函数式编程技术,例如尾部递归,映射,缩小和其他。尽可能多地阅读代码。实施尽可能多的想法。如果有问题,请阅读并阅读。

如果您想获得学习Haskell和其他函数式编程范例的良好理论参考,请查看:通过Lambda微积分进行函数式编程简介,Greg Michaelson(在线提供)。...还有其他类似的书籍。


1
我对此感到震惊,因为由于懒惰,“尾递归”对于在Haskell中进行编程通常并不重要。但是,“边做边学”几乎总是好的建议。
丹·伯顿

@ DanBurton ..有趣的观察。那就说,而不是Haskell,学习erlang或scheme :)。[我不是Haskell的专家,我选了它是因为听起来很酷]
AJed


0

范畴论是数学的一个非常复杂的分支,掌握它可以使您以前的大部分学习成为同一抽象对象的实例,从而使它们统一。因此,它非常有用且非常直观。但是它涉及面很广,而且您会发现自己处于许多新概念中,甚至不知道哪一个适合您的需求以及应该跳过哪个。因此,您有目的的方法需要在概念之间进行选择,否则掌握该方法将不可避免地需要很长时间,并且实际上不是自学领域。

顺便说一句,我建议您为来到这里的目的提供一个很好的起点。


这并不能真正回答问题:对学习函数式编程有用吗?范畴论中的哪些主题对Haskell有用?
David Richerby'3
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.