Wikiエンジンの開発

12.3 CGIの処理

loadContextの続き

今日は"foldr"関数です。
でも"foldr"関数だけを見ると逆に分かりにくいのである程度まとめてみていきます。

foldr            :: (a -> b -> b) -> b -> [a] -> b
foldr f z []     =  z
foldr f z (x:xs) =  f x (foldr f z xs)

and              =  foldr (&&) True

all p            =  and . map p

isBlank :: String -> Bool
isBlank = all isSpace


"isBlank"関数から簡約化していきます。
なお、"isBlank"関数の引数は"./config"の各行でした。
ここでは簡単に"ab c"という文字列(リスト)とします。

isBlank "ab c"
all isSpace "ab c"  ※isSpaceはとりあえずそのまま
(and . map isSpace) "ab c"
((foldr (&&) True) . map isSpace) "ab c"


さてここからです。
"isSpace"関数は後で見るとして、ここでは引数が' 'ならTrueを返すとして進めます。

foldr (&&) True [False, False, True, False]
((&&) False (foldr (&&) True [False, True, False]))
((&&) False ((&&) False (foldr (&&) True [True, False])))
((&&) False ((&&) False ((&&) True (foldr (&&) True [False]))))
((&&) False ((&&) False ((&&) True ((&&) False (foldr (&&) True [])))))
((&&) False ((&&) False ((&&) True ((&&) False (True)))))


二項演算子っぽく書くと

(False && (False && (True && (False && True))))
False && False && True && False && True


あらめて"foldr"関数の定義。

foldr            :: (a -> b -> b) -> b -> [a] -> b
foldr f z []     =  z
foldr f z (x:xs) =  f x (foldr f z xs)


なるほど、"foldr"関数は第三引数のリスト(ここの例では[Bool]型)の全ての要素を
第一引数の関数(ここの例ではBool -> Bool -> Bool型)で結び、
最後に第二引数(ここの例ではBool型)で結びます。


そして"and"関数。

and              =  foldr (&&) True


その関数名の通り、引数のリスト([Bool]型)全てに対して(&&)で結びます。
引数のリストが空リストの場合はTrueになります。


そして"all"関数。

all p            =  and . map p


引数のリストの各要素に対して関数"p"を適用します。
関数"p"の型はここの例では"[a] -> Bool"ですね。
その結果出てきたBool型のリスト全ての要素に対してAndをとります。


最後に"isBlank"関数。

isBlank :: String -> Bool
isBlank = all isSpace


あぁ、もうその関数名がコメントになっていますね。
すごく分かりやすい。
引数リスト(String)の各要素(Char)に対して"isSpace"関数を適用して、
それが全てTrueかどうかを判定しています。
つまり、引数の文字列がスペースだけの行かどうかを判定するわけです。


今日はここまで。
明日は"isSpace"関数を見ていきます。