Help us understand the problem. What is going on with this article?

「Learn You a Haskell」の「Making Our Own Types and Typeclasses」の写経 その弐

Haskellで独自のデータ型、型クラスを定義する方法を知りたかったので Learn You a Haskell for Great Good!Making Our Own Types and Typeclasses を写経してます。

今回は 「Record syntax」 です。


何か人物を表すデータ型を作成したいとします。保存したい情報は first name, last name, age, height, phone number, favorite ice-cream flavor です。

data Person = Person String String Int Float String String deriving (Show)

1つ目のフィールドが first name、2つ目が second name、3つ目が age といった感じでしょうか。データを作成してみます。

ghci>data Person = Person String String Int Float String String deriving (Show)
ghci>let guy = Person "Buddy" "Finklestein" 43 184.2 "526-2928" "Chocolate"
ghci>guy
Person "Buddy" "Finklestein" 43 184.2 "526-2928" "Chocolate"

問題なく作成できましたが少し読みづらいです。また、個別に情報を取り出す関数を作成したい場合はどうなるでしょうか? first namelast name 取得するような関数です。このままでは下記のように定義する必要があります。

firstName :: Person -> String
firstName (Person firstName _ _ _ _ _) = firstName

lastName :: Person -> String
lastName (Person _ lastName _ _ _ _) = lastName

age :: Person -> Int
age (Person _ _ age _ _ _) = age

height :: Person -> Float
height (Person _ _ _ height _ _) = height

phoneNumber :: Person -> String
phoneNumber (Person _ _ _ _ phoneNumber _) = phoneNumber

flavor :: Person -> String
flavor (Person _ _ _ _ _ flavor) = flavor

この実装を書くことは非常に面倒なものですが、一応動作します。

ghci>let guy = Person "Buddy" "Finklestein" 43 184.2 "526-2928" "Chocolate"
ghci>firstName guy
"Buddy"
ghci>height guy
184.2
ghci>flavor guy
"Chocolate"

データ型を書き込むためのもっと良い方法があります。それは レコード構文 を使うことです。上記の機能を実現する方法を下記に示します。

data Person = Person { firstName :: String
                    , lastName :: String
                    , age :: Int
                    , height :: Float
                    , phoneNumber :: String
                    , flavor :: String
                    } deriving (Show)

名前付けした型をスペースで区切る代わりに中括弧で囲みます。そしてフィールドの名前を書き、 :: で区切って型を設定します。結果としてデータ型を同じになります。この主な利点はデータ型のフィールドを探索する関数を自動で作成してくれることです。レコード構文によってデータ型を作成することで、firstName, lastName, age, height, phoneNumber, flavor のような関数が自動で作成されます。

ghci>:t flavor
flavor :: Person -> String
ghci>:t firstName
firstName :: Person -> String

レコード構文を使うことには他にも利点があります。独自の型に対し Show を導出させるときに、レコード構文を使用して型を定義してインスタンス化した場合には表示が異なります。

車を表現するデータ型があるとします。その車を製造した会社, モデル名, 製造年 を追跡したいとします。下記を見てください。

data Car = Car String String Int deriving (Show)
ghci>Car "Ford" "Mustang" 1967
Car "Ford" "Mustang" 1967

レコード構文を利用した場合には下記のようになります。

data Car = Car {company :: String, model :: String, year :: Int} deriving (Show)
ghci>Car {company="Ford", model="Mustang", year=1967}
Car {company = "Ford", model = "Mustang", year = 1967}

新しく車を作成する際に、全てのフィールドをリストアップしておけば、フィールドの順序を意識する必要はありません。レコード構文を指定しない場合には順序を意識する必要があります。コンストラクターにフィールドが複数存在し、どのフィールドが何であるのか明らかにする必要がある場合はレコード構文を使います。

べクトルを表現するデータ型は data Vector = Vector Int Int Int というような定義であってもフィールドがベクトルの構成要素であることは一目瞭然ですが、PersonCar のようなデータ型ではレコード構文を使用することで構成要素を明らかにするできるという利点を得られます。


まとめ

  • データ型を作成するときフィールドの構成要素を明らかにしたい場合にはレコード構文が使える。
  • レコード構文によって独自にデータ型を定義すると各フィールドを探索する関数を自動で作成してくれる
  • データ型の定義にレコード構文を使用した場合、新たにモデル作成する際に全フィールドをリストアップしておけばフィールドの順序を意識しなくても良い。

次回に続きます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした