このブログ記事では、Haskellにおいて重要なレコードを用いたデータ型の定義方法について紹介しています。

データ型の不便性
前回の記事では、新しくデータ型を定義する方法をみてみました。では、Haskellを使ってWebアプリを作ることを
想像してみましょう。Webアプリでは十中八九ユーザーの名前、年齢、メールアドレスなどのデータを
User
のデータ型に保存する必要があるでしょう。前回の定義方法を用いるとUser
を次のように定義できます。
data User = User String String Int String String
これはすでに雲行きが怪しくなってきましたが、続けてみましょう。Webアプリではユーザーの様々な情報にアクセス する必要があるでしょう。そのためには、以下のような関数を定義する必要があります。
firstName :: User -> String
firstName (User firstname _ _ _ _) = firstname
lastName :: User -> String
lastName (User _ lastname _ _ _) = lastname
age :: User -> Int
age (User _ _ age _ _) = age
email :: User -> String
email = (User _ _ _ email _) = email
phoneNumber :: User -> String
phoneNumber (User _ _ _ _ phonenumber) = phonenumber
--- 例
user = User "Micheal" "Jordan" 25 "mjordan@gmail.com" "123-456-789"
firstName user --- "Micheal"
age user --- 25
ユーザーの情報にアクセスするためだけに必要な労力としては大きすぎます。。このような関数をすべてのデータ型で書かなければ いけないのでしょうか?幸い、Haskellはもっと簡単な方法を用意してくれています。
レコード
Haskellにはレコードという概念があり、上のような問題を解決してくれます。では早速レコードを使って、User
を再定義
してみましょう。
data User = User {
firstName :: String,
lastName :: String,
age :: Int,
email :: String,
phoneNumber :: String
}
上のようにレコードを使ってデータ型を定義すると、Haskellが自動的に各データを抽出できる関数をセットアップしてくれます。
--- 関数を定義しなくても以下のように要素を抽出できます。
user = User "Micheal" "Jordan" 25 "mjordan@gmail.com" "123-456-789"
firstName user --- "Micheal"
age user --- 25
レコードは複数のコンストラクターに同時に用いることもできます。
data Point =
D2 {x::Int, y::Int}
| D3 {x::Int, y::Int, z::Int}
x (D2 1 2) --- 1
x (D3 1 2 3) --- 1
z (D2 1 2) --- Err Undefined
z (D3 1 2 3) --- 3
クイズ
この記事では、学習した内容を確認するためのクイズを設けます。記事のメイン部分を読んだ後に、ぜひ自分で問題を解いてみることを強くお勧めします。各問題をクリックすると答えが表示されます。
リソース
- Philipp, Hagenlocher. 2020. Haskell for Imperative Programmers #12 - Records. YouTube.
- NA. Making Our Own Types and Typeclasses. Learn You a Haskell for Great Good.