型コンストラクターとデータ コンストラクター
haskell のユニオン型で型にタグを付ける必要があります。
data Cost = Int | Float
言うべき
data Cost = I Int | F Float
Intこれは、とFloatが型であるためであることに注意してください。例のデータはI 5またはF 5.6です。データコンストラクターも必要です。Iとは、Fここではデータ コンストラクターです。I :: Int -> CostとF :: Float -> Cost。これらは、Int または Float を Cost に変換する関数です。たとえば、コメントのように、引数を取らないコンストラクターを使用できます。
data Bool = True | False
ここで True と False はコンストラクタであり、型ではありません。例のデータは単にTrueまたはFalseです。毎回コンストラクターを持たなければならないので、型にタグを付ける必要がありますInt。Float
定義
data Node a = Node a
左側Nodeは型コンストラクターと呼ばれる一種の型関数であり、 kind を持って* -> *いますが、右側Nodeは type のデータ コンストラクターであるため、少し混乱しa -> Node aます。データの例:Node "hello"型のNode String. これは、
data Node a = N a
Node型コンストラクターとデータNコンストラクターも同様です。N "Hello"これにより、タイプ のサンプル データが得られますNode String。この種の定義については、大きな違いはありません。
newtype Node a = N a
ほとんどの場合、コンパイラはそれを最適化して取り除くことができますが、ソース コードの最後で型の安全性を得ることができるからです。
型コンストラクターには型が必要です
あなたも必要です
data Edge a = Edge ((Node a,Node a),Cost)
Nodeは型コンストラクター ( kindを持っている) であるため* -> *、作業する型を常に指定する必要があります。私はそれを与えたaので、あなたは何でもノードを作ることができます.
costただし、角かっこは必要ありません。また、Int と Float の和集合は、固定型の代わりに小文字を使用することで、任意のコスト型を許可するほど有用ではない可能性があります。Cost
data Edge a cost = Edge (Node a) (Node a) cost
(数値ではないコストで誰も有利にならないようにしたい場合は、 と言うことができますdata Num cost => Edge a cost = Edge (Node a) (Node a) cost。私の見解では、Int と Float のタグ付けの扱いにくさと任意のコストを許可することの間のより良い妥協点ですが、あなたはそれを必要としません+.コストを
あなたの定義全体は次のようになります
data Node a = Node a
data Edge a cost = Edge (Node a) (Node a) cost
data Graph a c = Graph [Edge a c]
繰り返しますが、2 つの型を取るGraph [Edge a c]ため、書く必要があります。Edge* -> * -> *