data
宣言では、型コンストラクターは等号の左側にあるものです。データ コンストラクターは、等号の右側にあるものです。型が必要な場合は型コンストラクターを使用し、値が必要な場合はデータ コンストラクターを使用します。
データ コンストラクター
簡単にするために、色を表す型の例から始めましょう。
data Colour = Red | Green | Blue
ここには、3 つのデータ コンストラクターがあります。Colour
は型であり、 typeGreen
の値を含むコンストラクターですColour
。同様に、Red
とBlue
はどちらも type の値を構築するコンストラクタですColour
。でも、スパイスを効かせることは想像できます!
data Colour = RGB Int Int Int
まだ type しかColour
ありRGB
ませんが、値ではありません。3 つの Int を取り、値を返す関数です! RGB
タイプを持っています
RGB :: Int -> Int -> Int -> Colour
RGB
いくつかの値を引数として取り、それらを使用して新しい値を構築する関数であるデータ コンストラクターです。オブジェクト指向プログラミングを行ったことがある場合は、これを認識する必要があります。OOP では、コンストラクターもいくつかの値を引数として取り、新しい値を返します!
この場合、RGB
3 つの値に適用すると、色の値が得られます。
Prelude> RGB 12 92 27
#0c5c1b
データ コンストラクターを適用して、型の値を作成しました。Colour
データ コンストラクターには、変数のように値が含まれるか、他の値を引数として取り、新しい値を作成します。以前にプログラミングを行ったことがある場合、この概念はそれほど奇妙ではないはずです。
休憩
sを格納するために二分木を構築したい場合はString
、次のようなことを想像できます。
data SBTree = Leaf String
| Branch String SBTree SBTree
ここに表示されているのは、SBTree
2 つのデータ コンストラクターを含む型です。つまり、型の値を構築する2 つの関数 (すなわちLeaf
と) があります。二分木の仕組みに慣れていない場合は、しばらくお待ちください。二分木がどのように機能するかを実際に知る必要はありません。これが何らかの方法で s を格納することだけです。Branch
SBTree
String
また、両方のデータ コンストラクターが引数を取ることもわかりますString
。これは、ツリーに格納する文字列です。
しかし!も格納できるようにしたい場合はBool
、新しいバイナリ ツリーを作成する必要があります。次のようになります。
data BBTree = Leaf Bool
| Branch Bool BBTree BBTree
型コンストラクタ
SBTree
とはどちらBBTree
も型コンストラクターです。しかし、明らかな問題があります。それらがどれほど似ているか分かりますか?これは、どこかにパラメーターが本当に必要であることを示しています。
したがって、これを行うことができます:
data BTree a = Leaf a
| Branch a (BTree a) (BTree a)
ここで、型コンストラクターへのパラメーターとして型変数を導入します。 a
この宣言でBTree
は、関数になっています。引数として型を取り、新しい型を返します。
ここでは、プログラムで値に割り当てることができる型である具象型(例にはInt
、[Char]
およびが含まれます) と、型を代入できるようにする必要がある型コンストラクター関数の違いを考慮することが重要です。値に割り当てられます。値は「何かのリスト」である必要があるため、「リスト」型にすることはできません。同じ精神で、値は「何かを格納するバイナリ ツリー」である必要があるため、「バイナリ ツリー」型にすることはできません。Maybe Bool
たとえばBool
、引数としてを渡すと、sを格納するバイナリ ツリーであるBTree
type が返されます。type 変数の出現箇所をすべて type に置き換えると、それがどのように真であるかを自分で確認できます。BTree Bool
Bool
a
Bool
必要に応じて、次の種類BTree
の関数として表示できます
BTree :: * -> *
種類はやや型に似ています。 は具象型を示しているため、具象型から具象型へ*
と言います。BTree
まとめ
ここに戻って、類似点に注意してください。
値にわずかなバリエーションが必要な場合、パラメーターを持つデータ コンストラクターはクールです。これらのバリエーションをパラメーターに入れ、値を作成する人に、どの引数を入れるかを決定させます。同じ意味で、パラメーターを持つ型コンストラクターはクールです。タイプにわずかなバリエーションが必要な場合!これらのバリエーションをパラメーターとして入れ、型を作成する人に、どの引数を入れるかを決定させます。
ケーススタディ
ここでのホーム ストレッチとして、型を考えることができMaybe a
ます。その定義は
data Maybe a = Nothing
| Just a
ここでMaybe
は、具象型を返す型コンストラクターを示します。Just
値を返すデータコンストラクタです。Nothing
値を含むデータ コンストラクターです。の型Just
を見ると、
Just :: a -> Maybe a
つまり、Just
type の値を受け取り、 typea
の値を返しますMaybe a
。の種類Maybe
を見ると、
Maybe :: * -> *
つまり、Maybe
具象型を受け取り、具象型を返します。
もう一度!具象型と型コンストラクター関数の違い。s のリストを作成できませんMaybe
- 実行しようとすると
[] :: [Maybe]
エラーが発生します。Maybe Int
ただし、 、またはのリストを作成することはできますMaybe a
。これMaybe
は、 が型コンストラクター関数であるためですが、リストには具象型の値が含まれている必要があります。Maybe Int
およびMaybe a
具象型 (または、必要に応じて、具象型を返す型コンストラクター関数の呼び出し) です。