Yet Another Haskell 3章 (3.2)
3.3.2 Simple List Functions
代表的なリスト操作関数について
Haskellプログラムの殆どはリストの操作である。
3つのプリミティブなリスト処理関数がmap, filter, foldr(とfoldl)である。
map
mapはリストのそれぞれの要素に対して、与えた関数を適用し、その結果のリストを返す。
Prelude> map Data.Char.toUpper "hello"
"HELLO"
(GHCiでもWinGHCiでも、原文のChar.toUpperでは駄目だった)
map toUpper "hello"は
map toUpper ['h','e','e','l','l','o']と同じ
そして結果は
[toUpper 'h', toUpper 'e', toUpper 'l', toUpper 'l', toUpper 'o']と同じと。
Prelude> [Data.Char.toUpper 'h', Data.Char.toUpper 'e', Data.Char.toUpper 'l', Data.Char.toUpper 'l', Data.Char.toUpper 'o']
"HELLO"
filter
filterはリストのそれぞれの要素に対し、与えた関数を適用し、その結果がFalseになった要素を取り除いたリストを返す。
Prelude> filter Data.Char.isLower "Hello World"
"elloorld"
はい。
foldr (foldl)
foldr(とfoldl)は関数(2つの引数を取り、同じ型の結果を返すもの)、初期値、リストの3を引数に取る。
foldr (+) 0 [3, 8, 12, 5]としたとき、foldrは以下のような計算をする
(3 + (8 + (12 + (5 + 0))))
一方、foldlは
((((0 + 3) + 8) + 12) + 5)
与える関数が+だと結果は変わらない。
Prelude> foldr (+) 0 [3, 8, 12, 5]
28
Prelude> foldl (+) 0 [3, 8, 12, 5]
28
これは、+が結合法則を満たすからですね。
(+に括弧が付いているのは、確か+を関数名として扱うためだったと思う。)
-だと結果が変わる。
(3 - (8 - (12 - (5 - 0)))) = 2だから、
Prelude> foldr (-) 0 [3, 8, 12, 5]
2
((((0 - 3) - 8) - 12) - 5) = -28だから、
Prelude> foldl (-) 0 [3, 8, 12, 5]
-28
附則
foldlはfoldrより効率が良い。
一方、foldlは無限リストを扱えないが、foldrは扱える。
詳細は7.8で扱う。
Excecise 3.3
Prelude> map Data.Char.isLower "aBCde"
[True,False,False,True,True]
Excecise 3.4
Prelude> length (filter Data.Char.isLower "aBCde")
3
Excecise 3.5
Prelude> foldl max 0 [5,10,2,8,1]
10
Excecise 3.6
Prelude> fst (head (tail [(5,'b'),(1,'c'),(6,'a')]))
1
今日はここまで。