Haskellことはじめ


ここのところ、ふつける(ふつうのHaskellプログラミング)を読んだりしながら Haskellをちまちまと勉強しているのだけど、ようやく体に入ってきた感じがする。
昨日の「どう書く?org」のお題を解いてみたら、同様の回答がすでにあったのだけど、メモのために導出の過程を自分のブログに書いておくことにする。
Haskellのコードをはてダに書いたことないし。


お題と Haskellによる回答は次のとおり。

文字列に含まれる単語について、それぞれの単語の最初の文字を大文字にしてください。
たとえば、"LL future" と与えられたときは "LL Future" と出力する。"LL day and night" と与えられたときは "LL Day And Night" と出力する。

LL Golf Hole 2 - 文字列に含まれる単語の最初の文字を大文字にする Haskellどう書く?org
http://ja.doukaku.org/196/lang/haskell/

自分の回答

import Data.Char
main = getContents >>= putStrLn . unwords . map (\(x:xs) -> toUpper x : xs) . words

getContentsを使って標準入力からテキストを入力し、putStrLnにつなぐ、といった内容。
で、ことはじめということで、導出の過程を書いておく。

step1 複数の関数を定義

まずは mainを使わず、mytoupperという関数を定義して、関数定義の仕方とか処理の流れを確認した。

import Data.Char(toUpper)

mytoupper :: String -> String
mytoupper str = unwords $ foo $ words str

foo :: [String] -> [String]
foo [] = []
foo (x:xs) = bar x : foo xs

bar :: String -> String
bar (y:ys) = toUpper y : ys


あと、fooと barは myupperの中でだけ使う、ということを示すために where節を使ってもよいかも。

import Data.Char(toUpper)

mytoupper :: String -> String
mytoupper str = unwords $ foo $ words str
    where
        foo :: [String] -> [String]
        foo [] = []
        foo (x:xs) = bar x : foo xs

        bar :: String -> String
        bar (y:ys) = toUpper y : ys
step2 関数合成の適用

mytoupperに関数合成を適用して、引数の strをなくすとともに $ による連結から . による連結に変更した。
また、fooと barに分けていた処理を fooに一本化した。

import Data.Char(toUpper)

mytoupper :: String -> String
mytoupper = unwords . foo . words

foo :: [String] -> [String]
foo [] = []
foo ((y:ys):xs) = (toUpper y : ys) : foo xs
step3 無名関数と mapの適用

fooに分けていた処理を無名関数にして、mapで適用することにした。
これで基本となる処理は一行になった。

import Data.Char(toUpper)

mytoupper :: String -> String
mytoupper = unwords . map (\(x:xs) -> toUpper x : xs) . words
step4 入出力を追加 (do式)

mytoupperで関数にしていた部分を do式の中におさめて、標準入力から受け取ったテキストを標準出力に書き出すようにした。

import Data.Char(toUpper)
main = do cs <- getContents
          putStrLn $ unwords $ map (\(x:xs) -> toUpper x : xs) $ words cs


あとは do式で書いた部分を IOモナドで (>>=)を使って書き直せば、自分の回答になる。
importも Data.Charの指定までで済むので (toUpper)は省いた。
これで、ふつけるの 11章までの内容をおさらいできたことになるかな。

Haskellおもしろい

Haskellの感じがつかめてきたので、このあと、Parsecライブラリを使ったパーサコンビネータに進むつもり。
これまで yacc/lexで書いていた処理を、これからは Haskellで書こう、と、もくろんでいる。
Haskellおもしろいなぁ。


あと、ふつける以外で参考にしてるのが、英語だけど O'Reilly Mediaがまとめている Real World Haskellという書籍の web版。
ベータ版という位置づけだけど、サンプルコードも多くて、十分勉強になる。
まだ読み進められてないけど、ネットワークプログラミング(28章)とか並列プログラミング(26章)、データベース操作(23章)といった事柄についても説明していて楽しみなのです。


Real World Haskell

書籍 web版
http://book.realworldhaskell.org/beta/

ブログ
http://www.realworldhaskell.org/blog/