人気ブログランキング | 話題のタグを見る

RWH の読み方(16) 第3章

Real World Haskell 第3章 Defining Types, Streamlining Functions

Pattern Maching 続き

代数的データ型と関数のパターンマッチを組み合わせる例として、この節の先頭に not 関数と同じ働きをする myNot 関数が提示されている。

myNot True = False
myNot False = True

myNot の引き数が True ならこの関数の値は False になり、引き数が False なら True になる。たしかに、if 文は使われておらず、引き数のパターンで値が変わるようにプログラムされているが、これの一体どこが代数的型と関数のパターンマッチの組み合わせになるのだろうか。

これをはっきりさせるために、代数的データ型 Bool の型宣言を見てみる。

data Bool = True | False

この宣言で Bool は type constructor で True と False はいずれも value constructor だ。したがって、上の myNot の定義の引き数にはどちらも value constructor が使われている。つまり、代数的データ型があれば、関数の引き数に value constructor を使って関数の定義をすれば、代数的データ型の起こり得る可能性を網羅した関数が機械的に記述できることになる。

もう一つの例を上げてこのことを確かめてみよう。getJust は Just a からコンテナの内容の a を取り出す関数だ。

Prelude> let getJust (Just x) = x; getJust Nothing = 0
Prelude> getJust (Just 5)
5
Prelude> getJust Nothing
0

この場合関数の引き数に value constructor (Just x) を持ってくることで、パターンマッチの効果でコンテナの内容 x を取り出すことができる。

このように value constractor と関数のパターンマッチは直結することができる。

Contruction and DeconstructionFarther Adventures

このサブセクションでは代数的データ型で構成されたデータが、パターンマッチでコンテナから取り出すことができることを説明してある。例えば

Book 9 "Close Calls" ["John Long"]

で書籍の情報を1個の BookInfo 型のデータにまとめる (construction) ことができるが、関数のパターンマッチを使えばまとめられたパラメータを取り出すことができる。すなわち、関数の引き数に BookInfo 型の value constructor と同じパターンを持ってくるとコンテナの値が取り出せる。例えば BookInfo 型のデータから id を取り出す関数 bookID は次のようになる。

bookID (Book id title authors) = id

同じように title や authors を取り出す関数は次のように記述できる。

bookTilte (Book id title authors) = title
bookAuthors (Book id title authors) = authors

Variable Naming Patterns

このサブセクションでは、リストのパターンを記述するときの慣習を説明している。リストの要素は x で、リストはxs で、リストの先頭の要素が x で残りがリスト xs の場合は (x:xs) でなどだ。これも、関数をプログラムしているうちに自然に身についてくる。

The Wild Card Patten

このサブセクションではワイルドカード wild card の使い方を説明している。ワイルドカードはアンダースコアで表す。変数と同じ働きをするが、コンテナの値は読み捨てられる。ワイルドカードは関数の定義の際に使わない変数をパターンから除去するために用いられる。

前述の bookID 関数では、title や authors などの変数は関数の body (定義を実際に行う部分。= の右側) では使われない。このような場合は変数に wild card を使わないと、コンパイラの設定次第ではコンパイルエラーになることがある。

bookID = (Book id _ _) = id

Exhaustive Pattens and Wild Cards

このサブセクションでは、ワイルドカードをデフォールトのパターンマッチに利用する場合を説明している。次の goodExample はリストの要素の総和を計算する関数だが、2行目の定義ではパターンをワイルドカードにしている。これは、1行目のパターンマッチが失敗するどのような場合でも goodExample が0を返すようにプログラムするためだ。

goodExample (x:xs) = x + goodExample xs
goodExample _ = 0

これで goodExample の引き数が [] (空のリスト)の時も値 0 が返るので、めでたく goodExample はリストの総和を計算することができる。

まとめ

代数的データ型と関数のパターンマッチは本来は別のものだ。しかし、この両者を対応させることで、代数的データ型から半ば自動的にデータを処理する関数を記述することができる。これが RWH の説明の眼目だが、関数のパターンマッチそのものについては独立に説明してもらったほうが分かりやすい。

RWH はやはり、中級者の参考書だと考えたほうがいいだろう。RWH の説明は常にプログラムを作るためにはどうすればいいかということを考えてあるように見える。初心者は、Haskell という言語の使い方はどういうものかというのを知る必要がある。プログラムを作るために Haskell をどう使うかという説明には様々な要因が入り込んでくるので、わかりにくくなってしまうだろう。

RWH を読む前に簡単なチュートリアルで Haskell とは何かを知っておくと効率がいいのではないだろうか。
by tnomura9 | 2012-03-09 23:56 | Haskell | Comments(0)
<< 紫音リア うに式ミク >>