concatMapの便利なところ

便利そうなことを説明してみる。

concatMapの動作

まずはじめにconcatMapの動作についての説明を行う。
concatMapはその名前の示すとおりconcatとmapの組み合わせである。

1.concat seq :seqはListの入れ子型
concat ((1 2) (3 4))
=> (1 2 3 4)
concat ((1 2) (3 4) ((5 6)))
=> (1 2 3 4 (5 6))
Listの入れ子を一段階へらす。

2.map f seq :fはseqの要素を引数に取れる関数,seqはList型
map f (1 2 3 4)
=> ((f 1) (f 2) (f 3) (f 4))
mapは普通の
f:n->m
関数からList構造にマッチした関数
map f:List n-> List m
を生成する。

3.concatMap f seq :fはseqの要素を引数にとれるf:n -> List m型の関数,seqはList型
concatMapはconcatとMapの組み合わせ
concatMap f seq == concat (map f seq)
例えば、
plus-minus: n -> (-n +n)
のような関数があったとするとその動作は
concatMap plus-minus (list 1 2 3 4 5)
=>(-1 +1 -2 +2 -3 +3 -4 +4 -5 +5)
というようになる。動作を解析してみると
concatMap plus-minus (list 1 2 3 4 5)
->
concat (map plus-minus (list 1 2 3 4 5))
->
concat ((plus-minus 1) (plus-minus 2) (plus-minus 3) (plus-minus 4) (plus-minus 5))
->
concat ((-1 +1) (-2 +2) (-3 +3) (-4 +4) (-5 +5))
->
(-1 +1 -2 +2 -3 +3 -4 +4 -5 +5)
まとめると
    1. f:n -> List m型の関数をseqに適用
    2. seqがList型からListの入れ子型(List List型)になる。
    3. concatでList ListをListに落とす。
という動作を行っている。

mapの限界

ここではmapの限界について説明を行う。mapは関数の結果をまとめて得るのに非常に便利な関数である。
例えば、fibonacci数列の第1項~20項までの値を知りたいとする
gosh> (map fib (iota 20 1))
(1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765)
しかしながら、これは1価関数の場合であり多価関数の場合少しやっかいになる。
例えば、枝が0≦arccos≦2πのcos関数の逆三角関数arccosのとりうる値を列挙することを考える。
このarccosは枝の設定から1価関数でないので結果はListで返すとする
(arccos 1)
 => (0 2π)
結果の列挙のためにmapを用いたとするとこれは題意(列挙せよ)を満たさない
(map arccos (list -1 0 1))
=> ((π) (π/2 3π/2) (0 2π))
List List型でありこれは答え(値のList型として欲しい)としては不適当。
これに関してはmapや引数のfをいじることではどうにもならない。
mapは多価関数(多くの結果をもつ関数)の結果を列挙することに弱いのである。

ここで,concatが活用できる。この結果に対しconcatを用いると
(concat (map arccos (list -1 0 1))
=> (π π/2 3π/2 0 2π)
と、ちゃんと値のListに変形してくれる。

まだまだ・・・

集合操作におけるconcatMapの役割

タグ:

+ タグ編集
  • タグ:

このサイトはreCAPTCHAによって保護されており、Googleの プライバシーポリシー利用規約 が適用されます。

最終更新:2008年02月12日 23:45
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。