Haskell のforall
-s は、制限された従属関数型と見なすことができます。これは、概念的に最も啓発的なアプローチであり、集合論的または論理的解釈にも最も適していると思います。
従属言語では、引数の値を関数型にバインドし、それらの値を戻り値の型に含めることができます。
-- Idris
id : (a : Type) -> (a -> a)
id _ x = x
-- Can also leave arguments implicit (to be inferred)
id : a -> a
id x = x
-- Generally, an Idris function type has the form "(x : A) -> F x"
-- where A is a type (or kind/sort, or any level really) and F is
-- a function of type "A -> Type"
-- Haskell
id :: forall (a : *). (a -> a)
id x = x
決定的な違いは、Haskell は を使用して型、持ち上げられたカインド、および型コンストラクターのみをバインドできるforall
のに対し、従属言語は何でもバインドできることです。
文献では、従属関数は従属製品と呼ばれます。それらが関数であるのに、なぜそれらをそれと呼ぶのですか?従属関数のみを使用して、Haskell の代数積型を実装できることがわかりました。
一般に、どの関数も、キーに typeがあり、要素にa -> b
type がある製品のルックアップ関数と見なすことができます。-sのペアとして解釈できます。この解釈は、すべての製品フィールドが同じタイプでなければならないため、非依存関数にとってはあまり興味深いものではありません。従属関数を使用すると、ペアは適切にポリモーフィックになります。a
b
Bool -> Int
Int
Pair : Type -> Type -> Type
Pair a b = (index : Bool) -> (if index then a else b)
fst : Pair a b -> a
fst pair = pair True
snd : Pair a b -> b
snd pair = pair False
setFst : c -> Pair a b -> Pair c b
setFst c pair = \index -> if index then c else pair False
setSnd : c -> Pair a b -> Pair a c
setSnd c pair = \index -> if index then pair True else c
ここで、ペアの重要な機能をすべて回復しました。また、 を使用しPair
て、任意のアリティの製品を構築できます。
forall
では、 -sの解釈とどのように結びついているのでしょうか。まあ、私たちは通常の製品を解釈して、それらに対するいくつかの直感を構築し、それをforall
-s に変換しようとします。
では、まず通常積の代数を少し見てみましょう。代数型は、代数によって値の数を決定できるため、代数型と呼ばれます。詳細な説明へのリンク。値A
の|A|
数があり、B
値|B|
の数Pair A B
がある場合|A| * |B|
、可能な値の数があります。合計型では、住民の数を合計します。はフィールドをA -> B
持つ積と見なすことができ、すべてタイプが であるため、 の住民の数は-sの数を掛け合わせたものになり、これは次のようになります。|A|
B
A -> B
|A|
|B|
|B|^|A|
. したがって、関数を表すために時々使用される「指数型」という名前です。関数が従属関係にある場合、指数公式が適合しなくなるため、「いくつかの異なる型の積」の解釈に戻ります。
この理解があればforall (a :: *). t
、 type のインデックスと type*
を持つフィールドを持つ積の型として解釈できます。Haskell に の特定の型を推測させ、関数を型引数に効果的に適用することで、フィールドを調べることができます。t
a
t
a
forall
この製品には、存在するインデックスの値と同じ数のフィールドがあることに注意してください。これは、Haskell 型の潜在的な数を考慮すると、ここではほとんど無限です。