回答:
静的型システムは静的分析の一種ですが、型システムでは一般的にエンコードされない静的分析が数多くあります。例えば:
モデル検査は、並行システム用の分析および検証手法であり、すべての可能なスレッドインターリーブでプログラムが適切に動作することを証明できます。
データフロー分析は、変数の可能な値に関する情報を収集します。これにより、一部の計算が冗長であるか、一部のエラーが考慮されていないかを判断できます。
抽象解釈は、通常、分析が終了することが保証されるような方法で、プログラムの効果を控えめにモデル化します。型チェッカーは、抽象インタープリターと同様の方法で実装できます。
分離ロジックはプログラムロジック(たとえば、Inferアナライザーで使用)で、プログラムの状態について推論し、nullポインターの参照解除、無効な状態、リソースリークなどの問題を特定するために使用できます。
契約ベースのプログラミングは、前提条件、事後条件、副作用、および不変条件を指定する手段です。Adaは契約をネイティブでサポートしており、契約の一部を静的に検証できます。
最適化コンパイラは、最適化中に使用する中間データ構造(SSA、インラインコストの推定、命令ペアリング情報など)を構築するために、多くの小さな分析を行います。
非宣言的な静的分析の別の例は、Hack typecheckerにあります。ここでは、通常の制御フロー構造が変数の型を改良できます。
$x = get_value();
if ($x !== null) {
$x->method(); // Typechecks because $x is known to be non-null.
} else {
$x->method(); // Does not typecheck.
}
そして、「リファイン」と言えば、タイプシステムの土地に戻って、リファインメントタイプ(LiquidHaskellで使用される)は、「リファイン」タイプのインスタンスに対して保持されることが保証される述語とタイプをペアにします。そして、依存型はこれをさらに進め、型が値に依存できるようにします。依存型付けの「ハローワールド」は通常、配列連結関数です。
(++) : (a : Type) -> (m n : Nat) -> Vec a m -> Vec a n -> Vec a (m + n)
ここで++
は、型Vec a m
との2つのオペランドを取ります。それぞれ、Vec a n
要素の型a
と長さm
を持つベクターで、n
それぞれ自然数(Nat
)です。長さがである同じ要素タイプのベクトルを返しますm + n
。この機能は、特定の値を知ることなく、抽象的にこの制約を証明m
し、n
ベクトルの長さは、動的であってもよいので、。
int
、int -> int
、forall a. a -> a
)の用語(例えば、0
、(+ 1)
、\x -> x
)。他の分析では、副作用(pure
、io
)、可視性(public
、private
)、状態(open
、closed
)など、データタイプに関係のないさまざまなプロパティを割り当てることができます。実際には、これらのプロパティの多くは型チェック/推論と同じ実装でチェックできるため、区別は完全に明確ではありません。
@JonPurdyの答えは優れていますが、さらにいくつか例を追加したいと思います。
明らか:
構文チェック
リンティング
非自明:
Rustを使用すると、プログラマは「バインディング」が可変かどうかを指定でき、これらの制約を強制できます。
これは多少関連しています。一部の言語では、コンパイル時に一部のコードを実行できます。つまり、実行時エラーになりそうな多くのことをコンパイル時にキャッチできます。いくつかの例は、プラグマでマークされたマクロとNim言語の手順です。compileTime
準静的タイピング: