「ふつうのHaskellプログラミング」読みます(2)

3章やります。

3.1 型と値

読むだけ。型とか型推論、多相型とかはOCamlとかと似たようなもん(?)なので特にひっかかり無し。IO ()は「アクションの型」らしいです。

3.2 高階関数

これもOCamlSchemeとかあと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

これもOCamlScalaで経験してるからそんな戸惑わんけど。

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, (==)をつかった。全部関数。アクションとかは絡んでこない普通の人達。

3.6 練習

swapa

'a'と'A'を入れ替えるコマンドを作る。

main = do cs <- getContents
          putStr (map swapa cs)

swapa 'a' = 'A'
swapa c = c

できた。実6章まで読んでるからスッキリしたけど、これは標準入力を[Char]の無限リストとして評価してる。だから逐次処理になるんだなと。

% ghc swapa.hs -o swapa
% ./swapa
adsajifjac
AdsAjifjAc
jcxzidjife
jcxzidjife
adsfaij
AdsfAij

簡単。Haskellいいんじゃないか?

test