ああ、私はできる限りこの質問に答えようとしています。考えをきちんと整理できることを願っています。
@Dovalが言及し、質問者が(無作法ではありますが)指摘したように、あなたは本当に型システムを持っていません。タグを使用した動的チェックのシステムがありますが、これは一般的にはるかに弱く、あまり面白くありません。
「型システムとは」という質問は非常に哲学的である可能性があり、この問題に関するさまざまな視点で本を埋めることができます。ただし、これはプログラマ向けのサイトであるため、回答をできる限り実用的なものにしようとします(実際、型はプログラミングで非常に実用的です。
概要
より正式な基盤に飛び込む前に、型システムが何に適しているかを理解することから始めましょう。型システムはプログラムに構造を課します。さまざまな関数と式を一緒にプラグインする方法を教えてくれます。構造がなければ、プログラムは受け入れられず、非常に複雑で、プログラマのわずかな間違いで危害を加える準備ができています。
型システムを使用したプログラムの作成は、ブレーキが作動したり、ドアが安全に閉まったり、エンジンに油が注がれたりなど、未使用状態で注意を払うようなものです。スパゲッティから。あなたは絶対にコントロールできません。
議論を土台にするために、リテラル表現num[n]
とstr[s]
、それぞれ数値nと文字列sを表す言語、および意図された意味を持つプリミティブ関数plus
and concat
があるとします。明らかに、plus "hello" "world"
またはのようなものを書きたくはありませんconcat 2 4
。しかし、どうすればこれを防ぐことができますか?先験的に、数字2を文字列リテラル「world」と区別する方法はありません。言いたいのは、これらの式は異なるコンテキストで使用されるべきだということです。彼らは異なるタイプを持っています。
言語とタイプ
少し後退しましょう。プログラミング言語とは何ですか?一般に、プログラミング言語は、構文とセマンティクスの2つの層に分割できます。これらも呼ばれている静と動特性をそれぞれ。これら2つの部分間の相互作用を仲介するには、型システムが必要であることがわかります。
構文
プログラムはツリーです。コンピューターで書くテキストの行にだまされないでください。これらは、人間が読めるプログラムの表現です。プログラム自体は、抽象構文ツリーです。たとえば、Cでは次のように記述できます。
int square(int x) {
return x * x;
}
これがプログラム(フラグメント)の具体的な構文です。ツリー表現は次のとおりです。
function square
/ | \
int int x return
|
times
/ \
x x
プログラミング言語は提供文法その言語の有効木定義(具象または抽象構文のいずれかを用いてもよいです)。これは通常、BNF表記のようなものを使用して行われます。作成した言語でこれを実行したと思います。
意味論
プログラムが何であるかはわかっていますが、それは単なる静的なツリー構造です。おそらく、私たちのプログラムに実際に何かを計算させたいのです。セマンティクスが必要です。
プログラミング言語の意味論は、豊富な研究分野です。大まかに言って、2つのアプローチがあります:表示的意味論と操作的意味論。表示的意味論は、プログラムを基礎となる数学的構造(自然数、連続関数など)にマッピングすることでプログラムを記述します。それは私たちのプログラムに意味を提供します。それどころか、操作上のセマンティクスは、プログラムの実行方法を詳述することでプログラムを定義します。私の意見では、運用上のセマンティクスはプログラマー(私自身を含む)にとってより直感的であるため、これに固執しましょう。
正式な操作上のセマンティクスを定義する方法は説明しません(詳細は少し複雑です)が、基本的には次のようなルールが必要です。
num[n]
値です
str[s]
値です
- もし
num[n1]
およびnum[n2]
整数に評価n_1$ and $n_2$, then
整数$ N_1 + N_2 $にプラス(NUM [N1]、NUM [N2]) `評価します。
- 場合
str[s1]
とstr[s2]
S1とS2の文字列に評価され、その後、concat(str[s1], str[s2])
文字列S1S2と評価されます。
等ルールは実際にはもっとフォーマルですが、要点は分かります。しかし、すぐに問題が発生します。以下を書くとどうなりますか:
concat(num[5], str[hello])
ふむ これは非常に難問です。数字と文字列を連結する方法については、どこにもルールを定義していません。このようなルールの作成を試みることもできますが、この操作は無意味であることを直感的に知っています。このプログラムを有効にしたくありません。したがって、容赦なく型に導かれます。
タイプ
プログラムは、言語の文法によって定義されるツリーです。プログラムには、実行規則によって意味が与えられます。ただし、一部のプログラムは実行できません。つまり、一部のプログラムは無意味です。これらのプログラムは不適切なタイプです。したがって、タイピングは言語の意味のあるプログラムを特徴づけます。プログラムの型が適切であれば、実行できます。
いくつか例を挙げましょう。繰り返しになりますが、評価規則と同様に、非公式に入力規則を提示しますが、厳密にすることができます。以下にいくつかのルールを示します。
- フォームのトークンの
num[n]
タイプはnat
です。
- フォームのトークンの
str[s]
タイプはstr
です。
- expression
e1
にtypeがnat
あり、expression e2
にtype nat
がある場合、式にplus(e1, e2)
はtypeがありnat
ます。
- expression
e1
にtypeがstr
あり、expression e2
にtypeがあるstr
場合、expressionにconcat(e1, e2)
はtypeがありstr
ます。
したがって、これらの規則に従って、plus(num[5], num[2])
has type nat
がありますが、型をに割り当てることはできませんplus(num[5], str["hello"])
。プログラム(または式)は、任意の型を割り当てることができれば型付けが適切であり、そうでなければ型付けが不適切であると言います。型システムは、ある音すべてが順調に型付けされたプログラムを実行することができます。Haskellは健全です。Cは違います。
結論
型には他のビューがあります。ある意味での型は直観主義的論理に対応しており、カテゴリー理論の対象として見ることもできます。これらの接続を理解することは魅力的ですが、単にプログラミング言語を記述したり、設計したりするだけの場合には不可欠ではありません。ただし、プログラミング言語の設計および開発には、プログラムの構成を制御するツールとして型を理解することが不可欠です。私は型が表現できるものの表面をかじっただけです。それらがあなたの言語に組み込むのに十分価値があると思うことを願っています。