Haskellの基礎(3) モジュールと総合演習
4.2 総合問題
対になってる関数
遂になってる関数としてまとめられていて分かりやすかったので。
lines :: String -> [String] unlines :: [String] -> String
linesして、行単位で処理してからunlinesで文字列にする。
確かにイディオムとして考えるとよい感じですね。
head :: [a] -> a tail :: [a] -> [a]
こちらも対になってて分かりやすいんだけど、なぜ引数に空リストを指定すると実行時エラーになるんだろう?
今までの流れからすると空リストを返すと思った(headは無理ですけど)。
これらの関数を使う時は空リストチェックが必要になるんだろうなぁ、と思いつつ。
where節について
where節は、他の入門サイトなどを眺めていてよく理解出来なかったものの一つ。
でも本書の説明はとても分かりやすい♪
ある関数の中だけで使える関数を定義する時に利用するんですね。
スコープがある関数の中というわけですね。
あとちょっと気になったのは、patternという変数。
where節に定義された関数からは、where節がかかっている関数内の変数を見ることが出来るんですね。
4.3 本章のまとめ
4.4 練習問題
問題1
上で書いたイディオム(lines+unlines)を使うんですね。
まずは自力でおりゃっ!…の前にちょっと実験。
Prelude List> sort [1,3,2] [1,2,3] Prelude List> sort ["abc","def","bcd"] ["abc","bcd","def"]
なるほどぉ、sortは値だけじゃなく、文字列などのリストもオッケーなんですね。
そりゃそうか、関数の型にそんな制約ないからね。
ということで、こんな感じになりました。
import List main = do cs <- getContents putStr $ sortlines cs sortlines :: String -> String sortlines cs = unlines $ sort $ lines cs
うん、いい感じ♪
問題2
これももちろんlines→unlinesのイディオムを使います。
でもこれはそんな簡単じゃないなぁ。ちょっと考えてみる。
List.group関数で同じ要素がリストにまとめられるので、その各リストの先頭要素を取り出して要素にすればいい。
この方針でちょっと実験。
Prelude List> map head $ group ["abc","abc","bcd","bcd","cde"] ["abc","bcd","cde"]
よしよし、うまくいきそうだ。この勢いで作ってみました。
import List main = do cs <- getContents putStr $ uniq_lines cs uniq_lines :: String -> String uniq_lines cs = unlines $ map head $ group $ lines cs
テストファイルを使って、こんな感じでやってみました。
$ cat test.txt abc abc bcd bcd abc cde $ ./uniq < test.txt abc bcd abc cde
おぉ、ちゃんと隣り合う同じ行が一つにまとまってる♪