范畴论基本概念

如果你是第一次听说范畴论(category theory),看到这高大上的名字估计心里就会一咯噔,到底数学威力巨大,光是高等数学就能让很多人噩梦连连。和搞编程的一样,数学家喜欢将问题不断加以抽象从而将本质问题抽取出来加以论证解决,范畴论就是这样一门以抽象的方法来处理数学概念的学科,主要用于研究一些数学结构之间的关系及联系。

在范畴论里,一个范畴(category)指的是这样一个好东西,它由三部分组成:

  1. 一系列的对象(object).
  2. 一系列的态射(morphism).
  3. 一个组合(composition)操作符,用点(.)表示,用于将态射进行组合。

一个对象可以看成是一类东西,数学上的群,环,甚至简单的有理数,无理数等都可以归为一个对象,对应到编程语言里,可以理解为一个类型,比如说整型,布尔型,类型事实上可以看成是值的集合,例如整型就是由 0,1,2...等组成的,因此范畴论里的对象简单理解就可以看成是值(value)的集合。

一个态射指的是一种映射关系,简单理解,态射的作用就是把一个对象 A 里的值 va 映射为 另一个对象 B 里的值 vb,这和代数里的映射概念是很相近的,因此也有单射,满射等区分。态射的存在反映了对象内部的结构,这是范畴论用来研究对象的主要手法:对象内部的结构特性是通过与别的对象的关系反映出来的,动静是相对的,范畴论通过研究关系来达到探知对象的内部结构的目的。

组合操作符的作用是将两个态射进行组合,例如,假设存在态射 f: A -> B, g: B -> C, 则 g.f : A -> C.

看!好像没有想象中的复杂!一个结构要想成为一个范畴, 除了必须包含上述三样东西,它还要满足以下三个限制:

  1. 态射要满足结合律,即 f.(g.h) = (f.g).h。

  2. 态射在这个结构必须是封闭的,也就是,如果存在态射 f, g,则必然存在 h = f.g。

  3. 对结构中的每一个对象 A, 必须存在一个单位态射 Ia: A -> A, 对于单位态射,显然,对任意其它态射 f, f.I = f。

讲完了!范畴论就这么点东西!-- 当然是不可能的,但暂时来说,知道这些就已经很足够了。

Haskell 中的范畴

在 Haskell 中存在着这样一个唯一的范畴,名字称为 Hask, 这个 Hask 满足前面关于范畴的全部约定,因此是范畴论里一个纯正的“范畴":

  1. 对象就是 Haskell 里的所有类型,记得类型是一个集合。

  2. 态射就是编程语言里的一般函数(function),如: func :: Int -> Bool,将对象 int 映射为 对象 bool。

  3. 态射的组合就是函数的组合,在 Haskell 里,函数也是通过点号(.)进行组合的。

另外三个约束条件很容易证明也是满足,因此整个 Haskell 从数学的角度上看它就是一个范畴,这个角度的理解是很深刻的,这样一来传统意义上诸如语法,类型,函数等语言特性其实都只是这个内在本质的外在表现而已。

函子

前面对范畴的介绍反映了范畴内部各个对象之间的联系与相互作用,在范畴论里另外研究的重点是范畴与范畴之间的关系,就正如对象与对象之间有态射一样,范畴与范畴之间也存在某些映射,从而可以将一个范畴映射为另一个范畴,这种映射在范畴论中叫作函子(functor),具体来说,对于给定的两个范畴 A 和 B, 函子的作用有两个:

  1. 将范畴 A 中的对象映射到范畴 B 中的对象。

  2. 将范畴 A 中的态射映射到范畴 B 中的态射。

显然,函子反映了不同的范畴之间的内在联系,函子的定义是十分松散的,而不同范畴之间的关系有强有弱,一个随便定义的函子很多时候并不能太深刻反映范畴之间结构上的联系,因此数学上,对函子通常有几个限制,先假设 F 是范畴 A 与范畴 B 上一个函子,则:

  1. 对范畴 A 上的单位态射Ia, F 必须将其映射为范畴 B 上的单位态射 Ib, F(Ia) = Ib.

  2. 函子对态射的组合必须满足分配徤,即,假设 f, g 是范畴 A 上的态射,则 F(f.h) = F(f).F(g)。

