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