数学の型システム

時々、数学の質問を思いつきます。それはある意味で「文法的に間違っている」と言うことができます。



例。 「間隔 [ 0 1 ] 閉じているか開いていますか?」

例。\ {1、2、3 \}\ {1、2、3 \} グループ?」

例。 「フーリエ級数とは  s i n x + s i n p i x   ?」



そして、さらに愚かな例があります。



例。 「長方形は単純ですか?」

例。3ドルで17ドル ?」

例。 「空集合のフーリエ級数とは何ですか?」



これらすべての例を統一しているのは、 タイプミスであるということです。これらは、特定の数学的プロセスを数学的オブジェクトに適用する試みであり、決して入力することはできません。 これらの質問に答えるために、高度に数学的なプログラミング言語でプログラムを作成しようとすると、コンパイルされません。



数学オブジェクトは通常、型システムを持つプログラミング言語のオブジェクトと同じ意味で型を持っていると明確に認識されません。 通常の数学は、おそらく選択の公理を用いて、Zermelo-Frenkel (ZF)システムで形式化される必要があり、ZFでは、各数学オブジェクトはセットとして構築されます。 この意味で、これらのオブジェクトはすべて同じタイプです。 (特に、質問「 3ドルで17ドル 「ZFでは非常に論理的です!そして、これが数学の基礎としてZFを好まない理由の1つです。)しかし、実際には数学的なオブジェクトは暗黙的に型を持っていると認識され、数学者はこの考え方を学びますが、あまり議論されません。



集合論の観点から推論する代わりに、数学オブジェクトに型があると考える価値があります。これにより、 タイプセーフティ キャストサブタイプオーバーロードの概念など、さまざまな有用な概念を数学にインポートできます。 「数学的文。 この記事の残りの部分では、これらおよびその他のタイプ関連の概念が数学全般にどのように適用されるかについて、ゆったりと説明します。 記事には多くのカテゴリ概念がありますが、理解を簡単にするために、括弧で囲んだメモに限定します。



数学タイプの非公式な説明



非公式には、数学的オブジェクトのタイプはこのオブジェクトのさまざまなことを説明していると言えます。



例。 対象 2 タイプがあります  t e x t t t N a t (自然数)。

例。 対象 - 2 タイプがあります  t e x t t t I n t (整数)。

例。 対象  f r a c 1 2 タイプがあります  T E X T トントン (有理数)。

例。 対象 2 3 タイプがあります  textttNat\回 textttNat (自然数のペア)。

例。 対象 30 circ タイプがあります  textttDeg (度)。

例。 対象 x mapstox2 タイプがあります  textttNat\か textttNat (関数は自然数から自然数にマップされます)。

例。 対象  texttttrue タイプがあります  textttBoolブール )。



以下に簡単な例を示します。



例。 対象  mathbbZ タイプがあります  textttGrp (グループ)。

例。 対象 S2 タイプがあります  texttt (トポロジ空間)。

例。 対象 X mapstoH1X タイプがあります  texttt to textttGrp (関数はトポロジ空間からグループにマッピングされます)。



型は、数学オブジェクトのセットで実行できるアクションを理解するのに役立ちます。



例。 タイプの2つのオブジェクトを取ることができます  textttNat それらを追加または乗算します。 言い換えれば、機能があります +\回 textttNat times textttNat\か textttNat

例。 タイプの2つのオブジェクトを取ることができます  textttInt 加算と乗算に加えて、それらを減算します。 言い換えれば、機能があります +\回 textttInt\回 textttInt\か textttInt

例。 次のようなオブジェクトを取ることができます  textttDeg 三角関数を適用します。 言い換えれば、機能があります  textttsin textttcos textttDeg\か textttReal

例。 もし  textttA textttB 型である場合、あなたは型のオブジェクトを取ることができます  textttA および別のタイプのオブジェクト  textttA to textttB 後者を最初に適用します。 言い換えれば、機能があります  texttteval textttA\回 textttA to textttB to textttB



種類  textttBool この理論では特別な場所を占めています。 このタイプのオブジェクトは2つだけです。つまり、  texttttrue そして  textttfalse 、および出力で値を与える関数  textBool 、プロパティがtrueかどうかを確認するために使用できます。



例。 自然数を取り、それが素数であるかどうかを尋ねることができます。 言い換えれば、機能があります  textttisPrime textttNat to textttBool

例。 もし  textttA 型である場合、その型の2つのオブジェクトを取得できます  textttA それらが等しいかどうか尋ねます。 言い換えれば、機能があります







 displaystyle textttisEqual textttA times textttA to textttBool







等号で書くこともできます =

例。 2つの整数を使用して、最初の整数が2番目の整数以上かどうかを確認できます。 言い換えれば、機能があります







 ge textttInt times textttInt to textttBool







