Haskellの基礎(2) 型と高階関数

3.4 パターンマッチ

:演算子について

map関数の型、始め見たときよく分かりませんでした。

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


ですが、:演算子の説明を読み、

1 : [2,3]


とすることで[1,2,3]が得られることが分かったら理解出来ました。
map関数を再帰的に定義するには:演算子がないと厳しいですね。
よく考えられてるなぁ〜。


でもループのための構文がないとは驚きです。構造化プログラミングの三大構成要素の内の一つがないんですね。
それとよく分からなかったことがもう一つ。


リストに対するパターンマッチでは先頭要素とそれ以降のリストに分解するけど、
関数の中で使うと、逆にリストを生成する、という内容。


後半戦の「リストを生成する」というところは分かります。ghciで試すと一目瞭然。

Prelude> (1 : [])
[1]
Prelude> (1 : [2])
[1,2]
Prelude> (1 : [2, 3])
[1,2,3]


では前半戦の「パターンマッチでは分解する」というところ。これが分からなかった。
ですが、本にも書かれているように、map関数をトレースしてみるとよく分かりました。
こんな感じ。

map hogehoge [1, 2, 3]
map hogehoge (1 : [2, 3])
hogehoge 1 : (map hogehoge [2, 3])
hogehoge 1 : (map hogehoge (2 : [3]))
hogehoge 1 : (hogehoge 2 : (map hogehoge : [3]))
hogehoge 1 : (hogehoge 2 : (map hogehoge (3 : []))
hogehoge 1 : (hogehoge 2 : (hogehoge 3 : (map hogehoge [])))
hogehoge 1 : (hogehoge 2 : (hogehoge 3 : []))
hogehoge 1 : (hogehoge 2 : [hogehoge 3])
hogehoge 1 : [hogehoge 2, hogehoge 3]
[hogehoge 1, hogehoge 2, hogehoge 3]


なるほどパターンマッチ時に確かにリストリテラルが、(x : xs)に分解されていますね。
納得です。

3.5 本章のまとめ

練習問題がんばるぞ!

3.6 練習問題

まずは自力で解いてみます。こんな感じ。

main = do cs <- getContents
          putStr $ swapa cs

swapa :: String -> String
swapa cs = map swapaA cs

swapaA :: Char -> Char
swapaA 'a' = 'A'
swapaA 'A' = 'a'
swapaA  c  = c


仕事で書いたら怒られてしまいそうな関数名ですが…。
一応正しく動いているみたい。
サポートページみたらまぁまぁ同じでした。