? Functional Programming in Javascript 主目录第五章 范畴论

范畴论

范畴论是用于函数组合的理论性概念。范畴论和函数组合它俩在一起就像发动机排量和马力,像NASA和空间穿梭, 像好酒和装它的瓶子。基本上讲,你不能让它们中的一个脱离另一个而独立存在。

范畴论概览

范畴论实际并不是一个很难的概念。在数学上它大到能够填满一个本科课程,但是在计算机编程中它可以很容易地被总结出来。

爱因斯坦曾说过:“如果你不能把它解释给一个六岁的孩子听,那你自己也没有理解”。这样,按照给六岁孩子解释的说法, 范畴论只不过是一些连接的圆点。也许这过分简化了范畴论,不过这从直观的方式上很好的解释了我们所需要知道的东西。

首先你需要了解一些术语。范畴(category,也可以说是种类)只是一些同样类型的集合。 在JavaScript里,它们是数组或对象,包含了明确指定为数字、字符串、布尔、日期或节点等类型的变量。 态射(Morphism)是一些纯函数,当给定一系列输入时总会返回相同的输出。 多态操作可以操作多个范畴,而同态操作限制在一个单独的范畴中。 例如,同态函数“乘”只能作用于数字,而多态函数“加”还能作用于字符串。

下图展示了三个范畴——A、B、C,以及两个态射——fg

范畴论告诉我们,当第一个态射的范畴是另一个态射所需的输入时,它们就可以像下图所示这样组合:

f o g符号代表态射f和g的组合。现在我们就可以连接这些圆点。

真的是这样,只是连接圆点。

我插两句:作者老说范畴论就是圆点,但是也没看到个圆点。可以认为f o g中间的圆圈就是圆点 (中间不是字母o而是圆圈,我实在找不到合适的字符)。因为在haskell里,函数组合的形式就是f.g。

类型安全

我们来连接一些圆点。范畴包含两样东西:

  1. 对象 Object(在JavaScript中是类型)。
  2. 态射 Morphisms(在JavaScript中是只作用于类型的纯函数)。

这是数学赋予范畴论的术语,所以不幸与我们的JavaScript的术语集有些冲突。 范畴论中的对象更像是代表一个指定数据类型的变量,而不是像JavaScript所定义的对象那样具有一系列属性和值。 态射只是使用这些类型的纯函数。

所以JavaScript应用范畴论很简单。在JavaScript中使用范畴论意味着每个范畴只使用一个特定的数据类型。 数据类型是指数字、字符串、数组、日期、对象、布尔等等。但是JavaScript没有严格的类型系统,很容易出岔子。 所以我们不得不实现我们自己的方法来保证数据的正确

JavaScript中有四种原始类型:number、string、Boolean、function。我们可以创建类型安全函数, 返回变量或者抛出一个错误。这符合范畴论的对象定理。

var str = function(s) {if (typeof s === "string") {return s;} else {throw new TypeError("Error: String expected, " + typeof s + "given.");}
}
var num = function(n) {if (typeof n === "number") {return n;} else {throw new TypeError("Error: Number expected, " + typeof n + "given.");}
}
var bool = function(b) {if (typeof b === "boolean") {return b;} else {throw new TypeError("Error: Boolean expected, " + typeof b + "given.");}
}
var func = function(f) {if (typeof f === "function") {return f;} else {throw new TypeError("Error: Function expected, " + typeof f +" given.");}
}

然而这里重复代码太多,并且不是很函数式。我们可以创建一个函数,它返回一个类型安全的函数。

var typeOf = function(type) {return function(x) {if (typeof x === type) {return x;} else {throw new TypeError("Error: " + type + " expected, " + typeof x +"given.");}}
}
var str = typeOf('string'),num = typeOf('number'),func = typeOf('function'),bool = typeOf('boolean');
typeof = (type) ->(x) ->if typeof x is typexelsethrow new TypeError("Error:  expected, undefined given.")
str = typeOf('string')
num = typeOf('number')
func = typeOf('function')
bool = typeOf('boolean')

现在,我们可以利用这些函数让我们的函数像预期那样运行。

// 未受保护的方法
var x = '24';
x + 1; // 会返回'241',而不是25
// 受保护的方法
// plusplus :: Int -> Int
function plusplus(n) {return num(n) + 1;
}
plusplus(x); // 抛出错误,防止出现意外的结果

再来看个有点肉的例子。我们想检查Unix时间戳的长度,由JavaScript函数Date.parse()返回的值是数字而不是字符串, 我们得用str()函数。

// timestampLength :: String -> Int
function timestampLength(t) { return num(str(t).length); }
timestampLength(Date.parse('12/31/1999')); // 抛出错误
timestampLength(Date.parse('12/31/1999').toString()); // 返回12

像这样把明确地一个类型转换为另一个类型(或者是相同的类型)的函数叫做态射。这符合范畴论的态射定理。 这里强迫通过类型安全函数进行类型声明,利用了这个机制的态射是我们在JavaScript中展示范畴概念所需的一切。

对象识别

另外还有一种重要的数据类型:对象。

var obj = typeOf('object');
obj(123); // 抛出错误
obj({x:'a'}); // 返回 {x:'a'}

然而,对象各不相同。它们可以被继承。任何非原始类型(number、string、Boolean、function)的东西都是对象, 包括数组、日期、元素等等。

