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