bitterharvest’s diary

A Bitter Harvestは小説の題名。作者は豪州のPeter Yeldham。苦闘の末に勝ちえた偏見からの解放は命との引換になったという悲しい物語

Haskell ドリル12 レコード構文

1.概略

タプルは、複数のデータを一つにまとめたものである。また、それぞれのデータの型が異なっていても構わない。一例をあげれば、、名前と年齢と身長の集まりは、次のような形で表すことができる。

(“Tanaka”, 42, 173.3)

タプルの中で、データの数が二つのものは、特に、対と呼ばれる。対には最初のデータを取り出すfst、最後のデータを取り出すsndという関数も用意されている。

タプルは複数のデータを扱うのに便利であるが、プログラムを書き上げてからしばらくたつと、それぞれのデータが何を表していたのかが分からなくなることがある。そのような時、便利なのが、レコード構文である。

レコード構文は、まだ学んでいないが、新しいデータ型を作成するdataによって実現される。。今、Personというレコード構文を考える。レコード構文は、その属性を示すためにフィールドを持つ。Personも名前、年齢、身長をフィールドとして持っているとすると、次のようになる。

data Person = Person {name :: String, age :: Int, height :: Double} deriving (Show)

ここで、dataは新しいデータ型を作成するためのキーワードである。Dataに続く名前、ここではPerson、が型コンストラクタである。等号の後に続く名前、ここではPerson、は値コンストラクタと呼ばれる関数である。ここでは、型コンストラクタと値コンストラクタの名前が一致しているが、異なっていてもかまわない。値コンストラクタに続く{… }でフィールドを定義する。最後のderivingは型クラスを指定する。dataで定義された型は、Int,Doubleなどと同じように型である。このため、型クラスのインスタンスとなることができる。そこで、derivingではどの型クラスのインスタンスになるかを示す。
値コンストラクタPersonは関数なので、型シグネチャがある。それを調べると次のようである。

Prelude> :t Person
Person :: String -> Int -> Double -> Person

フィールドの値を入力としていることが分かる。また、このレコード構文の利用例を以下に示す。

Person {name="Tanaka", age=42, height=173.3}

2.例題

問題:新しいデータ型Triangleを作成しなさい。なお、フィールドには各辺の長さを持つものとする。
この問題は次のように解ける。なお、三角形同士は比較できるので、Showの他に、Eqのインスタンスとした。

data Triangle = Triangle {edgeA :: Double, edgeB :: Double, edgeC :: Double} deriving (Eq, Show)

辺の長さが、3,4,5である三角形は次のようになる。

Prelude> Triangle {edgeA=3, edgeB=4, edgeC=5}
Triangle {edgeA = 3.0, edgeB = 4.0, edgeC = 5.0}

3.問題

それでは問題を解いてみる。

問題1:レコード構文を用いて、車種、製造元、製造年をフィールドに持つ車のデータ型を定義せよ。

問題2:問題1で得られた車のレコード構文を用いて、二台の車について製造年が同一であるかどうかを判定する関数を作成せよ。

問題3:レコード構文を用いて、二つの辺とそれらに挟まれる角で三角形を定義せよ。

問題4:、問題3で得られた三角形のレコード構文を用いて、二つの三角形が合同であればTrueを返し、そうでなければFalseを返す関数を定義せよ。

問題5:レコード構文を用いて、二つの角とそれらに挟まれる辺で三角形を定義せよ。

問題6:問題5で得られた三角形のレコード構文を用いて、二つの三角形が相似であればTrueを返し、そうでなければFalseを返す関数を定義せよ。

問題7:レコード構文を用いて、辺の数と一辺の長さをフィールドに持つ正多角形を定義せよ。

問題8:問題7で得られた正多角形のレコード構文を用いて、二つの多角形の辺の数が同じであるかを判定する関数を作成せよ。

問題9:レコード構文を用いて、書名、出版社、出版年、価格をフィールドに持つ本を定義せよ。

問題10:問題9で得られた本のレコード構文を用いて、二つの本の価格が同じであるかを判定する関数を作成せよ。