これらの例が示すように、型を組み合わせて新しい型を作成する方法は多数あります。 それらは型コンストラクタと呼ばます。

例。 タイプproductのオブジェクト  textttA\回 textttB タイプのオブジェクトのペアです  textttA そして  textttB

例。 タイプサムを持つオブジェクト  textttA+ textttB isまたはタイプのオブジェクト  textttA 、またはタイプのオブジェクト  textttB

例。 機能型オブジェクト  textttA to textttB また時々書かれた  textttB textttA タイプのオブジェクトを受け取る関数です  textttA タイプのオブジェクトを返す  textttB



(これらの構造はカテゴリー理論の愛好家には馴染みがあるように見えるかもしれません。つまり、それらはすべて積、共積、指数関数にすぎません。つまり、型カテゴリーは双直交閉カテゴリーです。)



上記の単純な型コンストラクターを使用して、より複雑な型コンストラクターを作成できます。 たとえば、タイプを持つ  textttA リストタイプを作成できます  texttt[A] これは、型の要素の(有限)リストの型です  textttA







 displaystyle texttt[A]= texttt1+ textttA+ textttA\回 textttA+ textttA\回 textttA\回 textttA+...







(どこ  texttt1 -これはユニットタイプと呼ばれる特別なタイプです。 その定義的な特性は、ユニット型オブジェクトが1つしかないことです(これをポイントと呼びます)。 発見的には、リストタイプは「幾何級数」として記述できます。  frac texttt1 texttt1 textttA



表記システム



上記のエントリを使用しました  textttf textttA to textttB それを示すために  textttf タイプのオブジェクトでした  textttA to textttB 。 このエントリを任意の型に一般化して、  texttta textttA ということです a タイプのオブジェクトです  textttA 。 これは型宣言になります。



タイプセーフティとタイピングエラー



数学的オブジェクトのセットで何ができるかを理解するのに役立つことに加えて、型は、何ができないかを理解することも可能にします。 この考えを考慮して、投稿の冒頭に示した例を見てみましょう。



例。\ {1、2、3 \} グループ?」

例。 「フーリエ級数とは  sinx+ sin pix ?」



例。 「間隔 [01] 閉じているか開いていますか?”関数  textttisClosed そして  textttisOpen 入り口で多数のまたは地形的なスペースを受け取ることはできません。 入力ペアを取得します XS どこで X 位相空間であり、 S -部分空間 X (そして、 S 閉じたサブセットまたは開いたサブセット X ) 言い換えれば、それらはタイプではありません  textttTop to textttBool 、およびタイプ  texttt to textttBool 。 質問は [01] 開いているか閉じているかは、それがそれ自体のサブセットと見なされるか、たとえば  mathbbR



例。\ {1、2、3 \} グループ?”機能  textttisGroup 入り口はあまりありません 彼女はペアの入力を取得します X cdot どこで X たくさんあり、  cdot -バイナリ演算 Xマグマ )。 つまり、そうではありません  textttSet to textttBool 、およびタイプ  textttMagma to textttBool



例。 「フーリエ級数とは  sinx+ sin pix ?”機能  textttFourierSeries 入力関数を受信しません  mathbbR ; 入力で周期関数を受け取ります  mathbbR たとえば、ピリオド付き 2 pi または、同様に、上の関数  sinx+ sin pix どんな周期でも周期的ではありません。 言い換えれば  textttFourierSeries タイプがありません  textttReal to textttComplex to textttInt to textttComplex 、およびタイプ  textttCircle to textttComplex to textttInt to textttComplex



より愚かな例も同様に分析できます。



型エラーの検索、または型チェックは 、コンパイラが型エラーを探してコードをデバッグするのと同じ方法で数学計算をデバッグするのに役立ちます。 たとえば、次の形式の式が表示された場合 a=b 、その真実をチェックする前に、それが意味をなすかどうかを確認することができます。 a そして b 1つのタイプがあります。 これは、 ディメンション分析の非常に一般化されたバージョンです



型チェックは、新しい数学的トピックを理解する方法でもあります。 必要なトピック(主題を知っている他の人が決定できる)で正しく型付けされた文をまだ発音できない場合、この領域の基本的なオブジェクトまたは機能のタイプはまだわかりません。 たとえば、「基本グループ...」と言う場合、文を「point topological space」または「linearly connected topological space」というフレーズで終了する必要があります。 そうでない場合、基本グループを決定する重要な側面、つまりベースポイントの役割を理解できません。



型キャスト、サブタイピング、およびオーバーロード



型チェックは、ほとんどの数学的オブジェクトが自然にいくつかの型を持っていると考えられる非自明なタスクによって実行できます。 たとえば、上記の番号 2 タイプがあります  textttNat しかし、タイプがあることも明らかです  textttInt textttRat textttReal そしてさらに  textttComplex 。 この状況を説明する1つの方法は型変換機能を通してです。







 displaystyle textttNat to textttInt to textttRat to textttReal to textttComplex







