查看原文
其他

【第673期】函数式编程术语解析

2016-08-16 pinggod 前端早读课

前言

本篇由@pinggod翻译的,他曾经分享过:【第523期】2016 JavaScript 技术栈展望  

ps:我是来学习的


正文从这开始~


函数式编程蔚然成风,越来越多的开源项目、技术交流在使用函数式编程的术语降低开发或沟通成本,这无形中对不了解函数式编程的开发者造成了一定的学习门槛,翻译本文的初衷就是要普及函数式编程的基本知识,从新的角度扩展编程思维。至于为什么要使用 JavaScript 演示函数式编程,一方面是因为 JavaScript 的特性在很多方面与函数式编程浑然天成,另一方面是因为 JavaScript 是世界上最 XX 的语言……


Arity

指函数的参数数量,由 -ary 和 -ity 这两个英文后缀拼接而成:



Higher-Order Functions

高阶函数,此类函数可以接收其他函数作为参数,也可以返回一个函数作为返回值:



Partial Application

偏函数,在原函数的基础上预填充(pre-filling)部分参数并返回的新函数:



JavaScript 中的 Function.prototype.bind() 函数是创建偏函数的最简单方式:



Currying

柯里化,将一个接收多个参数的函数转化为单参数函数的方式,转化后的函数每次只接收一个参数,然后返回一个新函数,新函数可以继续接收参数,直到接收到所有的参数:


Function Composition

函数合成,接收多个函数作为参数并返回一个新函数的方式,新函数按照传入的参数顺序,从右往左依次执行,前一个函数的返回值是后一个函数的输入值:



Purity

一个纯函数需要满足两个条件,第一是函数的返回值只能由输入值(函数接收的参数)决定,也就是说纯函数接收相同的参数会返回相同的值;第二是纯函数不会对自身作用域之外的运行环境产生副作用(side effects),比如说不会改变外部环境中变量的值,这会被认为是不安全的行为:



纯函数示例:



Side effects

如果函数或表达式与其自身作用域之外的可变数据(mutable data)发生了读写操作,那么此时函数和表达式就产生了副作用:



Idempotent

幂等,同一个函数使用相同的参数嵌套执行多次的结果与执行一次的结果相同:


Point-Free Style

point-free style 是一种不显式向函数传递参数的代码风格,通常需要柯里化和高阶函数来实现:



point-free style 的函数看起来就像是一个赋值表达式,没有使用我们常见的 function 或 => 等来声明其接收的参数。


Predicate

断言,一个返回布尔值的函数:


Contracts

TODO


Guarded Functions

TODO


Categories

categories 内部都绑定了具体的函数用于约束或执行特定的逻辑,比如 Monoid。


Value

任何可以赋值给变量的值都可以称为 value:



Constant

常量,初始化后不能再次执行赋值操作的数据类型:



常量具有 referentially transparent 的特性,也就是说将程序中出现的常量替换为它们实际的值,并不会影响程序的结果。译者话外:实际上在 JavaScript 中的 const 所声明的常量并不是完全稳定的,使用 Immutable.js 演示更加恰当:


f(g()) === g


Functor

functor 都拥有 map 函数,并且在执行 map 之后会返回一个新的 functor:



JavaScript 中最常见的 functor 就是数组类型的实例:



Pointed Functor

pointed functor 都拥有 of 函数,用于接收和构建 functor。ES2015 提供了 Array.of 函数,所以数组实例就可以看成是 pointed functor:



Lift

lift 发生在你将值放入 functor 的时候,如果你将函数 lift 进了 Applicative Functor,那么就可以使用这个函数处理传递给这个 functor 的值。某些 lift 的实现拥有 lift 或 liftA2 函数,便于在 functor 上执行相关的函数:



lift 一个单参数的函数非常类似于 map 操作:



Referential Transparency

如果一个表达式可以被替换为实际的值而不影响程序的运行结果,那么我们就说这个表达式是 referentially transparent:



以上面代码为例,任何调用 greet() 的地方都可以替换为 "Hello World!" 而不影响程序的执行结果。


Equational Reasoning

如果一个应用由多个表达式组合而成,且每个表达式都没有 side effect,那么这个应用就可以由部分推导出整体。


Lambda

匿名函数,本质上是一个 value:



Lambda Calculus

数学的分支之一,使用函数创建通用的计算模型(universal model of computation)。


Lazy evaluation

惰性求值,是一种按需执行的求值策略,只有需要某个值时才会执行相关的表达式。在函数式编程语言中,这一特性可用于构造无限列表。



Monoid

Monoid,通过一个函数“合并”两个同类型数据后返回相同的数据类型。最简单的 monoid 就是两数相加:



这里的 + 就是上面所说的“合并”函数。Monoid 中存在恒等式的概念:



如果知道了一个函数的的恒等式和“合并”函数 compose,函数本身就是一个 monoid:



Monad

Monad,是一个拥有 of 和 chain 函数的数据类型,chain 类似于 map,但它会输出非嵌套形式的结果:



在其他函数式编程语言中,of 也被称为 return,chain 也被称为 flatmap 和 bin


Comonad

Comonad,拥有 extract 和 extend 函数的数据类型:



Applicative Functor

Applicative Functor,是拥有 ap 函数的数据类型,ap 函数可以将 functor 中的值转化为其他 functor 中的同类型值:



这一特性对于多个 applicative functor 需要接收多个参数时,就显得很有用:



Morphism

态射,一个转换函数。


Isomorphism

同构转换,相同数据下不同结构之间的转换。举例来说,2D 坐标既可以存储为数组 [2, 3] 也可以存储为 { x: 2, y: 3 }:



Setoid

Setoid,拥有 equals 函数的数据类型,可用于与其他同类型的数据进行比较。为 Array 类型添加 equals 函数使其成为 Setoid:



Semigroup

Semigroup,拥有 concat 函数的数据类型,可以与同类型数据进行合并:



Foldable

Foldable,拥有 reduce 函数的数据类型,可以将 Foldable 的实例转换为其他数据类型:



Traversable

TODO


Type Signatures

类型签名,在 JavaScript 中通常会在注释中写明当前函数的参数类型和返回值类型,虽然各种语言的类型签名不同,但通常与以下示例相似:



如果某个函数要作为参数传递给其他函数,那么在类型签名中需要使用括号包裹起这个函数的类型信息:



上面示例中的 a、b 表示参数可以是任何数据类型的,但在下面的代码中,map 的类型签名表示: f 是一个函数,f 接收一个 a 类型的参数,返回一个 b 类型的值,同时 map 是一个柯里化的函数,其第二个接收一个列表形式的 a 类型参数,并返回列表形式的 b 类型参数:



Union type

联合类型,表示将多个类型信息放入一个类型变量中。JavaScript 中没有类型机制,所以让我们假设有一个类型变量 NumOrString,它表示 Number 或者 String 类型。+ 运算符在 JavaScript 中既可用于 Number,也可用于 String,所以我们使用 NumOrString 定义 + 的输入输出类型信息:



Product type

product type 同样包含多种基本类型:



Option

Option,是 union type 的特例,它只包含两种类型 Some 和 None。Option 常用于表示那些不确定是否返回值的函数:



使用 chain 函数执行链式调用可以返回具体的 Option:


某些语言中使用 Maybe 表示 Option,使用 Just 表示 Some,使用 Nothing 表示 Node。


关于本文

译者:@pinggod

译文链接:http://pinggod.com/2016/函数式编程术语解析/



欢迎投稿到前端早读课

投稿邮箱:181422448@qq.com

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存