In computer science and logic, a dependent type is a type whose definition depends on a value. It is an overlapping feature of type theory and type systems. In intuitionistic type theory, dependent types are used to encode logic's quantifiers like "for all" and "there exists". In functional programminglanguages like Agda, ATS, Rocq (previously known as Coq), F*, Epigram, Idris, and Lean, dependent types help reduce bugs by enabling the programmer to assign types that further restrain the set of possible implementations.
Two common examples of dependent types are dependent functions and dependent pairs. The return type of a dependent function may depend on the value (not just type) of one of its arguments. For instance, a function that takes a positive integer may return an array of length , where the array length is part of the type of the array. (Note that this is different from polymorphism and generic programming, both of which include the type as an argument.) A dependent pair may have a second value, the type of which depends on the first value. Sticking with the array example, a dependent pair may be used to pair an array with its length in a type-safe way.
Dependent types add complexity to a type system. Deciding the equality of dependent types in a program may require computations. If arbitrary values are allowed in dependent types, then deciding type equality may involve deciding whether two arbitrary programs produce the same result; hence the decidability of type checking may depend on the given type theory's semantics of equality, that is, whether the type theory is intensional or extensional.[1]
In 1934, Haskell Curry noticed that the types used in typed lambda calculus, and in its combinatory logic counterpart, followed the same pattern as axioms in propositional logic. Going further, for every proof in the logic, there was a matching function (term) in the programming language. One of Curry's examples was the correspondence between simply typed lambda calculus and intuitionistic logic.[2]
述語論理は命題論理の拡張であり、量化子を追加したものです。ハワードとデ・ブルインは、このより強力な論理に合わせてラムダ計算を拡張し、「すべて」に対応する依存関数と、「存在する」に対応する依存ペアの型を作成しました。[ 3 ]
このため、そしてハワードによる他の研究により、命題を型として扱うことは、カリー・ハワード対応として知られています。
依存型理論において、依存型とは、値によって仕様が変化する可能性のある型であり、インデックス付き集合族に類似するものと見なすことができる。型の集合を表し、示すためにはタイプです期間タイプの、 書く型の依存ファミリー書かれているつまり、各項に対して家族はタイプを割り当てますしたがって、そして表現特定の値に依存する型を示します標準的な用語では、これは次のように表現されます。異なる。
戻り値の型が引数によって変化する関数(つまり、固定された終域を持たない関数)は従属関数であり、この関数の型は従属積型、π型(Π型)、または従属関数型と呼ばれる。[ 4 ]型のファミリーから依存関数のタイプを構築することができます項は、項を取る関数である。そして、次の項を返します。この例では、依存関数型は通常次のように記述されます。または。
もしは定数関数であり、対応する従属積型は通常の関数型と同等です。つまり、判断的に同等であるいつ依存しない。
「Π型」という名称は、これらが型のデカルト積として捉えられるという考え方に由来する。Π型は、全称量化子のモデルとしても理解できる。
例えば、次のように書くと実数のn組の場合、これは、自然数nが与えられたときに、サイズnの実数のタプルを返す関数の型です。通常の関数空間は、範囲の型が実際には入力に依存しない場合の特殊なケースとして発生します。例これは自然数から実数への関数の一種であり、次のように表されます。型付きラムダ計算において。
より具体的な例として、0から255までの符号なし整数型(8ビットまたは1バイトに収まるもの)であり、のために、 それからの産物へと退化する。
依存積型の双対は、依存ペア型、依存和型、シグマ型、または(紛らわしいことに)依存積型です 。[ 4 ]シグマ型は存在量化子としても理解できます。上記の例を続けると、型の宇宙において、種類がありますそして、タイプのファミリーすると、依存ペア型が存在する。(代替表記法はΠ型の表記法と同様です。)
依存ペア型は、2 番目の項の型が最初の項の値に依存する順序対の概念を捉えています。それからそして。 もしが定数関数である場合、従属ペアのタイプは積のタイプ、つまり通常のデカルト積になります(判断上等になります)。[ 4 ]
より具体的な例として、再び0から255までの符号なし整数型となり、再び等しくなるさらに256個の任意の、 それから合計に退化する。
させてあるタイプとし、カリーとハワードの書簡によると、は、以下の用語に関する論理述語として解釈できる。特定の種類が居住されているかどうかは、この述語を満たす。この対応関係は存在量化と依存ペアに拡張できる。命題型が真である場合に限り真となります。人が住んでいる。
例えば、以下別の自然数が存在する場合に限るそのため論理学において、この命題は存在量化によって体系化される。
この命題は、従属対タイプに対応します。
つまり、次の主張の証明以下非負の数を含むペアこれは、そして等号の証明。
ヘンク・バレンデレヒトは、型システムを3つの軸に沿って分類する手段としてラムダキューブを開発しました。結果として得られる立方体状の図の8つの角はそれぞれ型システムに対応しており、最も表現力の低い角には単純型ラムダ計算が、最も表現力の高い角には構成計算が配置されています。立方体の3つの軸は、単純型ラムダ計算の3つの異なる拡張に対応しています。すなわち、依存型の追加、多相性の追加、およびより高次の型コンストラクタ(例えば、型から型への関数)の追加です。ラムダキューブは、純粋型システムによってさらに一般化されます。
システム論理フレームワークLFに対応する純粋な一階依存型の型は、単純型付きラムダ計算の関数空間型を依存積型に一般化することによって得られる。
システム2次依存型のものは以下から得られる。型コンストラクタに対する量化を可能にすることによって。この理論では、依存積演算子は、単純型ラムダ計算の演算子とシステムFのバインダー。
高次システム拡張ラムダキューブからの4つの抽象化形式すべてに対応します。すなわち、項から項、型から型、項から型、型から項への関数です。このシステムは構成計算に対応し、その導関数である帰納的構成計算はRocqの基盤となるシステムです。
カリー・ハワード対応は、任意の複雑な数学的性質を表現する型を構築できることを示唆しています。ユーザーが型に値が存在すること(つまり、その型の値が存在すること)を構成的に証明できれば、コンパイラはその証明を検証し、その構成を実行して値を計算する実行可能なコンピュータコードに変換できます。証明検証機能により、依存型言語は証明支援言語と密接に関連しています。コード生成機能は、形式的なプログラム検証と証明付きコードへの強力なアプローチを提供します。なぜなら、コードは機械的に検証された数学的証明から直接生成されるからです。