Haskell 入門


Haskell でユーザ定義のデータを簡単に作る方法

Haskell でユーザ定義のデータをきちんと使いこなせるためには、data, class, instance, deriving の4つのキーワードに習熟しておく必要がある。

そのためには、データの型名とは何かとか、コンストラクタとは何かとか、クラスとは何かとか、インスタンスは何かとか、クラスの関数のオーバロードはどうするかとか様々な知識が必要になってくる。Haskell に慣れてくれば、そういう知識を活用していろいろな工夫をすることができるだろが、初心者にとっては敷居が高い。

ユーザ定義のデータ型を記述する

そこで、単にユーザ定義のデータ型を使いたいだけのときはどうすればいいかを考えてみた。それは、とりあえず、

data データ型の定義 deriving Show

とするだけだ。これで、大抵の用は足りる。

たとえば、二分木のデータ型で、葉の部分に整数型のデータを保持するデータ型を Btree という名前で定義してみる。Btree 型のデータは2種類のデータから構成されるとする。ひとつは整数値を保持する葉の部分を表す、Leaf Int 型で、もうひとつは木構造の節の部分を表す、Node Btree Btree 型だ。Leafの先には数字がぶら下がっており、Nodeの両端には Btree がぶら下がっているというイメージだ。

これを上に述べた方法で定義すると次のようになる。

data Btree = Leaf Int | Node Btree Btree deriving Show

data というキーワードはデータ型を定義するから分かる。deriving と Show が分からないが、それは、後で Google 先生に尋ねることにして、今のところはお約束として意味を問わないことにする。

そうすると、

1^(2^3)

のような木構造は上の定義を使って、

sampletree = Node (Leaf 1) (Node (Leaf 2) (Leaf 3))

のように定義できる。そこで、次のようなファイル mydata.hs を作って ghci で実行してみる。

data Btree = Leaf Int | Node Btree Btree deriving Show

sampletree = Node (Leaf 1) (Node (Leaf 2) (Leaf 3))

実行例

Prelude> :l mydata.hs
[1 of 1] Compiling Main ( mydata.hs, interpreted )
Ok, modules loaded: Main.
*Main> sampletree
Node (Leaf 1) (Node (Leaf 2) (Leaf 3))

上の実行例で sampletree としてデータの内容を表示させるために deriving Show が必要だったのだ。テクニカルに表現すると、Btree型のデータ型に show 関数を適用させるためには、deriving キーワードでBtreeがShowクラスのインスタンスであることを宣言する必要があったのだ。要するに詳しいことはあとで勉強することにしてとりあえず、データ型の定義の末尾には deriving Show をつけるものだと覚えておけばいい。

ユーザ定義データ型を使う

二分木構造のデータを定義できるようになったのでこれを使うことを考える。この二分木を探索して、Leaf の部分に収められている整数値のデータを全て集めてリストにする関数 toList を定義してみよう。

まず、Btreeのデータが Leaf x なら、toList は [x] を返す。次にBtree のデータが Node x y 型の場合、toList は toList x と toList y を連結したものになる。従って toList の定義は次のようになる。

toList (Leaf x) = [x]
toList (Node x y) = (toList x) ++ (toList y)

そこで、toList の定義を追加した mydata.hs は次のようになる。

data Btree = Leaf Int | Node Btree Btree
  deriving Show

sampletree = Node (Leaf 1) (Node (Leaf 2) (Leaf 3))

toList :: Btree -> [Int]
toList (Leaf x) = [x]
toList (Node x y) = (toList x) ++ (toList y)

随分簡単なプログラムだが、次のようにちゃんと動いてくれる。

*Main> :l mydata.hs
[1 of 1] Compiling Main ( mydata.hs, interpreted )
Ok, modules loaded: Main.
*Main> toList sampletree
[1,2,3]

そういうわけで、Haskellでユーザ定義のデータ型を使いたくなったら、

data データ型の定義 deriving Show

としておけば、とりあえずユーザ定義のデータ型を使ってみることができることがわかった。