Haskell 関連(当面)最後の記事

Haskell のいいところは関数をつなげて使うことができることだ。たとえば、前回の記事で紹介した組み合わせを列挙するプログラムを利用して活用することができる。

とりあえず、Hugs で次のプログラムを作成して load してみよう。

Hugs> :e comb.hs

(comb.hs の内容。List モジュールを import しているのは後で sort 関数を使いたいから。)
import List

comb _ 0 = [[]]
comb [] _ = []
comb (x:xs) n = map (x:) (comb xs (n-1)) ++ comb xs n

Hugs> :l comb.hs
Main>

comb 関数が機能するかどうかテストしてみる。

Main> comb "abc" 2
["ab","ac","bc"]

ここで、1円から100円までのコインのリストについて、とりえるすべての組み合わせを考えてみる。取り出し方も1個から5個までのすべての個数について試してみる。このためには map 関数を利用するのが便利。

Main> map (comb [1,5,10,50,100]) [1..5]
[[[1],[5],[10],[50],[100]],[[1,5],[1,10],[1,50],[1,100],[5,10],[5,50],[5,100],[10,50],[10,100],[50,100]],[[1,5,10],[1,5,50],[1,5,100],[1,10,50],[1,10,100],[1,50,100],[5,10,50],[5,10,100],[5,50,100],[10,50,100]],[[1,5,10,50],[1,5,10,100],[1,5,50,100],[1,10,50,100],[5,10,50,100]],[[1,5,10,50,100]]]

これでは、取り出す枚数ごとにリストでまとめられているので concat ですべてを一本のリストにする。

Main> concat $ map (comb [1,5,10,50,100]) [1..5]
[[1],[5],[10],[50],[100],[1,5],[1,10],[1,50],[1,100],[5,10],[5,50],[5,100],[10,50],[10,100],[50,100],[1,5,10],[1,5,50],[1,5,100],[1,10,50],[1,10,100],[1,50,100],[5,10,50],[5,10,100],[5,50,100],[10,50,100],[1,5,10,50],[1,5,10,100],[1,5,50,100],[1,10,50,100],[5,10,50,100],[1,5,10,50,100]]

こうなると、その集計が sum で計算できる。

Main> map sum $ concat $ map (comb [1,5,10,50,100]) [1..5]
[1,5,10,50,100,6,11,51,101,15,55,105,60,110,150,16,56,106,61,111,
151,65,115,155,160,66,116,156,161,165,166]

金額の順序がばらばらなので sort で整理してみる。

Main> sort $ map sum $ concat $ map (comb [1,5,10,50,100]) [1..5]
[1,5,6,10,11,15,16,50,51,55,56,60,61,65,66,100,101,105,106,110,111,
115,116,150,151,155,156,160,161,165,166]

このように、Haskell で一つ関数を作るとそれを次々に組み合わせることでいろいろな問題に対処できる。一つの問題に一つのプログラムになりやすい手続き型のプログラム言語に比べると、使い捨てプログラムをつくるのに特に有利なのが分かる。

これで、Haskell が使い捨てプログラムに使えるのではないかという問題提起に一応の結論が出たので、本当に、本当にこれが Haskell 記事の最後の記事にしたい。また、面白いアイディアがあったら Haskell のネタで記事を書きたいと思う。
[PR]
by tnomura9 | 2009-09-08 12:42 | Haskell | Comments(0)
<< 脳内マインドマップ 勝間和代を目指さない >>