型コンストラクタまとめ(概要~具体例)
この記事では型コンストラクタについてまとめます。概要,仕組み,具体例などあれこれ書いてみようと思います。代数的データ型、値コンストラクタをおさらいしてから内容に入っていきます。
代数的データ型の定義
代数的データ型とは新しいデータ型を作るための仕組みです。オブジェクト指向でいうクラスに相当します。その定義は以下です。data
と書いた後に新しい型名を宣言します。型コンストラクタが新しい型名、新しいデータ型で取り得る値が値コンストラクタとなります。
data 型コンストラクタ (※型引数) = 値コンストラクタ (※既存のデータ型 or 型引数)
型コンストラクタ、値コンストラクタには引数を渡すことも可能です。ですがまずは最も単純な代数的データ型としてSchool型を作ってみます。学校には先生か生徒かの2種類しかありません。
data School = Teacher | Student
()
内へ引数は渡さずに作ってみました。School
型を持つデータはTeacher,Studentのどちらかの値を取ることになります。 田中さんが生徒だったとして、変数tanakaにSchool
型を持たせます。
data School = Teacher | Student deriving Show
tanaka :: School
tanaka = Student
main = print tanaka
-- 実行結果「Student」
OR条件で指定しなくとも代数的データ型はもっとシンプルに作れます。School
型はTeacherかStudentを取り得ますが、間違えてTeacherを削除したらどうでしょうか。School
型を持つデータは必ずStudentの値を取るようになります。何も実用性はありませんが、型に対して取りうべき値を指定できます。
data School = Student deriving Show
tanaka :: School
tanaka = Student
main = print tanaka
-- 実行結果「Student」
値コンストラクタへ引数を渡す
また値コンストラクタは「値を作り上げるモノ」であり、引数を渡すことが可能です。出席番号の情報を付け加えたいとします。その場合、値コンストラクタへInt型の引数を渡します。田中さんが10番だったとして引数を渡したのがこちらです。
data School = Student Int deriving Show
tanaka :: School
tanaka = Student 10
main = print tanaka
-- 実行結果「Student 10」
値コンストラクタへ引数を渡せば、プラスで色々な情報を管理できることがわかります。
型コンストラクタへ引数を渡す
値コンストラクタへ引数を渡すことができたように、型コンストラクタへも引数を渡すことができます。しかし一口に「引数を渡す」といっても、値コンストラクタ/型コンストラクタによって意味合いが異なります。
値コンストラクタへ引数を渡す:プラスで情報をまとめるため
型コンストラクタへ引数(型引数a)を渡す:多相型を実現するため
値コンストラクタには任意のデータ型を渡すことができます。しかし型コンストラクタへは引数として型変数aしか渡すことができません。これは多相型(任意のデータ型を受け取れる)を実現するためです。 例えば型コンストラクタへInt型を引数として渡すとエラーとなります。『型コンストラクタへは型変数aを引数して渡してね』というエラー内容です。
In the data declaration for ‘◯◯’
A data declaration should have form
data ◯◯ a = ...
型コンストラクタあれこれ
型コンストラクタを理解するには実際に具体例をみるのが1番です。ここからは型コンストラクタを使った例を2つご紹介します。
Point型(2点を管理)
2つの座標軸を表すPoint型というデータ型を新しく作ってみます。x軸、y軸の値は整数かもしれませんし、小数かもしれません。IntかDoubelか決めかねる時には、後からデータ型を引数として渡して、受け取った引数を元にデータ型を作るようにします。
data Point a = Double a a deriving Show
p1 = Double 10 20
main = print p1
Point a
型に引数としてInt型を渡しました。これによってPiont Int
型という新しいデータ型を作ることができました。
Maybe型(Maybe ◯◯型を作る)
他にも引数を受け取る型コンストラクタとして有名なのがMaybeです。Maybeは成功/失敗を表すためのデータ型ですが、色々なデータ型で利用できるようにしたいですよね。型は次のように定義されています。
data Maybe a = Just a | Nothing
Maybe a
型となっており、任意のデータ型を受け取れるようになっています。Int,String,Doubleなどのデータ型を渡すことで、Maybe Int
,Maybe String
,Maybe Double
などのデータ型を作ることができます。ここでは10という整数を渡しMaybe Int
型を作りました。(型コンストラクタへ型引数を渡して作った型を明示的に指定する必要はありません。)
result = Just 10
-- Just 10 :: Maybe Int
main = print result
-- 実行結果「Just 10」
IntでもStrignでもDoubelでもCharでも、同じ1つのデータ型で対応できるのが便利ですよね。
result = Just "OK!"
-- Just "OK" :: Maybe String
main = print result
-- 実行結果「Just "OK!"」
Discussion