显然这两个限制是很强的,如果两个范畴之间存在这样一个函子,则反映了他们之间在结构上有着很强的相似性,从看似风牛马不相及的东西里找出他们内在的相似性,数学家最爱干的事情了。

和态射一样函子也可以是自映射的,即函子允许将范畴映射到其自身,这样做有什么好处呢?不同范畴之间的映射反映了范畴间的相似性,范畴到范畴自身的映射则显然是反映了范畴内部的自相似性 --- 到底认识自己也不是一件容易的事啊。。。自相似性是大自然里美妙的存在,想想六角形的雪花,想想分形... 在范畴论里,这种将范畴映射到自身的函子被称为自函子(endofunctor).

Haskell 中的函子

知道为什么要讲自函子了吗,Haskell 中只有一个范畴! 那么这个唯一的范畴 Hask 中,存不存在自函子呢?有的!终于讲到重点了,为什么 Haskell 有这么些奇怪的概念? Haskell 的老鸟会告诉你,这些奇怪的东西都是宝贝,它们都是有本而来的。

那么 Haskell 中的自函子是怎么体现出来的呢? 根据前面的定义,一个函子其实就是一个映射,它把对象映射为对象,把态射映射为态射,我们知道在 Haskell 中对象就是一个类型,如整型,布尔型等,将一个类型映射为另一个类型,没错,就是 type constructor 在干的事情,c++ 的程序员可以用模板类来想象一下,如,vector<int> 其实就是将 int 映射为 vector<int>, 这是两种不同的类型了,实例化模板的过程实际上就是把一个类型变成另一个类型的过程。

注意不要把对象的映射与对象内部的态射混淆了,态射是将对象内部的值进行映射,而对象的映射(函子)是把对象这个整体映射为另一个对象,函子根本不关心一个对象内部会有什么值。

类型到类型的映射事实上并不是普遍存在的,自函子反映的是范畴内部的结构关系,这些关系并不是因为函子的存在而存在,函子只是揭示了这些内在的关系。具体在 Haskell 中,类型间的关系并不是普遍存在的,比如说, Int -> Bool 就没有直接对应的映射关系,而存在映射关系的类型,它们都有一些共同的特点,比如可以看成是简单类型与复杂类型之间的相互转换。

type constructor 就是自函子的一部分!

好了,现在类型到类型的映射在 Haskell 中找到了,那态射到态射之间的映射呢?必竟这也是函子的必要组成部分。

在 Haskell 中,态射就是一般的函数,把一个函数映射为另一个函数,听起来不就是高阶函数在干的事情嘛。具体来说,映射函数这件事可以认为来自 Functor 这个 typeclass,连名字都一模一样,目的昭然若揭。Haskell 中的 Functor 是一个 typeclass,它的定义如下:

fmap 干嘛的?显然就是用来把态射 (a -> b) 映射为态射 (f a -> f b)的,它把范畴里的态射映射到另一个态射,且遵守了函子在映射态射时所需要遵守的两个原则。

讲到这里,我们一步一步不知不觉就已经向着 monad 靠近了,好激动,先打住了,回头再整理整理。

【参考】

http://en.wikibooks.org/wiki/Haskell/Category_theory

http://bartoszmilewski.com/2011/01/09/monads-for-the-curious-programmer-part-1/

http://www.cnblogs.com/catch/p/3973104.html

转载于:https://www.cnblogs.com/feng9exe/p/10131709.html

