web-dev-qa-db-ja.com

依存型の実用的な用途はありますか?

私はこの 依存型 と呼ばれるものについて読んでいます。

たとえば、長さnの配列を返す関数firstNPrimes(int n)を想像してください。つまり、返された型はint[n]。 (依存型のない通常のプログラミング言語では、int[]ここで、型は配列の長さを指定しません。)

これがどれほど便利かはわかりません。 (最初の関数を引数として送信できる)クロス積があると仮定します。

int[3] Cross(int[3] A, int[3] B){..}

これは3次元ベクトルでのみ機能し、コンパイラはこれを型チェックしてポインタの問題を回避できます。

日常のプログラミングに役立つ、依存型の実際の使用法はありますか?それとも、それらは主に抽象的なロジックに役立つだけですか?

7
zooby

私が見逃しているのは、依存している値が3のような定数である必要がないことだと思います。長さは一般的に指定されることが多いため、正確な長さがわからない場合がありますが、戻り値とさまざまな引数。

headなど、n > 0を必要とする関数はたくさんあります。

ベクトルのサイズ内でなければならないインデックスを取る関数はたくさんあります。

たとえば内積のように、互いに同じサイズでなければならない2つのベクトルを取る関数はたくさんあります。

依存型入力を使用すると、コンパイル時にこれらの種類の制約をすべて検証し、システムのエッジで検証することができます。

19
Karl Bielefeldt

あなたが外積を持っていたと思います:

int[3] Cross(int[3] A, int[3] B){..}

これは3次元ベクトルでのみ機能し、コンパイラはこれを型チェックしてポインタの問題を回避できます。

はい、サイズが型システムの一部である場合、コンパイラはABCrossが使用されるすべての場所で正しいサイズであることを確認できます。そうでない場合はエラーになる可能性があります。 そして、それがチェックできない場合、言語デザイナーの裁量でエラーまたは警告のいずれかになります。

日常のプログラミングに役立つ、依存型の実際の使用法はありますか?

これは、実行できることを制限する機能です。 Crossに間違ったサイズの配列を渡すことはできません。そしてそれは良いことです。この機能により、言語が読みやすくなり、間違いを防ぐことができます。

さらに、情報の転送に必要なバッファーのサイズは型システムの一部であるため、自動マーシャリングに最適です。これをインターフェイスの一部として宣言できます。正しく宣言されていれば、バッファーオーバーフローの問題を回避できます。

また、コードでデータベースタイプを一致させることもできます。たとえば、指定された文字数に制限された文字列。


それとも、それらは主に抽象的なロジックに役立つだけですか?

依存型は、値によってパラメーター化される型です。 -ドラムロール-C++では常に発生します。値パラメーターを持つテンプレートを作成できます。

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

template<int N>
struct S { int a[N]; };

これは、テンプレート引数として指定されたサイズの配列メンバーを定義します。

使用例:

S<10> s; // s.a is an array of 10 int
s.a[9] = 4;

cppreferenceからの例

これが std::array の仕組みです。 std:arrayは、タイプとサイズを取るテンプレートです。 サイズを推測したい場合は make_array を使用できます。std::arrayについて読むと、それがわかりますCスタイルの配列ほど用途が少ないです。私が言っていたように、この機能はあなたができることを制限します。引き換えに、静的チェックを取得します。

C++テンプレートシステムを使用して、N次元のベクトル代数を定義できます。また、C++は特殊化をサポートしているため、すべての次元に共通ではない操作も処理できます。 たとえば、2つの2Dベクトルの外積が2Dベクトルであることは意味がありませんが、2つの2Dベクトルのくさび積は、2つの2Dベクトルの外積の長さが増加します。 3次元で0を指定しても意味がありません。


別の例として、エイダを見てみましょう。これはAdaのサブタイプ宣言です:

subtype Count_To_Ten is Integer range 1 .. 10;

上記はCount_To_Ten型を定義しています。この型のすべての値もInteger型であり、1から10までの包括的な範囲にあります。

その後

subtype Ten_Characters is String (Count_to_Ten);

上記はタイプTen_Charactersを定義し、このタイプのすべての値は文字列であり、文字のidexはCount_to_Tenであり、したがって10文字の文字列です。

この例は Ada Programming/Type Systemからの引用です。

Adaでこれらの3Dベクトルを定義できます。

type Axis is range 1 .. 3;
type Vector3 is array (Axis) of Integer;

申し分なく、正確にはそうではありませんが、Adaで定義されているVector3タイプを OpenGLAda – OpenGL binding for Ada で見つけました(インデックスに列挙型を使用し、算術演算がある限り、要素)。ええ、そうですね、これはビデオゲームという実用的な用途があります。

6
Theraot

実際の例を見てみましょう。以上、本当の火星。

NASAの火星気候オブザーバーは、ソフトウェアがメートルとフィートを混同したため、火星に衝突しました。ソフトウェアがすべての距離を単なる数値として扱ったため、これは可能でした。物理学では、数量には単位が関連付けられています。フィートとメートルは異なる単位ですが、どちらも長さで使用されます。秒とメートルは、異なる数量の異なる単位です。

C++では、これを型システムで表現できます。また、これを使用して、速度などの派生量をメートル/秒(m ins-1)と面積、平方メートル(m2)。

NASAがこれを使用したとしたら、メートルとフィートを比較できたでしょう。フィートからメートルに変換するときに、コンパイラーは適切なスケール係数を導入します。

6
MSalters