型システムとは何ですか?


50

バックグラウンド

私はサイドプロジェクトとして言語を設計しています。動作するアセンブラー、静的アナライザー、それに仮想マシンがあります。構築したインフラストラクチャを使用して、重要なプログラムを既にコンパイルおよび実行できるため、大学でプレゼンテーションを行うことを考えました。

私の話の中で、私はVMが型システムを提供することについて言及しました、「あなたの型システムは何のためにあるのですか?」答えた後、私は質問をする人に笑われました。

したがって、この質問をすることで評判を失うことはほぼ確実ですが、プログラマーに頼ります。

私の理解

私が理解しているように、型システムはプログラム内のエンティティに関する追加情報の層を提供するために使用されるため、ランタイム、コンパイラー、またはその他の機械は、操作対象のビット文字列をどう処理するかを認識します。また、コントラクトの維持にも役立ちます。コンパイラ(またはコードアナライザー、ランタイム、またはその他のプログラム)は、プログラマーが期待する値でプログラムが動作することをいつでも検証できます。

タイプは、それらの人間のプログラマーに情報を提供するためにも使用できます。たとえば、次の宣言を見つけます。

function sqrt(double n) -> double;

これよりも便利

sqrt(n)

前者は多くの情報を提供します:sqrt識別子は関数であり、double入力として単一のものを取り、double出力として別のものを生成します。後者は、おそらく単一のパラメーターを取る関数であることを示しています。

私の答え

それで、「あなたのタイプシステムは何のためですか?」私は次のように答えました:

型システムは動的です(型は値を保持する変数ではなく値に割り当てられます)が、意外な強制ルールがなければ強力です(互換性のない型を表すため、文字列を整数に追加できませんが、浮動小数点数に整数を追加できます) 。

タイプシステムは、命令のオペランドが有効であることを確認するためにVMによって使用されます。また、プログラマーは、関数に渡されたパラメーターが有効(つまり、正しい型)であることを確認するために使用できます。
型システムは、サブタイピングと多重継承をサポートしています(プログラマーは両方の機能を使用できます)。オブジェクトのメソッドの動的ディスパッチが使用される場合、型は考慮されます。

次の質問は、「タイプは値にどのように割り当てられますか?」でした。そこで、すべての値がボックス化され、タイプの名前、応答するメッセージ、および継承するタイプに関する情報を提供するタイプ定義構造を指すポインターがあることを説明しました。

その後、私は笑われ、「それは本当のタイプシステムではない」というコメントで私の答えは却下されました。

だから-私が説明したものが「実際のタイプシステム」として適格でない場合、どうなりますか?その人は、私が提供するものを型システムと見なすことができないということは正しいのですか?


19
型システムについて話すとき、彼らは通常静的型付けについて話します。動的型付けは、ほとんど何も保証されないため、型システムに関心がある人にとってはあまり興味深いものではありません。たとえば、変数xはどのような値を保持できますか?何でも。
ドーバル

7
私は、彼らの反応を弁護/説明するために彼らが言わなければならなかったことを聞きたいです。
ニュートピアン

18
@Doval動的型付けは、猫に5を追加するなどのことを行うことで、無意味な状態に陥らないようにすることができます。確かに、それはあなたが試みることを妨げることはありませんが、少なくとも実際に起こることを止め、何が間違っていたかを理解し、是正措置をとる機会を与えることができます。
8ビットツリー

10
その人は、「値に型をどのように割り当てるのか」というあなたの答えに問題を抱えました。彼らは、ボックスとポインターの図ではなく、入力規則について聞きたいと思っていました。笑いは絶対に失礼でした。
ガーデンヘッド

10
笑う人は強い型システムを持つ特定の言語(家族)の熱狂者である可能性が高く(Haskellは人気があるようです)、それよりも弱い(したがっておもちゃ)、またはそれより強い(したがって非実用的)ものをrid笑します。または単に異なる。狂信者と議論することは危険で無駄です。そのような笑いはあまりにも失礼なので、この種のより深い問題を示しています。彼らが説教を始めなかったのは幸運です
ハイド

回答:


30

それはすべて、タイプシステムが提供するものの詳細な説明のように思えます。そして、あなたの実装は、それがしていることに対して十分に妥当なもののように聞こえます。

一部の言語では、言語はランタイムディスパッチを実行しないため(または、vtablesまたは別のメカニズムを介して単一のディスパッチを実行するため、型情報は必要ありません)、ランタイム情報は必要ありません。一部の言語では、名前や継承ではなく型の等価性のみを考慮しているため、シンボル/プレースホルダーさえあれば十分です。

あなたの環境によっては、その人はあなたの型システムにもっとフォーマリズムを求めているかもしれません。彼らは、あなたができるかを知りたい証明プログラマが何をすることができない、それでやることに。これは残念ながら学界ではかなり一般的です。学者はそのようなことをしますが、それはあなたの型システムに、物事が正しさを逃れることを許す欠陥があるのは非常に簡単だからです。これらのいずれかを発見した可能性があります。

