前章に引き続き,
永続データとしてのリスト
関数プログラミングの入門書では,
関数プログラミングの説明をリストから始めるのはよくないと主張する人もいます。なぜなら,
リストには3つの基本的な操作があります。
- リストの先頭に要素を加える
- リストの先頭要素を取り出す
- リストの先頭要素を取り除いた残りのリストを取り出す
驚くべきことに,
- 注1)
- Haskellの場合,
文字列であればByteStringやTextなどです。
リストの先頭に要素を加える
Haskellでリストの先頭に要素を加えるには,
> let xs = ['b','o','a','r','d']
> let ys = 'a' : xs
> ys
"aboard"
文字列
では,
関数プログラミングでは再代入はできませんから,
> xs
"board"
このように,
リストから先頭要素を取り出す
Haskellで,
> head ys
'a'
先頭要素を取り除いた残りのリストを取り出す
また,
> tail ys
"board"
ただし,
パターンマッチでリストの一部を取り出す
パターンマッチの例として,
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
関数の引数に現れるf,
この関数の意味するところは次の通りです。
- 第二引数が空リストにマッチしたら空リストを返す
- 第二引数が空でないリストにマッチしたら,
「fをリストの先頭に適用した結果」 を 「残りのリストを自分自身で処理した結果のリスト」 の先頭に加える
このようにHaskellでは,
実際の動作例を図3に示します。
図3 mapの動作例
['1','a']の各要素にisDigitを適用するためmapを使う
map isDigit ['1','a']
↓
'1'にisDigitが適用され,
isDigit '1' : map ['a']
↓
isDigit '1'がTrueになる
True : map ['a']
↓
'a'にisDigitが適用され,
True : isDigit 'a' : map isDigit []
↓
isDigit 'a'がFalseになる
True : False : map isDigit []
↓
map isDigit []が[]になる
True : False : []