「ふつうのHaskellプログラミング」読みます(2)
3章やります。
3.2 高階関数
これもOCaml、SchemeとかあとRubyとかでも頻出の概念なので特に違和感無し。
expand0.hs
main = do cs <- getContents putStr (expand cs) expand :: String -> String expand cs = map translate cs translate :: Char -> Char translate c = if c == '\t' then '@' else c
mapでtlanscateしてタブ文字を@に変えてる。
% ghc expand0.hs -o expand0 % ./expand0 abcd ef abcd@ef aaaaa aaaaa
上のソースでは書いてあったけど、このプログラムなら型推論が成功するので、以下のソースでいける。
main = do cs <- getContents putStr (expand cs) expand cs = map translate cs translate c = if c == '\t' then '@' else c
expand1.hs
main = do cs <- getContents putStr (expand cs) expand cs = concat (map expandTab cs) expandTab c = if c == '\t' then " " else [c]
concatが増えてますね。concatはリストを一重減らす関数。Stringは[Char]なので[c]がStringですね。型はめんどくさいので型推論任せです。
% ghc expand1.hs -o expand1 % ./expand1 abc def abc def
3.3 パターンマッチ
expand2.hs
これもOCaml、Scalaで経験してるからそんな戸惑わんけど。
tabStop = 4 main = do cs <- getContents putStr (expand cs) expand cs = concatMap expandTab cs expandTab '\t' = replicate tabStop ' ' expandTab c = [c]
concatMap f xs = concat (map f xs)。replicate n cで、[c, c, c, ...]でcがn個のリスト。rubyのStringに対する乗算みたいなもんですね。
パターンマッチは楽でいいですね。OCamlのfunctionみたいなもんですね。SMLだとfunだったかな。ML系のそれの文法と違って、別行に書いちゃうってのもなんかわかりやすい気もする。
% ghc expand2.hs -o expand2 % ./expand2 ab cde ab cde
3.4 パターンマッチ(2)
mapの定義とか。なんかSICPとかで見覚えあるような置き換えモデルぽいのが並んでる。
3.5 まとめ
map, concat, concatMap, replicate, (==)をつかった。全部関数。アクションとかは絡んでこない普通の人達。