プログラミング勉強ログ

プログラミングの勉強記録

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

 

今日はここまで。