型コンストラクターとデータ コンストラクター
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
* -> * -> *