2015-10-25 9 views
8

あなたは、コンストラクタのない代数的データ型を定義することができます(または種類は?)?コンストラクタのない代数データ型の目的は何ですか?コンストラクタを持っていません</p> <pre><code>data Henk </code></pre> <p>しかしタイプの目的です:Haskellでは

+2

これらはファントムタイプと呼ばれます。それらは、他の型をパラメータ化するために、すなわち、タイプコンストラクタに型パラメータとして渡す。その値コンストラクタのどれも、そのファントム型の値パラメータを期待しない。 –

+9

ファントムの種類は気にしないでください(重複していない、Erik)。少なくとも1つの空の種類のための賢明な動機があります:http://stackoverflow.com/q/14131856/828361 – pigworker

答えて

13

タイプレベルの機械では型が存在することがしばしばありますが、そのような型の値は構成されません。

例えば、ファントムの種類:

module Example (Unchecked, Checked, Stuff()) where 

data Unchecked 
data Checked 
data Stuff c = S Int String Double 

check :: Stuff Unchecked -> Maybe (Stuff Checked) 
check (S i s d) = if i>43 && ... 
        then Just (S i s d) 
        else Nothing 

readFile :: Filepath -> IO (Stuff Unchecked) 
readFile f = ... 

workWithChecked :: Stuff Checked -> Int -> String 
workWithChecked stuff i = ... 

workWithAny :: Stuff any -> Int -> Stuff any 
workWithAny stuff i = ... 

限りSコンストラクタは、モジュールによってエクスポートされていないとして、このライブラリの利用者は、Stuffデータ型のステータスを「確認」を偽造することはできません。

上記のように、workWithChecked関数は、呼び出されるたびに入力をサニタイズする必要はありません。ユーザは、「チェックされた」タイプの値を提供する必要があるため、すでにそれを完了していなければなりません。これは、ユーザが事前にcheck関数を呼び出していなければならないことを意味します。これは効率的で堅牢な設計です。コールごとに同じチェックを何度も繰り返すわけではありませんが、チェックされていないデータをユーザーに渡すことはできません。

タイプChecked,Uncheckedの値が重要でないことに注意してください。決してそれらを使用しません。

コメントの中で言及されている他のものとして、空のタイプの他にも、ファントムタイプ以外の多くの用途があります。たとえば、一部のGADTには空のタイプが含まれます。例えば。

上記では、タイプに長さ情報を記録するために空のタイプを使用しています。さらに、なしのコンストラクタを持つ型は、いくつかの理論的な特性を達成するために必要な

は:私たちはEither a TTに同型であるようなaを探している場合、我々はaが空になりたいです。型理論では、空の型は、論理的に「偽」な命題に相当する型として一般に使用されます。

+0

これは、有用である。あなたの例を拡張するには、チェックされているかチェックされていない 'Stuff'や、チェックされたバージョンだけで動作する他の関数でうまく動作するいくつかの関数を持つこともできます。 –

+0

@JeremyList私は完全に同意します(そうでなければ、単にファントムインデックスの代わりに2つの異なるタイプを使用できます)。もう少し改善するためにもう1つの機能を追加しましたが、ファントムタイプのフルパワーはここには表示されません。 – chi

関連する問題