さらに質問がある場合、Types and Programming Languagesはこの主題に関する標準的な本であり、学者が必要とする厳密さの一部と、物事を説明するための用語の一部を学ぶのに役立ちます。


3
「あなたの環境によっては、その人はあなたの型システムにもっと形式主義を望んでいたかもしれません。」おそらくそれだけです。型システムで証明できることに集中するのではなく、ツールとして考えました。本の推薦をありがとう!
マエル

1
@Mael一部の型システムは、ロジックとして使用されます(論理フレームワークを参照)。これは基本的タイプが式を与え、プログラムはこれらの式の証明されている(例えば、機能タイプは、a -> bと見ることができ、Bを意味し、あなたが私のタイプの値が得られた場合、つまりa、私は型の値を取得することができますがb)。ただし、これが一貫しているためには、言語が完全である必要があり、したがってチューリングが完全ではありません。そのため、実際の型システムはすべて、一貫性のないロジックを実際に定義しています。
バクリウ

20

特に、形式主義へ​​の学問的関心に言及しているため、@ Telastynの回答が気に入っています。

ディスカッションに追加させてください。

型システムとは何ですか?

型システムは、不正なプログラム状態を定義、検出、および防止するためのメカニズムです。制約を定義して適用することで機能します。制約の定義はtypesであり、制約の適用はtypeの使用法です(変数宣言など)。

タイプ定義は通常、合成演算子をサポートします(たとえば、構造、サブクラス化、および列挙、ユニオンなどの選言など、さまざまな形の接続詞)。

制約、型の使用法により、合成演算子も許可される場合があります(たとえば、少なくともthis、正確にthis、thisまたはthat、何か他の条件が満たされる場合)。

型システムが言語で使用可能であり、コンパイル時にエラーを発行できるという目的に向けてコンパイル時に適用される場合、それは静的な型システムです。これらは、多くの違法プログラムがコンパイルされるのを防ぎ、実行を許可しません。したがって、違法プログラムの状態を防止します。

(静的型システムは、プログラムが文句を言う不健全なコードに到達することがわかっているかどうかにかかわらず、プログラムの実行を停止します。静的型システムは、ある種のナンセンス(宣言された制約の違反)を検出しますプログラムが実行される前にエラーであると判断します。)

型システムが実行時に適用される場合、それは不正なプログラム状態を防止する動的型システムです。ただし、最初に実行されるのを防ぐのではなく、実行中にプログラムを停止します。

かなり一般的なタイプシステムの提供は、静的機能と動的機能の両方を提供することです。


いわゆるハイブリッドタイプのシステムはあまり一般的ではないと思います。どの言語を考えていますか?
ガーデンヘッド

2
@gardenhead、ダウンキャストする機能は静的な型システム機能ではないため、通常は実行時に動的にチェックされます。
エリックエイド

1
@gardenhead:ほとんどの静的に型付けされた言語では、Cのvoid *ポインター(非常に弱い)、C#の動的オブジェクト、またはHaskellの実存的に定量化されたGADT(他のほとんどの静的に型付けされた値よりもかなり強い保証を与える)言語)。
左辺り

確かに、「キャスティング」を忘れていました。しかし、キャスティングは弱い型システムの単なる松葉杖です。
ガーデンヘッド

@gardenhead動的オプションを提供する静的言語と同様に、多くの動的言語は静的型付けを提供します。たとえば、Dart、Python、およびHackにはすべて、「段階的な入力」の概念に基づいて静的分析を実行するためのモードまたはツールがあります。
IMSoP

14

ああ、私はできる限りこの質問に答えようとしています。考えをきちんと整理できることを願っています。

@Dovalが言及し、質問者が(無作法ではありますが)指摘したように、あなたは本当に型システムを持っていません。タグを使用した動的チェックのシステムがありますが、これは一般的にはるかに弱く、あまり面白くありません。

