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

Data.List モジュールの使い方(7) map 関数の仲間

Data.List モジュールには非常に多くの関数がある。そのため、Haskell のホームページからユーザーズマニュアルをたどると、機能の似たもの同士をグループ分けして説明されている。それについては、この一連の記事の最後で取り上げようと思うが、関数の使い方を学ぶという点からは必ずしも使いやすい分け方ではない。

そこで、当分は、系統的な記述にはならないが、使う側の立場からこれらの関数をグループ分けして調べてみることにする。

Data.List モジュールの関数は、鋸や鉋のような汎用の工作道具のような関数が多い。それは、リストがデータ処理のための汎用の容器のような使われ方をするからだ。

リストのデータ構造は、あるグループの要素的なデータの集まりに対して特定の処理を繰り返し行うというような作業で頻繁に利用される。手続き型のプログラムで頻繁に現れるループの構造の大半はリスト処理として扱うことができる。

例えば、1から10までの整数の和を求めるようなプログラムは、手続き型のプログラムの場合ループを使って次のように記述する。

irb(main):009:0> begin
irb(main):010:1* total = 0
irb(main):011:1> for i in 1..10
irb(main):012:2>   total += i
irb(main):013:2> end
irb(main):014:1> puts total
irb(main):015:1> end
55

こういう繰り返しの操作は、Haskell ではリストに対する関数の適用として記述される。

Prelude> sum [1..10]
55

したがって、Data.List モジュールの関数に習熟すれば、このような繰り返しの処理を効率的に記述することができるようになる。Data.List ライブラリには多くの関数があるが、繰り返しを記述するための道具としての関数には大きく map, fold, zip, 無限リストの処理 という4種類の機能に分類することができる。

ところで、Haskell の関数の記述をする時に、小さいプログラムの時は型宣言を省略することが多い。Haskell には型推論の機能があり自動的に判別してくれるからだ。しかし、この型宣言は、ライブラリの関数や、サブルーチンとして使う関数の機能を調べるときには非常に便利だ。関数の型宣言の部分を見れば、その関数がどういう作業をするのかを大まかに推測することができる。

例えば map 関数の型宣言は次のようになっているが、map 関数が、一個の引数をとるタイプの関数をリストに適用して、リストの戻値を戻すのだなということがなんとなく分かる。

map :: (a -> b) -> [a] -> [b]

こういうライブラリの関数を調べるときに、一番便利なのは戻値のデータ構造を知るということだ。関数のタイプ宣言の最後に現れる戻値の型を知れば、その関数を次のどんな関数につないで使うのかということを推測することができるからだ。上の map 関数の型宣言を見れば、[a] というリストに処理を施して [b] というリストを戻すから、次にはその戻された [b] というリストを使って処理を続けるのだという予測することができる。

このように、単一のリストに処理を施して単一のリストの戻値を得る関数を仮に map 型の関数と呼ぶことにすると、Data.List モジュールに記述された map 型の関数には次のようなものがある。

map, tail, init, reverse, intersperse, take, drop, takeWhile, dropWhile, filter, delete, sort, insert, nubBy, deleteBy, sortBy, insertBy, genericTake, genericDrop

比較的よく使うものもあるので、次の記事では、これらのうち見慣れないものについて調べてみることにする。
by tnomura9 | 2011-08-20 07:26 | Haskell | Comments(0)
<< Data.List モジュール... Random モジュールの使い方 >>