配列をスライスする。

[1..9] のリストを、3個の要素からなるリストに分けて、それらのリストのリストを作るにはどうすればいいか考えてみた。

まず、上の動作をする関数の名前を付ける必要がある。リストからテーブルをつくるので table とすることにした。

リスト xs の先頭から要素数3個のリストを切り出すには take 3 xs でいい。また、切り出した後の残りのリストは drop 3 xs で得られる。そうしておいて、先頭から切り出したリストを (:) 演算子で残りのリストと結合する。table はこの操作を再帰的に繰り返すので、table の再帰的部分の記述をまず作ってみる。

table n xs = (take n xs) : (table n (drop n xs))

再帰的定義では初期条件を決めておかないと、再帰的手続きが永遠に止まらないので、初期条件も決める。

table _ [] = []

空ののリストからはリストが切り出せないからだ。引数の評価のパターンは先に記述してる方からパターンマッチが行われるので、初期条件を最初に記述しておく必要がある。したがって、出来上がったプログラムは作ったときの順序とは逆で次のようになる。

table :: Int -> [a] -> [[a]]
table _ [] = []
table n xs = (take n xs) : (table n (drop n xs))

動作確認は Hugs で where を使ってやると便利だ。ghci では、このような where の使い方はできないので、きちんとファイルを作る必要がある。下の例が、Hugsで行った動作確認の例だ。

Hugs> table 3 [1..9] where table _ [] = []; table n xs = (take n xs) : (table n (drop n xs))
[[1,2,3],[4,5,6],[7,8,9]]

Haskellの繰り返しは再帰関数で行うのが普通なので上の手順のように、1)関数の名前の決定、2)再帰部分のプログラミング、3)初期条件のプログラミング、4)関数の型の明示的指定、の順にプログラムするとよい。最初はパズルを解くようで、奇異な感じがするが、慣れるとインデックスの指定やインデックスの範囲などを気にせずにロジックだけを考えればいいのでかえって楽になる。
[PR]
by tnomura9 | 2011-06-05 15:51 | Haskell | Comments(0)
<< パスカルの三角形を作ってみた Curry の不動点演算子のつくり方 >>