「型システムとは」という質問は非常に哲学的である可能性があり、この問題に関するさまざまな視点で本を埋めることができます。ただし、これはプログラマ向けのサイトであるため、回答をできる限り実用的なものにしようとします(実際、型はプログラミングで非常に実用的です。

概要

より正式な基盤に飛び込む前に、型システムが何に適しているかを理解することから始めましょう。型システムはプログラムに構造を課します。さまざまな関数と式を一緒にプラグインする方法を教えてくれます。構造がなければ、プログラムは受け入れられず、非常に複雑で、プログラマのわずかな間違いで危害を加える準備ができています。

型システムを使用したプログラムの作成は、ブレーキが作動したり、ドアが安全に閉まったり、エンジンに油が注がれたりなど、未使用状態で注意を払うようなものです。スパゲッティから。あなたは絶対にコントロールできません。

議論を土台にするために、リテラル表現num[n]str[s]、それぞれ数値nと文字列sを表す言語、および意図された意味を持つプリミティブ関数plusand 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つのアプローチがあります:表示的意味論操作的意味論。表示的意味論は、プログラムを基礎となる数学的構造(自然数、連続関数など)にマッピングすることでプログラムを記述します。それは私たちのプログラムに意味を提供します。それどころか、操作上のセマンティクスは、プログラムの実行方法を詳述することでプログラムを定義します。私の意見では、運用上のセマンティクスはプログラマー(私自身を含む)にとってより直感的であるため、これに固執しましょう。

正式な操作上のセマンティクスを定義する方法は説明しません(詳細は少し複雑です)が、基本的には次のようなルールが必要です。

  1. num[n] 値です
  2. str[s] 値です
  3. もしnum[n1]およびnum[n2]整数に評価n_1$ and $n_2$, then整数$ N_1 + N_2 $にプラス(NUM [N1]、NUM [N2]) `評価します。
  4. 場合str[s1]str[s2]S1とS2の文字列に評価され、その後、concat(str[s1], str[s2])文字列S1S2と評価されます。

等ルールは実際にはもっとフォーマルですが、要点は分かります。しかし、すぐに問題が発生します。以下を書くとどうなりますか:

concat(num[5], str[hello])

ふむ これは非常に難問です。数字と文字列を連結する方法については、どこにもルールを定義していません。このようなルールの作成を試みることもできますが、この操作は無意味であることを直感的に知っています。このプログラムを有効にしたくありません。したがって、容赦なく型に導かれます。

タイプ

プログラムは、言語の文法によって定義されるツリーです。プログラムには、実行規則によって意味が与えられます。ただし、一部のプログラムは実行できません。つまり、一部のプログラムは無意味です。これらのプログラムは不適切なタイプです。したがって、タイピングは言語の意味のあるプログラムを特徴づけます。プログラムの型が適切であれば、実行できます。

いくつか例を挙げましょう。繰り返しになりますが、評価規則と同様に、非公式に入力規則を提示しますが、厳密にすることができます。以下にいくつかのルールを示します。

  1. フォームのトークンのnum[n]タイプはnatです。
  2. フォームのトークンのstr[s]タイプはstrです。
  3. expression e1にtypeがnatあり、expression e2にtype natがある場合、式にplus(e1, e2)はtypeがありnatます。
  4. 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は違います。

結論

型には他のビューがあります。ある意味での型は直観主義的論理に対応しており、カテゴリー理論の対象として見ることもできます。これらの接続を理解することは魅力的ですが、単にプログラミング言語を記述したり、設計したりするだけの場合には不可欠ではありません。ただし、プログラミング言語の設計および開発には、プログラムの構成を制御するツールとして型を理解すること不可欠です。私は型が表現できるものの表面をかじっただけです。それらがあなたの言語に組み込むのに十分価値があると思うことを願っています。


4
+1。ダイナミックなタイピング愛好家がこれまでに引っ張った最大のトリックは、タイプシステムなしで「タイプ」を持つことができる世界を納得させることでした。:-)
ruakh

1
以来、あなたは自動的に何も面白い確認することはできません任意のプログラムのために、すべてのタイプのシステムは、キャスト演算子(あるいは道徳的同等)を提供しなければならない、またはそうでなければチューリング完全を生け贄に捧げます。もちろんこれにはHaskellも含まれます
ケビン

1
@Kevinライスの定理はよく知っていますが、あなたが思うほど関連性はありません。そもそも、プログラムの大部分は無制限の再帰を必要としません。GodelのSystem Tなど、プリミティブな再帰のみを使用する言語で作業する場合、型システムを使用して、停止などの興味深いプロパティを検証できます。現実世界のほとんどのプログラムはかなり単純です-実際にキャストする必要があった最後の時間を考えることはできません。チューリングの完全性は過大評価されています。
ガーデンヘッド

9
「ダイナミックタイピングは本当にタイピングではありません」は、クラシックミュージシャンが「ポップミュージックは本当に音楽ではない」と言ったり、福音主義者は「カトリックは実際にクリスチャンではない」と言っていました。はい、静的型システムは強力で魅力的で重要であり、動的型付けは異なるものです。しかし、(他の答えが説明しているように)伝統的に型付けと呼ばれ、重要な共通点を共有する静的な型システム以外にもさまざまな有用なものがあります。私たちの種類の入力を真の入力として主張する必要があるのはなぜですか?
ピータールファヌラムスデイン16年

5
@IMSoP:本よりも短いものについては、Chris Smithのエッセイタイプシステムについて議論する前に知っておくべきことは素晴らしいです。
ピータールファヌラムスデイン16年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.