Haskell 与范畴论-函子、态射、函数相关推荐

  1. Haskell 与范畴论

    说到 Haskell,这真是一门逼格极高的编程语言,一般初学者如果没有相关函数式编程的经验,入门直接接触那些稀奇古怪的概念,简直要跪下.现在回想起来,隐隐觉得初学者所拥有的命令式编程语言(impera ...

  2. Haskell与范畴论

    http://www.yi-programmer.com/blog/2010-04-06_haskell_and_category_translate.html#id24 白菜 - 精确编程 Home ...

  3. (转)Haskell与范畴论

    Haskell与范畴论 http://www.yi-programmer.com/blog/2010-04-06_haskell_and_category_translate.html 用haskel ...

  4. 这么看来,范畴论中对象与态射的概念,是完全应用到 Haskell当中了,是吗?...

    是的,范畴论中的对象与态射的概念在 Haskell 编程语言中得到了很好的应用.在 Haskell 中,函数是态射,而对象可以被抽象为数据类型.函数是 Haskell 中重要的概念,可以将一个输入映射 ...

  5. 范畴论:1.2 类型和函数

    由类型[Type]和函数[Function]组成的范畴在编程中扮演者重要的角色.所以,让我们来谈谈什么是类型以及为什么需要它们. 2.1 who need type? 对于静态vs动态.强类型vs弱类 ...

  6. Haskell的monad和范畴论的探讨

    下面是上次和我一起讨论haskell的网友的继续,主要探讨了haskell的monad和范畴论的关系. 2012年3月28日: Parker says: (10:45:06 PM) haskell你现 ...

  7. 【读书笔记】Haskell函数式编程入门 I 基础篇 2. 类型系统和函数

    文章目录 2. 类型系统和函数 2.1 Haskell的数据和类型 2.1.1 Haskell常用数据类型 2.1.2 函数类型 (1) 函数类型的定义 (2) 非柯里化函数和柯里化函数 (3) 多态 ...

  8. JS函数式编程【译】5.1 范畴论

    ? Functional Programming in Javascript 主目录第五章 范畴论 范畴论 范畴论是用于函数组合的理论性概念.范畴论和函数组合它俩在一起就像发动机排量和马力,像NASA ...

  9. JS函数式编程【译】5.2 函子 (Functors)

    函子(Functors) 态射是类型之间的映射:函子是范畴之间的映射.可以认为函子是这样一个函数,它从一个容器中取出值, 并将其加工,然后放到一个新的容器中.这个函数的第一个输入的参数是类型的态射,第 ...

最新文章

  1. SystemML大规模机器学习,优化算子融合方案的研究
  2. P3743 kotori的设备(二分答案,思维,线性)难度⭐⭐⭐
  3. linux 协议栈之socket,Linux协议栈之BSD和INET socket层(一)
  4. CCpp.CallGraph
  5. flush privileges 什么意思
  6. 面试题整理5 顺时针打印矩阵
  7. springboot整合flowable
  8. boost::safe_numerics模块测试对文字的 constexpr 操作
  9. Java Language Changes for Java SE 9
  10. 跳出IT运维怪圈 看南方报业如何主动出击
  11. 并发服务器模型——单进程服务器
  12. ibm服务器修改ide,IBM刀片服务器配置IDE RAID的方法
  13. 【第一天】【ROS操作系统】【2】ROS安装教程
  14. 数据可视化大屏-Vue项目
  15. 什么是请求报文和响应报文?
  16. GEEer成长日记十二:Modis_LST地表温度产品时间序列分析
  17. 设计评审CheckList
  18. post-processing effects HDR
  19. 解构金蝶EAS 开发工具
  20. c语言程序项目任务教程 杨东芳 答案,c语言项目化教程 c语言程序设计

热门文章

  1. 算法竞赛入门经典第二版课后习题答案第二章
  2. Android app做成 (home)launcher 只是 应用开发非ROM 开发
  3. Android分屏流程分析
  4. 2020年鸿蒙手机在千元机吗,鸿蒙OS升级计划表曝光,华为千元机也有份!
  5. LDA原理(剖析源代码,详解)
  6. 我SB了,深感懊恼和自责,希望看到本文的朋友,不要再上当受骗了
  7. CAPWAP基础原理
  8. 「双11」十年,阿里与中国都需要再转身
  9. uni-app中让input标签在点击时清空
  10. f7d4301 mysql_Belkin酷玩:最全能的顶级无线路由器