2011-01-27 7 views
6

いくつかの互換性のないデータ・タイプを作成したいとします。つまり、私は実際にaが何であるかについてを気にすることなくパラメータ化された型Foo a、および、そのような私は、Haskellでシングルトンタイプを正しく考えて使用していますか?

bar :: (Foo a) -> (Foo a) -> (Foo a) 

としての機能を持っているしたいと思います。およそIntChar(私は、彼らが同じじゃないことを気にし)同時に、私は本当に気にしませんが、さらに明確にするために、私は

x :: Foo Int 
y :: Foo Char 
bar x y 

をやってから私を停止するように型システムが欲しいです。

私の実際のコードでは、与えられた環の多項式の型があります。私は実際には、型システムが多項式をsの多項式でtに加えるのを止めている限り、不定数が何であるかは気にしません。これまでのところ、私は与えられた多項式が終わったどの特定のリングについてケアを行うので、このアプローチはRing部分は完全に自然な感じ型クラスIndeterminateを作成することでこれを解決し、そして

data (Ring a, Indeterminate b) => Polynomial a b 

としての私の多項式タイプをパラメータ化しました。以下に説明するように、Indeterminateの部分については非常に工夫されています。

上記の方法は問題なく機能しますが、問題はありません。特にこの部分:

class Indeterminate a where 
    indeterminate :: a 

data T = T 

instance Indeterminate T where 
    indeterminate = T 

data S = S 

instance Indeterminate S where 
    indeterminate = S 

(など、多分もっと不確定なもの)。それは不思議で間違っているように感じます。基本的に私はIndeterminateのインスタンスにシングルトン(this sense)を要求しようとしています。奇妙な気持ちは、私がこれを間違って攻撃している可能性のある指標です。もう一つは実際のタイプbがしばしば推測できないので(私はPolynomial a bの多くの注釈をつける必要があるという事実ですが、これは奇妙ではありませんが厄介です)。

提案がありますか?私はちょうどこれのようにそれを続けなければならない、または私は何かを逃している?

PS:すぐにアップヴォートしたり受け入れたりしないと怒らないでください。私は数日間チェックインできません。

+0

多項式をリングの要素のシーケンスまたは同様のもの(例えば、部分和のシーケンス)としてモデル化しないのに十分な理由はありますか? –

+0

私はここで少し失われています。私はあなたがなぜ「不確定」を必要としているのか分かりません。 2つのBSが同じであることを強制したい場合は、タイプシグネチャのままにしてください。 – sclv

+0

@Alexandre C .:私はそれをやっています。しかし、タイプシグネチャは、 "2 + 5t"を "6s"に追加する意味がないようにしたいと思います。環要素のシーケンスとしての多項式では、型システム(正当なもの)は、ある環に係数を持つ多項式を他の環に係数を加えて追加するのを止めますが、不確定性を区別しません。今、私が実際に不確定要素を必要としているかどうかは、非常に有効な質問です:-) – gspr

答えて

7

まず第一に、私はこのわからない:

data (Ring a, Indeterminate b) => Polynomial a b 

...あなたはそれが何を期待やっています。 dataのコンテキストは非常に有用ではありません。何らかの理由でthe discussion hereを参照してください。なぜなら、実際に多くの追加の型保証を追加することなく余分な注釈を追加する必要があるからです。

第2に、実際には、型が区別されていることを保証する以外の「不確定」パラメータが気になりますか?そのようなことを行うためのかなり標準的な方法は、phantom typesと呼ばれ、データコンストラクタでは使用されない型コンストラクタのパラメータです。もしあなたが望むような機能が多型となることができますので、例えばファントム型の値を使用しないか、必要なんでしょう:

data Foo a b = Foo b 

foo :: Foo a b -> Foo a b 
foo (Foo x) = Foo x 

bar :: Foo a c -> Foo b c 
bar (Foo x) = Foo x 

baz :: Foo Int Int -> Foo Char Int -> Foo() Int 
baz (Foo x) (Foo y) = Foo $ x + y 

明らかにこれは注釈を必要としませんが、唯一のあなたが故意に制限を追加している場所で。そうでなければ、推論はファントム型のパラメータに対して正常に機能します。

シングルトンタイプのビジネスは、複雑なタイプレベルのものと通常のバリューレベルの計算とのギャップを埋めることが主な目的です値のプロキシを入力します。これは、例えば、基底を示す型のベクトルをマーキングするか、または物理的な単位で数値をマーキングする場合に便利です。注釈の意味が単なる「不確定なXというよりも意味がある」場合もあります。

+1

'-XEmptyDataDecls'を使うと、あなたの"マーカー "型にランタイム表現が全くないようにすることができます。 'data T'、そして改行を行い、あなたのコードを続けます。これは、 'T'はコンストラクタを持たない型であることを示しています。したがって、実際には型システムに対して何かを意味するだけです。 – luqui

+0

ありがとうございました!私はあなたが私が尋ねていたことと疑問に思っていたことを正確に得たと思う。私はファントムタイプについて知らなかったので、教えてくれてありがとう。シングルトンが実際に使用される時期についての明確化はまた、非常に啓発的であり、私が問題を抱えていたものの中心に辿り着きます(本当にあなたは私の心を読んでいましたか?)。 (サイドノートでは、 'data'定義の文脈は有用ではないことを知っています - コードを書いている間に私の思考を助けるのにそれらを使用しますが、後で取り除きます。 – gspr

+1

@gspr:ある時点で、GADTと関連する言語拡張について読むことができます。それらが提供する表現力は、有用であると思われるもののように見え、実際に意味のあるデータ定義のコンテキストを可能にします。 –

関連する問題