2012-09-09 14 views
6

これは私の前の質問からのフォローアップとなったので、この新しい質問を開始しました。私は同様のコンストラクタで構成されている2つのデータ型を持っている場合はハスケルでのデータ型の使用

:あなたは私がやっているかを見ることができれば

data A = C | Z 
data B = C 

data C = X | Y 

data A = X | Y | Z 
data B = X | Y 

はと私は何とかこれを表現することができる方法はありません私はXをグループ化しようとしています。 Yを1つのデータ型に変換し、それを複数の他のデータ型で使用することができます。私はこれを許可するコンパイラを得ることができない、または場合は、私はXまたはY、Cのみパターン一致することはできません?

Cが複数回宣言されているというエラーメッセージが表示されます。

多分型を使うことができると思っていましたが、複数の型指定をすることはできません。

EDIT

私は(下記のような)長い道のりを宣言した場合でも、それはまだコンパイルしてXとYは、複数の宣言を持って言いません。

data A = X | Y | Z 
data B = X | Y 
+0

のためのユニークなコンストラクタで織り込んアウトデータあなたが求めている何 'Aのサブタイプになります'。これは、新しい型を作成するキーワード 'data'で宣言されることはなく、既存の型とは離れています。私はハスケルがこのような機能を持っているとは思っていませんが、私はハスケルのすべての拡張機能を使っているわけではありません。 – Gilles

+0

@Gilles:いいえ、Haskellにはサブタイプ多型がありません。それは、パラメトリック多型、および型クラスによるアドホック多型のみを有する。あなたが得ることができる最も近いものは、実在のタイプですが、それはまったく違っていますが、まったく違うものです。 –

+0

私はこれを答えとして書いていますが、それほどではありません。あなたはtypeclassを宣言し、次にそれらの "一般的なもの"に必要な操作を行うことで、あなたが望むものに近づくことができます。これは、この問題の(バージョン)を解決するために周りのものを反転するかなり一般的な方法です。 –

答えて

13

だけでなく、あなたが行うことはできませんこれは、あなたも最初のオプションを行うことはできません。つまり、同じモジュールに2つの型(XYという名前のコンストラクタがあります)を持つことはできません。

この場合、Xのタイプは、CABのいずれでなければなりませんか。最も明白な答えはCですが、AまたはBが必要なコンテキストでは使用できません(Haskellにはサブタイプがないことに注意してください)。そうすれば、構造全体の目的を打ち破ることができます。

あなたができる最善のは、AとB、すなわちのコンストラクタでCをラップすることです:

data A = AC C | Z 
data B = BC C 
data C = X | Y 

その後、あなたは型の値を作成するためにACBCコンストラクタのいずれかでCをラップすることができそれぞれAまたはBです。次のようにあなたがこの

data A = X | Y | Z 
data B = X | Y 

を行うことはできません

+0

私の最初のオプションdoesntの仕事を言うためにちょうど編集されています。 「折り返し」と言うとき、文字通り「元のCと区別するために、Cの前に構文の他の部分を入れてください」という意味ですか? – Lethi

+2

@ダンはい。私の例では、 'AC X'を使って' A'型の値を作成し、 'BC X'型を作成して' B型 'の値を生成します。 'X'自体は2つの異なるタイプを持つことはできません。 – sepp2k

4

理由があります。第2のスロット内の最初のスロットとXnのペアを構築

foo n = (n,X) 

を:あなたは後にいくつかのコードを書く言います。コンパイラはどのような型を推測すべきですか?有効なタイプはXため

foo :: a -> A -> (a,A) 

あろう型Aのコンストラクタが、XタイプBのコンストラクタであるので、同様に有効で

foo :: a -> B -> (a,B) 

あります。同じ名前のコンストラクタが2つある場合は、それらを使用する関数の一意の型を推論することはできません。したがって、同じモジュールに同じ名前のコンストラクタを2つ与えることは許されません。

1

あなたはこれを行うことはできません。

data A = C | Z 
data B = C 

data C = X | Y 

を(余談として、B同じCであれば、なぜ全くBを持っている?)

しかし、あなたはをすることができますがdoは次のようなものです:

data A = A_Other C | Z 
data B = B_Other C 

data C = X | Y 

あなたのことができ、このようなパターンマッチ:あなたは複数のデータコンストラクタを宣言しているので、あなたがやりたいことができない

0

それが理にかなっている場合

foo :: A -> String 
foo (A_Other X) = "X" 
foo (A_Other Y) = "Y" 
foo (  Z) = "Z" 

bar :: B -> String 
bar (B_Other X) = "X" 
bar (B_Other Y) = "Y" 

foobar :: C -> String 
foobar X = "X" 
foobar Y = "Y" 

...。

data A = X | Y | Z 

では、実際には3つのコンストラクタ(値)XY、及びZを有するタイプAを導入しています。これは、最初のコードがコンパイルされないため、2つの異なるタイプのコンストラクタと同じ名前がリストされています。あなたがこれを行うことができれば、あなたは自問する必要があるだろう非オブジェクト指向の文脈で怖いです

X :: A 

または

X :: B 

です!そのため、その基礎となるデータを共有するために異なるコンストラクタ名を指定する必要があります。C

あなたはこれを考慮したい場合は他の記事を示唆しているとして、あなたが行うことができ、各データ型

data A = CForA C | Z 
data B = CForB C 

data C = X | Y 
関連する問題