オブジェクトを異なるタイプに変換します。 キャスト演算子がある場合  textttA to textttB 、その後、次のようなオブジェクトを使用できます  textttA 型のオブジェクトを期待する関数への入力として  textttB 最初に型変換を実行する場合。



この状況を説明する別の方法は、一部のタイプが他のタイプのサブタイプであることです。 言い換えれば、上記の状況は、一連の型変換関数の代わりに、サブタイプの包含の連鎖を説明しています。 サブタイプを作成すると、オブジェクトが同時に複数のタイプを持つことができ、一部の計算の特定の時点で特定のタイプになることはできません。



サブタイプは、機能タイプと興味深い関係があります。 もし  textttB サブタイプです  textttB 次に機能タイプ  textttA\か textttB サブタイプです  textttA to textttB でも  textttA サブタイプです  textttA (タイプのオブジェクトを出力する関数  textttB タイプのオブジェクトも生成します  textttB )、機能タイプ  textttA to textttB サブタイプではなくスーパータイプ  textttA to textttB (タイプのオブジェクトを受け取る関数  textttA タイプのオブジェクトも受け取ることができます  textttA ) つまり、機能タイプの作成は、出力タイプで共変ですが、サブタイプに関連する入力タイプでは反変です。



(これはカテゴリー理論の愛好家にもおなじみのはずです:この現象は、指数オブジェクトの作成が最終オブジェクトでは共変関数であるが、元のオブジェクトでは反変関数であるという事実を反映しています。)



この状況を説明する3番目の方法は、数学の関数が過負荷になることであり、この説明はおそらく数学的実践に最も近いでしょう。 オーバーロードとは、同じ名前を持つが異なるタイプの入力データを受け取る関数を定義する方法です。 たとえば、追加記号 + 1つではなく、同じ名前を持つ複数の関数を指します。







+ textttNat times textttNat to textttNat











+ textttInt times textttInt to textttInt











+ textttRat times textttRat to textttRat











+ textttReal times textttReal to textttReal











+ textttComplex times textttComplex to textttComplex







などなど。 より一般的には使用できます + 任意のリングでの加算操作、さらに一般的には、任意のアーベル群のグループ化操作。 金額の種類を示すために上記で使用しました!



記録付き ab もっとひどいです 次のタイプの機能を参照できます。







 displaystyle textttNat times textttNat to textttNat











 displaystyle textttPosReal times textttReal to textttReal











 displaystyle textttPosReal times textttComplex to textttComplex







またはさらに一般化 a グループの要素であり、 b 全体または a たぶん e 、そして b は要素になる可能性があり、指数表記を使用して機能タイプを示すことさえできました! math.SEのこの質問も参照してください。



過負荷は学生を混乱させるように思われますが、その理由の一部は、数学者がそれを適用する際にそれについて明示的に話すことはめったにないからだと思います。 オーバーロードは、そのすべての異なるインスタンスが少なくとも論理的に相互に接続されている限りそれほど悪くはありませんが、「通常」や「正しい」などの歴史的な理由以外の理由で数学的な概念がオーバーロードされる場合があります。 これは生徒をさらに混乱させます。たとえば、「通常の展開」と「通常のサブグループ」などの論理的な接続のために2つの異なるコンテキストで1つの単語が使用される場合もあります。 MOに関するこの質問も参照してください。



再帰型



型理論では、いくつかの型を再帰的に定義することができます。他の型に直接関連するのではなく、自分自身に対して相対です。 したがって、驚くほど多くの重要なタイプの数学的オブジェクトを識別できます。



例。 種類  textttNat の自然数は再帰的に次のように定義できます







 textttNat= texttt1+ textttNat







つまり、自然数は点(つまり 1 )、または別の自然数(つまり、前の自然数)。



例。 より一般的には、リストタイプ  texttt[A] 再帰的に定義できます







 displaystyle texttt[A]= texttt1+ textttA times texttt[A]







すなわち、型の要素のリスト  textttA 点またはタイプの要素のいずれかです  textttA (つまり、リストの先頭)と型の要素のリスト  textttA (つまり、リストの残りの部分)。 特に  textttNat 単なるタイプです  texttt[1] ポイントのリスト。 これは、「幾何級数」が満たすべき比率であることに注意してください  frac texttt1 texttt1 textttA



例。 種類  texttt (完全にバイナリ)ツリー(ルート付き)は、再帰的に







 displaystyle textttTree= texttt1+ textttTree times textttTree







つまり、ツリーはポイントまたはツリーのペア(つまり、ルートを削除して取得したツリーのペア)です。



例。 バラエティータイプ  texttt セットは次のように再帰的に定義できます







 displaystyle textttSet= textttSet to textttBool







