ホームページ > 記事 > ウェブフロントエンド > TypeScript での関数型プログラミング
ソースコードはここで見つけることができます: https://github.com/aelassas/function-ts
TypeScript では、関数は単なるオブジェクトです。したがって、関数を構築したり、パラメーターとして渡したり、関数から返したり、変数に割り当てたりすることができます。したがって、TypeScript には第一級の関数があります。より正確には、TypeScript は以下をサポートしています:
関数型プログラミングの基本については、インターネット上で多数のリソースが見つかるため、この記事では説明しません。代わりに、代数、数値、ユークリッド平面、フラクタルに適用される TypeScript の関数型プログラミングについて説明します。この記事で説明する例は、単純なものからより複雑なものまでありますが、常にシンプル、直接的、そして理解しやすい方法で図解されています。
ソース コードを実行するには、Node.js をインストールする必要があります。 Node.js がインストールされたら、ソース コード アーカイブをダウンロードして解凍し、ターミナルで解凍したソース コード フォルダーに移動し、TypeScript 環境をセットアップして、次のコマンドを使用して必要な依存関係をすべてインストールします。
npm install
Numbers のデモを実行するには、次のコマンドを実行します:
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 をテーブル上の 2 冊の緑の本、c と d を 2 冊の赤い本としましょう。次に:
npm install
S をユークリッド平面内の点の集合、S' をユークリッド平面の原点 (0, 0) を中心とする半径 1 の円 (単位円) 内の点の集合とする。 a と b を単位円内の 2 点とし、c と d をユークリッド平面の原点を中心とする半径 2 の円内の 2 点としましょう。次に:
npm run numbers
したがって、任意の集合 S' は常にその 特性関数 によって表すことができます。要素を引数として受け取り、この要素が S' にある場合は true、それ以外の場合は false を返す関数。つまり、セット (抽象データ型) は TypeScript の関数を通じて表現できます。
npm run plane
次のセクションでは、TypeScript を使用して関数的な方法で集合の代数におけるいくつかの基本的な集合を表現する方法を見てから、集合に対する一般的な二項演算を定義します。次に、これらの操作を数値に適用し、次にユークリッド平面のサブセットに適用します。セットは抽象データ構造であり、数値のサブセットとユークリッド平面のサブセットは抽象データ構造の表現であり、最後に二項演算は抽象データ構造のあらゆる表現で動作する汎用ロジックです。
このセクションでは、TypeScript を使用した集合の代数におけるいくつかの基本的な集合の表現を紹介します。
E を空集合とし、その 特性関数を空にします。集合の代数では、E は要素を持たない一意の集合です。したがって、Empty は次のように定義できます。
npm run fractals
したがって、TypeScript での E の表現は次のように定義できます。
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
は次の結果を返します:
S を集合、S' をすべての要素とそのすべての 特性関数 を含む S の部分集合とします。集合の代数では、S' はすべての要素を含む完全な集合です。したがって、All は次のように定義できます。
S'(a) = S'(b) = true S'(c) = S'(d) = false
したがって、TypeScript での S' の表現は次のように定義できます。
type Set<T> = (x: T) => boolean
集合の代数では、All は次のように表されます。
したがって、以下のコードを実行します:
npm install
は次の結果を返します:
E をシングルトン集合とし、シングルトンをその 特性関数 とします。集合の代数では、単位集合または 1 タプルとしても知られる E は、要素 e を 1 つだけ持つ集合です。したがって、シングルトンは次のように定義できます。
npm run numbers
したがって、TypeScript での E の表現は次のように定義できます。
npm run plane
したがって、以下のコードを実行します:
npm run fractals
は次の結果を返します:
このセクションでは、整数セットのサブセットを示します。
E を偶数の集合とし、その 特性関数を偶数とします。数学では、偶数は 2 の倍数です。したがって、偶数は次のように定義できます。
S'(x) = true if x is in S' S'(x) = false if x is not in S'
したがって、TypeScript での E の表現は次のように定義できます。
S'(a) = S'(b) = true S'(c) = S'(d) = false
したがって、以下のコードを実行します:
S'(a) = S'(b) = true S'(c) = S'(d) = false
は次の結果を返します:
E を奇数の集合とし、奇数をその 特性関数 とします。数学では、奇数は 2 の倍数ではない数です。したがって、Odd は次のように定義できます。
type Set<T> = (x: T) => boolean
したがって、TypeScript での E の表現は次のように定義できます。
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))
したがって、TypeScript での E の表現は次のように定義できます。
All(x) = true if x is in S
したがって、以下のコードを実行します:
const all = () => (e: T) => true
は次の結果を返します:
E を 5 の倍数の集合とし、MultipleOfFive の 特性関数 とします。数学では、5 の倍数は 5 で割り切れる数です。したがって、MultipleOfFive は次のように定義できます:
npm install
したがって、TypeScript での E の表現は次のように定義できます。
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'
したがって、TypeScript での E の表現は次のように定義できます。
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 を 2 つのセットとする。 E U F で示される E と F の 和集合 は、E と F のいずれかのメンバーであるすべての要素のセットです。
Union を 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 を 2 つのセットとする。 E と F の 交差 (E n F で示される) は、E と F の両方のメンバーであるすべての要素のセットです。
Intersection を 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 を 2 つのセットとする。 E × F で示される E と F のデカルト積は、e が E のメンバーであり、f が F のメンバーであるような、すべての順序ペア (e, f) の集合です。
CartesianProduct を デカルト積 演算とします。したがって、CartesianProduct 演算は TypeScript で次のように実装できます。
npm install
以下のコードを実行します:
npm run numbers
は次の結果を返します:
E と F を 2 つのセットとする。 E における F の 相対補体 (EF で示されます) F は、E のメンバーであるが F のメンバーではないすべての要素の集合です。
Complement を 相対補数 演算とします。したがって、Complement 操作は TypeScript で次のように実装できます。
npm run plane以下のコードを実行します。
npm run fractals
は次の結果を返します:
E と F を 2 つのセットとする。 E Δ F で示される E と F の対称差は、E と F のいずれかのメンバーであるが、E と F の共通部分には含まれないすべての要素の集合です。
SymmetricDifference を 対称差分 演算とします。したがって、SymmetricDifference 操作は TypeScript で 2 つの方法で実装できます。簡単な方法は、次のように結合演算と補数演算を使用することです:
S'(x) = true if x is in S' S'(x) = false if x is not in S'
もう 1 つの方法は、次のように 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 で実装されました。このセクションでは、ユークリッド平面で実装された概念を実践します。
ディスクは、円で囲まれた平面のサブセットです。ディスクには2種類あります。 閉じたディスクは、その境界を構成する円の点を含むディスクであり、開いたディスクは、その境界を構成する円の点を含まないディスクです。
このセクションでは、Closed ディスクの 特徴関数 を設定し、HTML5 ページに描画します。
特性関数を設定するには、まず平面内の 2 点間のユークリッド距離を計算する関数が必要です。この関数は次のように実装されます:
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 は半径です。
したがって、TypeScript での Disk の実装は次のようになります:
npm install
HTML5 ページでセットを表示するために、ユークリッド平面でセットを描画する関数描画を実装することにしました。 HTML5 を選択したため、描画には Canvas 要素を使用しました。
したがって、メソッド描画を通じて、以下に示す ユークリッド平面 を構築しました。
飛行機の実装の下。
npm run numbers
描画関数では、ユークリッド平面コンテナと同じ幅、同じ高さのキャンバスが作成されます。次に、キャンバスのピクセル (x,y) 単位の各点がセットに属している場合は黒い点に置き換えられます。 xMin、xMax、yMin、および yMax は、上の ユークリッド平面 の図に示されている境界値です。
以下のコードを実行します:
npm run plane
ここで、disk はキャンバスの ID です:
npm run fractals
は次の結果を返します:
水平 または 垂直 半平面は、平面がユークリッド空間を分割する 2 つの部分集合のいずれかです。 水平半平面は、上の図のように、Y 軸に垂直な線を通してユークリッド空間を分割する 2 つのサブセットのいずれかです。 垂直半平面は、X 軸に垂直な線を通してユークリッド空間を分割する平面の 2 つのサブセットのいずれかです。
このセクションでは、水平 と 垂直 の半面の 特徴的な関数 を設定し、HTML5 ページに描画して、どのような機能があるかを確認します。これらを ディスク サブセットと組み合わせれば可能です。
horizontalHalfPlane を 水平 半平面の 特性関数 とします。 TypeScript での horizontalHalfPlane の実装は次のとおりです:
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 を 垂直 半平面の 特性関数 とします。 TypeScriptでのVerticalHalfPlaneの実装は次のとおりです:
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` と 2 番目のユークリッド次元のデルタ距離である `deltay` をパラメータとして受け取ります。点 _P (x, y)_ がセット _S_ 内で変換される場合、その座標は _(x', y') = (x, delatx, y, deltay)_ に変わります。したがって、点 _(x' - delatx, y' - deltay)_ は常に集合 _S_ に属します。集合代数では、「翻訳」は同型と呼ばれます。言い換えれば、すべての翻訳の集合は、空間自体と同型である _translation グループ T_ を形成します。これは関数の主なロジックを説明します。 したがって、HTML5 ページで以下のコードを実行します。
const empty = () => (e: T) => false
ep_op はキャンバスの ID です:
console.log('\nEmpty set:') console.log('Is 7 in {}?', common.empty()(7))
は次の結果を返します:
scalePoint を、セグメント SN が SM と同じ線上になるように、任意の点 M を別の点 N に送信する関数とします。 ですが、係数 λ でスケーリングされます。集合の代数では、スケールは次のように定式化されます:
したがって、TypeScript での実装は次のようになります:
npm install
ここで、(deltax, deltay) は平行移動の定数ベクトル、(lambdax, lambday) はラムダ ベクトルです。
スケールを計画内のセットに相等性を適用する関数とします。この関数は、TypeScript で次のように単純に実装されます。
npm run numbers
scale は、最初のユークリッド次元のデルタ距離である deltax、2 番目のユークリッド次元のデルタ距離である deltay、および定数因子ベクトル λ である (lambdax, lambday) をパラメーターとして受け取ります。点 P (x, y) が集合 S のスケールを介して変換される場合、その座標は (x', y') = (lambdax *) に変わります。 x、delatx、lambday * y、deltay)。したがって、点 ((x'- delatx)/lambdax, (y' - deltay)/lambday) は、ラムダがベクトルと異なる場合、常に集合 S に属します。もちろん0です。集合の代数では、スケールは同型と呼ばれます。言い換えれば、すべての相同性の集合は、空間自体 {0} と同型である 相同群 H を形成します。これは関数の主なロジックを説明しています。
したがって、HTML5 ページで以下のコードを実行します。
npm run plane
は次の結果を返します:
rotatePoint を角度 θ で点を回転する関数としましょう。行列代数では、rotatePoint は次のように定式化されます。
ここで、(x', y') は回転後の点の座標であり、x' と y' の式は次のとおりです。以下のように:
この公式の実証は非常に簡単です。このローテーションを見てください。
デモの下:
したがって、TypeScript での実装は次のようになります:
npm install
角度 θ の平面内のセットに回転を適用する関数を回転とします。この関数は TypeScript で次のように単純に実装されます。
npm run numbers
rotate は、回転角度である theta をパラメータとして取る関数です。点 P (x, y) がセット S 内で回転によって変換される場合、その座標は (x', y') = (x * cos(シータ) - y * sin(シータ)、x * sin(シータ)、y * cos(シータ))。したがって、点 (x' * cos(theta), y' * sin(theta), y' * cos(theta) - x' * sin(theta)) は常に集合 す。集合の代数では、回転は同型と呼ばれます。言い換えれば、すべての回転の集合は、空間自体と同型である 回転群 R を形成します。これは関数の主なロジックを説明しています。
したがって、HTML5 ページで以下のコードを実行します。
npm run planeは次の結果を返します:
さらに上を目指したい人へ
フラクタルは、通常は位相次元を超え、整数の間に入る可能性があるフラクタル次元を持つ集合です。たとえば、
マンデルブロ セットは、複素 2 次多項式の族によって定義されるフラクタルです。
npm run fractalsここで、c は複合体です。
マンデルブロ フラクタルは、上記の数列が無限に逃げないように、すべての点 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マンデルブロ フラクタル
マンデルブロ フラクタル (抽象データ型表現) P(z) = z^2 c を作成しました。これは以下で利用可能です。
npm install_Complex_ 数値を描画できるようにするために、`ComplexPlane` クラスを作成しました。以下はTypeScriptでの実装です。
npm run numbers
したがって、以下のコードを実行します:
npm run plane
ここで、フラクタルはキャンバスの ID です:
npm run fractals
は次の結果を返します:
さらに詳しく知りたい方は、以下をご覧ください:
それだけです!楽しんで読んでいただければ幸いです。
以上がTypeScript での関数型プログラミングの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。