您可以在这里找到源代码:https://github.com/aelassas/function-ts
在 TypeScript 中,函数只不过是对象。因此,可以构造函数、作为参数传递、从函数返回或分配给变量。因此,TypeScript 具有一流的功能。更准确地说,TypeScript 支持以下内容:
本文不会讨论函数式编程的基础知识,因为您可以在互联网上找到有关此主题的大量资源。相反,它将讨论 TypeScript 中应用于代数、数字、欧几里得平面和分形的函数式编程。本文提供的示例将从简单到复杂,但始终以简单、直接且易于理解的方式进行说明。
要运行源代码,您需要安装 Node.js。安装 Node.js 后,下载源代码存档,解压它,转到在终端上解压的源代码文件夹,设置 TypeScript 环境并使用以下命令安装所有必需的依赖项:
npm install
要运行数字的演示,请运行以下命令:
npm run numbers
要运行欧几里得平面的演示,请运行以下命令:
npm run plane
要运行分形演示,请运行以下命令:
npm run fractals
设 S 为任意元素 a、b、c ... 的集合(例如,桌子上的书或欧几里得平面上的点),并设 S' 为这些元素的任意子集(例如,桌子上的绿色书籍或以欧几里德平面原点为圆心的半径为 1 的圆中的点)。
集合 S' 的特征函数 S'(x) 是将 S 的每个元素 x 与 true 或 false 相关联的函数。
S'(x) = true if x is in S' S'(x) = false if x is not in S'
令 S 为桌子上的一套书,让 S' 为桌子上的一套绿书。设a和b是桌上的两本绿书,c和d是桌上的两本红书。然后:
npm install
设 S 为欧几里德平面中点的集合,令 S' 为以欧几里德平面原点 (0, 0)(单位圆)为中心、半径为 1 的圆中点的集合。设a和b为单位圆中的两点,c和d为以欧几里德平面原点为圆心、半径为2的圆中的两点。然后:
npm run numbers
因此,任何集合S'总是可以用它的特征函数来表示。该函数接受一个元素作为参数,如果该元素位于 S' 中,则返回 true,否则返回 false。换句话说,集合(抽象数据类型)可以通过 TypeScript 中的函数来表示。
npm run plane
在接下来的部分中,我们将了解如何通过 TypeScript 以函数式方式表示集合代数中的一些基本集合,然后我们将定义集合上的通用二元运算。然后,我们将这些运算应用于数字,然后应用于欧几里得平面的子集。集合是抽象数据结构,数字的子集和欧几里得平面的子集是抽象数据结构的表示,最后的二元运算是适用于抽象数据结构的任何表示的通用逻辑。
本节介绍集合代数中一些基本集合通过 TypeScript 的表示。
设E为空集,并清空其特征函数。在集合代数中,E 是没有元素的唯一集合。因此,Empty 可以定义如下:
npm run fractals
因此,E 在 TypeScript 中的表示可以定义如下:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
在集合代数中,Empty 表示如下:
因此,运行以下代码:
S'(a) = S'(b) = true S'(c) = S'(d) = false
给出以下结果:
设 S 为集合,S' 为包含所有元素及其所有 特征函数 的 S 子集。在集合代数中,S' 是包含所有元素的完整集合。因此,All 可以这样定义:
S'(a) = S'(b) = true S'(c) = S'(d) = false
因此,S' 在 TypeScript 中的表示可以定义如下:
type Set<T> = (x: T) => boolean
在集合代数中,All 表示如下:
因此,运行以下代码:
npm install
给出以下结果:
设 E 为 Singleton 集合,Singleton 为其特征函数。在集合代数中,E 也称为单位集或一元组,是只有一个元素 e 的集合。因此,Singleton可以定义如下:
npm run numbers
因此,E 在 TypeScript 中的表示可以定义如下:
npm run plane
因此,运行以下代码:
npm run fractals
给出以下结果:
本节介绍整数集的子集。
设E是偶数集合,Even是它的特征函数。在数学中,偶数是二的倍数。因此,Even 可以定义如下:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
因此,E 在 TypeScript 中的表示可以定义如下:
S'(a) = S'(b) = true S'(c) = S'(d) = false
因此,运行以下代码:
S'(a) = S'(b) = true S'(c) = S'(d) = false
给出以下结果:
设E为奇数集合,Odd为其特征函数。在数学中,奇数是指不是二的倍数的数。因此,Odd 可以定义如下:
type Set<T> = (x: T) => boolean
因此,E 在 TypeScript 中的表示可以定义如下:
Empty(x) = false if x is in E Empty(x) = false if x is not in E
因此,运行以下代码:
const empty = () => (e: T) => false
给出以下结果:
设 E 为 3 的倍数集,MultipleOfThree 是其特征函数。在数学中,3的倍数是能被3整除的数。因此,MultipleOfThree可以定义如下:
console.log('\nEmpty set:') console.log('Is 7 in {}?', common.empty()(7))
因此,E 在 TypeScript 中的表示可以定义如下:
All(x) = true if x is in S
因此,运行以下代码:
const all = () => (e: T) => true
给出以下结果:
设 E 为 5 的倍数集,MultipleOfFive 为其特征函数。在数学中,5的倍数是能被5整除的数。因此,MultipleOfFive可以定义如下:
npm install
因此,E 在 TypeScript 中的表示可以定义如下:
npm run numbers
因此,运行以下代码:
npm run plane
给出以下结果:
很久以前,当我在玩 Project Euler 问题时,我必须解决以下问题:
npm run fractals
为了解决这个问题,我首先必须编写一个快速算法来检查给定的数字是否是素数。算法编写完成后,我编写了一个迭代算法,迭代素数,直到找到第 10 001 个素数。
设 E 为素数集,并素其特征函数。在数学中,素数是大于 1 的自然数,除了 1 和它本身之外没有正因数。因此,Prime可以定义如下:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
因此,E 在 TypeScript 中的表示可以定义如下:
S'(a) = S'(b) = true S'(c) = S'(d) = false
因此,运行下面的代码来解决我们的问题:
S'(a) = S'(b) = true S'(c) = S'(d) = false
其中 getPrime 定义如下:
type Set<T> = (x: T) => boolean
给出以下结果:
本节介绍了从给定集合构造新集合和操作集合的几个基本操作。下面是集合代数中的文氏图。
设E和F是两个集合。 E 和 F 的并,用 E U F 表示,是属于 E 和 F 的成员的所有元素的集合。
让 Union 成为 并集 操作。因此,Union 操作可以在 TypeScript 中实现如下:
Empty(x) = false if x is in E Empty(x) = false if x is not in E
运行以下代码:
const empty = () => (e: T) => false
给出以下结果:
设E和F是两个集合。 E 和 F 的交集,用 E n F 表示,是同时属于 E 和 F 成员的所有元素的集合。
设 Intersection 为 交集 运算。因此,Intersection 操作可以在 TypeScript 中实现如下:
console.log('\nEmpty set:') console.log('Is 7 in {}?', common.empty()(7))
运行以下代码:
All(x) = true if x is in S
给出以下结果:
设E和F是两个集合。 E 和 F 的笛卡尔积,用 E × F 表示,是所有有序对 (e, f) 的集合,使得 e 是 E 的成员,f 是 F 的成员。
令 CartesianProduct 为 笛卡尔积 运算。因此,CartesianProduct 运算可以在 TypeScript 中实现如下:
npm install
运行以下代码:
npm run numbers
给出以下结果:
设E和F是两个集合。 E 中 F 的相对补,记为 E F 是属于 E 成员但不属于 F 成员的所有元素的集合。
设补码为相对补运算。因此,补码操作可以在 TypeScript 中实现如下:
npm run plane运行下面的代码:
npm run fractals
给出以下结果:
设E和F是两个集合。 E 和 F 的对称差,用 E Δ F 表示,是属于 E 和 F 的成员但不在 E 和 F 交集内的所有元素的集合。
设 SymmetricDifference 为 对称差 运算。因此,SymmetricDifference 操作可以在 TypeScript 中通过两种方式实现。一种简单的方法是使用并集和补集运算,如下所示:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
另一种方法是使用 XOR 二元运算,如下所示:
S'(a) = S'(b) = true S'(c) = S'(d) = false
运行以下代码:
S'(a) = S'(b) = true S'(c) = S'(d) = false
给出以下结果:
本节介绍了集合上其他有用的二元运算。
设 Contains 为检查元素是否在集合中的操作。此操作是一个函数,它接受一个元素作为参数,如果该元素在集合中则返回 true,否则返回 false。
因此,该操作在 TypeScript 中定义如下:
type Set<T> = (x: T) => boolean
因此,运行以下代码:
npm install
给出以下结果:
设 Add 为将元素添加到集合中的操作。此操作是一个函数,它将一个元素作为参数并将其添加到集合中。
因此,该操作在 TypeScript 中定义如下:
npm run numbers
因此,运行以下代码:
npm run plane
给出以下结果:
设Remove为从集合中删除元素的操作。此操作是一个函数,它将一个元素作为参数并将其从集合中删除。
因此,该操作在 TypeScript 中定义如下:
npm run fractals
因此,运行以下代码:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
给出以下结果:
你可以看到我们通过函数式编程在 TypeScript 中做一些集合代数是多么容易。前面的部分显示了最基本的定义。但是,如果你想更进一步,你可以考虑:
在上一节中,集合的基本概念是在 TypeScript 中实现的。在本节中,我们将练习在欧几里得平面上实现的概念。
圆盘是由圆包围的平面的子集。有两种类型的磁盘。 闭圆盘是包含构成其边界的圆的点的圆盘,开圆盘是不包含构成其边界的圆的点的圆盘。
在本节中,我们将设置封闭圆盘的特征函数并将其绘制在HTML5页面中。
要设置特征函数,我们首先需要一个计算平面上两点之间的欧氏距离的函数。该函数的实现如下:
S'(a) = S'(b) = true S'(c) = S'(d) = false
其中 Point 定义如下:
S'(a) = S'(b) = true S'(c) = S'(d) = false
这个公式基于毕达哥拉斯定理。
其中 c 是 欧几里得距离,a² 是 (p1.X - p2.X)²,b² 是 (p1.Y - p2.Y)²。
设Disk为闭盘的特征函数。在集合代数中,实数集中闭盘的定义如下:
其中 a 和 b 是中心坐标,R 是半径。
因此,Disk 在 TypeScript 中的实现如下:
npm install
为了在 HTML5 页面中查看集合,我决定实现一个在 欧几里得平面 中绘制集合的函数draw。我选择了HTML5,因此使用canvas元素进行绘图。
因此,我通过绘制方法构建了如下所示的欧几里得平面。
下面执行平面。
npm run numbers
在绘制函数中,创建了一个与欧几里得平面容器具有相同宽度和相同高度的画布。然后,如果画布的像素 (x,y) 中的每个点属于该集合,则该点将被替换为黑点。 xMin、xMax、yMin 和 yMax 是上面欧几里得平面图中所示的边界值。
运行以下代码:
npm run plane
其中disk是画布的id:
npm run fractals
给出以下结果:
水平或垂直半平面是平面将欧几里得空间划分成的两个子集之一。 水平半平面是两个子集之一,平面通过与Y轴垂直的线将欧几里得空间划分为两个子集,如上图所示。 垂直半平面是平面通过与X轴垂直的线将欧几里得空间划分成的两个子集之一。
本节我们将设置水平和垂直半平面的特征函数,将它们绘制在HTML5页面中,看看会发生什么如果我们将它们与 disk 子集结合起来,我们就可以做到。
设 HorizontalHalfPlane 为 水平半平面的特征函数。 HorizontalHalfPlane 在 TypeScript 中的实现如下:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
因此,运行以下代码:
npm install
其中 hhp 是画布的 id:
npm run numbers
给出以下结果:
设VerticalHalfPlane为垂直半平面的特征函数。 VerticalHalfPlane 在 TypeScript 中的实现如下:
npm run plane因此,运行以下代码:
npm run fractals
其中 vhd 是画布的 id:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
给出以下结果:
在文章的第一部分中,我们在集合上设置了基本的二元运算。因此,例如,通过组合圆盘和半平面的交集,我们可以绘制半圆盘子集。
因此,运行以下示例:
S'(a) = S'(b) = true S'(c) = S'(d) = false
其中 hd 是画布的 id:
S'(a) = S'(b) = true S'(c) = S'(d) = false
给出以下结果:
本节介绍欧几里得平面上的集合上的函数。
令translatePoint 为平移平面上的点的函数。在欧几里得几何中,translatePoint 是一个将给定点沿指定方向移动恒定距离的函数。因此 TypeScript 中的实现如下:
type Set<T> = (x: T) => boolean
其中 (deltax, deltay) 是平移的常数向量。
设translate为在平面上平移集合的函数。该函数在 TypeScript 中简单实现如下:
Empty(x) = false if x is in E Empty(x) = false if x is not in E“translate”采用参数“deltax”和“deltay”作为参数,“deltax”是第一欧几里德维度中的增量距离,“deltay”是第二欧几里德维度中的增量距离。如果点 _P (x, y)_ 在集合 _S_ 中平移,则其坐标将更改为 _(x', y') = (x, delatx, y, deltay)_。因此,点 _(x' - delatx, y' - deltay)_ 将始终属于集合 _S_。在集合代数中,“平移”被称为同构,换句话说,所有平移的集合形成_平移群T_,它与空间本身同构。这就解释了该函数的主要逻辑。 因此,在 HTML5 页面中运行以下代码:
const empty = () => (e: T) => false
其中 ep_op 是画布的 id:
console.log('\nEmpty set:') console.log('Is 7 in {}?', common.empty()(7))
给出以下结果:
设scalePoint为将任意点M发送到另一个点N的函数,使得线段SN与SM在同一行,但按因子 λ 缩放。在集合代数中,尺度的公式如下:
因此 TypeScript 中的实现如下:
npm install
其中 (deltax, deltay) 是平移的常数向量,(lambdax, lambdaday) 是 lambda 向量。
设标度为对计划中的集合应用相似性的函数。该函数在 TypeScript 中简单实现如下:
npm run numbers
scale 将第一欧几里得维度中的增量距离 deltax、第二欧几里得维度中的增量距离 deltay 以及常数因子向量 λ (lambdax, lambdaday) 作为参数。如果一个点 P (x, y) 在集合 S 中进行尺度变换,那么它的坐标将变为 (x', y') = (lambdax * x、delatx、lambda * y、deltay)。因此,点 ((x'- delatx)/lambdax, (y' - deltay)/lambday) 将始终属于集合 S,如果 lambda 与向量不同0,当然。在集合代数中,尺度被称为同构,换句话说,所有同势的集合形成同势群H,它与空间本身{0}同构。这就解释了该函数的主要逻辑。
因此,在我们的 HTML5 页面中运行以下代码:
npm run plane
给出以下结果:
令rotatePoint为以角度θ旋转点的函数。在矩阵代数中,rotatePoint 的公式如下:
其中(x', y')是旋转后点的坐标,x'和y'的公式为如下:
这个公式的演示非常简单。看看这个轮换。
演示如下:
因此 TypeScript 中的实现如下:
npm install
设rotate为对平面内的集合应用角度θ旋转的函数。该函数在 TypeScript 中简单实现如下。
npm run numbers
rotate 是一个以 theta 为参数的函数,theta 是旋转的角度。如果一个点 P (x, y) 在集合 S 中进行旋转变换,则其坐标将变为 (x', y') = (x * cos(theta) - y * sin(theta), x * sin(theta), y * cos(theta))。因此,点 (x' * cos(theta), y' * sin(theta), y' * cos(theta) - x' * sin(theta)) 将始终属于集合 S。在集合代数中,旋转被称为同构,换句话说,所有旋转的集合形成旋转群R,它与空间本身同构。这就解释了该函数的主要逻辑。
因此,在我们的 HTML5 页面中运行以下代码:
npm run plane
给出以下结果:
很简单,不是吗?对于那些想要更进一步的人,您可以探索这些:
分形是分形维数通常超过其拓扑维数并且可能落在整数之间的集合。例如,Mandelbrot 集合是由一系列复杂二次多项式定义的分形:
npm run fractals
其中 c 是复数。 Mandelbrot 分形被定义为所有点 c 的集合,使得上述序列不会逃逸到无穷大。在集合代数中,其公式如下:
分形(抽象数据类型)在 TypeScript 中始终可以表示如下:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
为了能够绘制分形,我需要操纵复数数字。因此,我创建了下面的 Complex 类:
S'(a) = S'(b) = true S'(c) = S'(d) = false
我创建了一个 Mandelbrot 分形(抽象数据类型表示)P(z) = z^2 c,如下所示。
npm install为了能够绘制_Complex_数字,我创建了一个“ComplexPlane”类。下面是 TypeScript 中的实现。
npm run numbers
因此,运行以下代码:
npm run plane
其中 fractal 是画布的 id:
npm run fractals
给出以下结果:
对于那些想要更进一步的人,您可以探索这些:
就是这样!我希望你喜欢阅读。
以上是TypeScript 中的函数式编程的详细内容。更多信息请关注PHP中文网其他相关文章!