つまり、セットは、true(セットに含まれる要素の場合)またはfalse(セットに含まれない要素の場合)を返すセット関数です。



例。 種類  texttt (オプションで有限) 組み合わせゲームは、次のように再帰的に定義できます。







 displaystyle textttGame= textttGame to textttBool times textttGame to textttBool







つまり、ゲームは名前を付けることができるいくつかのゲーム機能です  textttL そして  textttR 。 厳密に言えば、コンビナトリアルゲームは、ゲーム内の特定の瞬間(チェスゲームの開始など)を記述し、通常ゲームと呼ばれるもの(チェスなど)ではなく、ゲームの位置と呼ぶ必要があります。 私たちは、ゲームを2人が左右にプレイするものと見なします。ゲームのどの位置でも、左にはゲームを移動できる位置、つまり、  textttL trueを返します。また、正しいものには、移動できるゲームの位置、つまり、  textttR trueを返します。



コンウェイは、組み合わせゲームは序数(序数のセットに関して記述できる)とDedekindセクション(一対の有理数のセットで記述できる)の両方の一般化に似ていることに注意しました。 彼はこの接続を使用して、ゲームを使用して大きなクラスの数値を定義しました。 詳細については、 数字とゲームをご覧ください。



以前に定義したタイプ  textttSet= textttSet to textttBool 、また、 公平なゲームのタイプとして知覚することができます。つまり、可能な動きがどのプレイヤーがプレイしているかに依存しないゲームです。



(カテゴリー理論の愛好家の場合:再帰型は、対応する型カテゴリーの内積関数に関する初期代数です。)



入力で再帰型を受け取る関数も再帰的に定義できます。 自然数の例はすでにおなじみのはずです。 他の例を次に示します。



例。 リストの長さは、次のように再帰的に決定できます。ポイントの長さは 0 。 リストがポイントではない場合、リストは要素とサブリストで構成され、リストの長さはサブリストの長さよりも1つ長くなります。 (これを擬似コードで書くことはできましたが、WordPressを使用してサイトに擬似コードを表示する明確な方法はわかりません。)



例。 より一般的には、任意の2つのタイプ  textttA textttB 機能があります







 textttmap textttA to textttB to texttt[A] to texttt[B]







mapと呼ばれる、入力で関数を受け取る  textttf textttA to textttB 、および出力関数は  textttmapf texttt[A] to texttt[B] 、再帰的に次のように定義されます。入力リストが空の場合、出力リストは同じです。 それ以外の場合、入力リストはタイプのオブジェクトで構成されます  textttA そしてサブリストも  textttmapf 適用する  textttf オブジェクトに  textttmapf サブリストに追加し、それらすべてをまとめて終了リストを作成します。 関数リストの長さは、以下を適用することにより取得されます  textttmap ユニークな機能へ  textttA to texttt1



(カテゴリー理論のファンは、実際、リストコンストラクターがこのエントリのファンクターであることがわかります。この事実を認識して使用するHaskellのようなプログラミング言語さえあります。)



例。 ツリーの高さは、次のように再帰的に決定できます。ポイントの高さは 0 。 ツリーがポイントでない場合、2つのサブツリーがあり、ツリーの高さはそのサブツリーの最大高さよりも1つ大きくなります。



例。 完了が保証されているゲームは、4つの互いに素なクラスに分類できます。ゲームは





ここで、「勝利」とは、通常のゲームで、最初のプレイヤーが負けて誰が移動できないかでの勝利を指します。上記のクラスは4つの関数に対応します







isPositiveisNegativeisZeroisFuzzyゲームBool







次のように、相互に再帰的に定義できます。





(カテゴリー理論の愛好家にとって:再帰的に定義された関数は初期代数の普遍的な性質の応用です。)



再帰型は数学に型システムがあると信じるもう一つの理由です。帰納法を使用してそれを書くNat)または場合によっては半無限帰納(変更に対する再帰セットそれどころか、再帰型は構造誘導の一般的な記録を提供します。多くの場合、通常の帰納法に必要な構造帰納のケースを減らすことができます(たとえば、樹木に対して構造帰納を行いたい場合は、頂点に対して通常の帰納を行うことができます)が、概念的には、構造帰納はより明確です(たとえば、特定の頂点関数を強調せずにツリー)。



おわりに



理論上、数学は型システムを持っていると説明されることはあまりありませんが、実際には、数学をそのようなシステムを持っていると説明する方が便利で正確です。これにより、特定の種類の数学的エラー(入力エラー)を理解するための言語と、特定の暗黙的な数学的アクション(オーバーロード)を理解するための言語が提供されます。さらに、型には興味深い数学構造があり、再帰的に定義された数学オブジェクトを設定し、それらを操作するための従来の方法よりも豊富な言語を提供します。



All Articles