没有办法知道一个对象是个什么类型,也就是说没法通过typeof关键字知道JavaScript的对象的子类型是什么, 所以我们得想办法。Object有个toString()函数,我们可以通过它变通实现这个目的。

var obj = function(o) {if (Object.prototype.toString.call(o) === "[object Object]") {return o;} else {throw new TypeError("Error: Object expected, something else given.");}
}

同样,对于各种对象,我们要实现代码重用:

var objectTypeOf = function(name) {return function(o) {if (Object.prototype.toString.call(o) === "[object " + name + "]") {return o;} else {throw new TypeError("Error: '+name+' expected, something else given.");}}
}
var obj = objectTypeOf('Object');
var arr = objectTypeOf('Array');
var date = objectTypeOf('Date');
var div = objectTypeOf('HTMLDivElement');

这对下一个主题函子非常有用。

下一节 函子

转载于:https://www.cnblogs.com/tolg/p/4877373.html

JS函数式编程【译】5.1 范畴论相关推荐

  1. JS函数式编程【译】5.3 单子 (Monad)

    单子是帮助你组合函数的工具. 像原始类型一样,单子是一种数据结构,它可以被当做装载让函子取东西的容器使用. 函子取出了数据,进行处理,然后放到一个新的单子中并将其返回. 我们将要关注三种单子: May ...

  2. js 函数式编程(一)

    函数式编程,以强调函数使用为主的开发风格,也是一种范式 函数为一等公民 js函数是一个特殊的对象,有很高的灵活性,比如函数返回一个函数,函数闭包,函数作为函数的参数,函数赋给变量,如果某个编程语言的函 ...

  3. JS函数式编程思维:柯里化、闭包

    偏函数(Partial Application): 探讨柯里化之前,我们先聊一聊很容易跟其混淆的另一个概念--偏函数(Partial Application).在维基百科中,对 Partial App ...

  4. 【基于JS 函数式编程 -1】什么是函数式编程 | 纯函数 | 命令式与声明式 | 优点

    ⭐️ 本文首发自 前端修罗场(点击即可加入),一个专注 Web 技术.答疑解惑.面试辅导.职业发展的社区. 相关文章 [函数式编程]基于JS 进行函数式编程(一)引入 | 什么是函数式编程 | 函数式 ...

  5. JS函数式编程概念理解:函子(Functor)

    标签(空格分隔): 函数式编程 函子 functor 很多前端在学习函数式编程之前,都会被各种概念折磨的死去活来,本文的重点算是函数式编程之前的一个甜品,重点在如何切入. 函子即Functor是FP( ...

  6. js函数式编程最佳实践 - 持续更新

    函数式编程最佳实践 学习文档 函数式编程术语 数组字串处理 function addString(el){return el + "0"; } var newArr = arr.m ...

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

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

  8. 【读书笔记】《JS函数式编程指南》(一)

    纯函数 纯函数:函数的返回值由传入的参数决定,即相同的参数返回相同的结果. slice和splice,表现作用相似. slice浅复制,返回复制之后的数组 splice删除数组元素,返回删除元素 sl ...

  9. js函数式编程之代码改善 - 封装和去重

    改动前的代码,问题如下 if语句滥用 重复功能代码 数据.ui和业务逻辑代码耦合 不易测试 function errorCatch(err) {if (err.status == 0) {wx.sho ...

最新文章

  1. PyQt5 技术篇-QWidget、QDialog程序窗口关闭closeEvent()触发事件方法重写
  2. 计算机网络时延图,计算机网络中网站性能延迟加载图像的示例分析
  3. java自定义异常返回_Java自定义异常
  4. 02-requests模块的概述
  5. 阿里云AHAS Chaos:应用及业务高可用提升工具平台之故障演练
  6. 01-Windows下安装Node.js及环境配置
  7. 5月25 python3.6—pymouse—pyhook_3安装问题
  8. hp服务器装vm系统,服务器虚拟化ESXi 5.5安装过程(HP)
  9. java 集合底层_java集合底层实现总结
  10. vue中处理文本不换行问题
  11. 从实例学Kettle(一):获取股票行情数据
  12. c++ 写一个复数计算器
  13. 批量删除进程 mysql_linux 批量删除进程
  14. Android Studio导入工程项目一直处于gradle....而且一直卡在这个页面
  15. java.io.FileNotFoundException异常的原因
  16. 一、编程语言与Python介绍
  17. JVM初探究【JVM入门教程】
  18. 世界上最难的视觉图_【若寒专栏】被喻为世界上最难的联赛——2019赛季日本J2联赛球队总结(7 完结)...
  19. vsd格式文件如何打开?
  20. [附源码]计算机毕业设计Python游戏交易平台(程序+源码+LW文档)

热门文章

  1. vue 生命周期 返回不触发_Vue生命周期小结
  2. nodejs用egg框架实现图片上传
  3. 浅谈怎样建设一个为企业带来更大价值的企业网站
  4. 围棋java_围棋模拟
  5. Spring之AOP的切点、通知、切点表达式以及知识要点
  6. PyQuery的使用方法
  7. Server 2008R2更新系统失败,提示8000FFFF的解决方法
  8. 论文笔记之C3D(Learning Spatiotemporal Features with 3D Convolutional Networks)
  9. sql复习(sql基础、过滤和排序数据、单行函数)
  10. 学生无线耳机哪款好?两百左右适合学生党的无线耳机推荐