ふつける練習問題を解く:3,4章

レポートのお陰で,活発にHaskellの勉強ができなかった鬱憤を晴らすかのような,一日で三度目のHaskell更新.とは言うものの,記事そのものは一気に書いてますけど.


とりあえずテキスト処理をしなければいけないので,テキストを用意.

RubyPerl
RubyPerl
JavaC++.NET
PythonSmalltalk
PythonSmalltalk

3章

大まかな狙いは,「高階関数は素敵だよ」だと思う.

標準入力の'a'と'A'を入れ替える

まずは高階関数を使わず,再帰で解く.

main = do cs <- getContents
                 putStrLn $ swapa cs

swapa [] = []
swapa (c:cs) | c == 'a' = 'A': swapa cs
                   | otherwise = c : swapa cs

次に,高階関数を使って.

main = do cs <- getContents
                 putStrLn $ swapa cs

swapa cs = map swap cs

swap c = if c == 'a' then 'A' else c

実行結果

$ ./swapa < lang.txt 
RubyPerl
RubyPerl
JAvAC++.NET
PythonSmAlltAlk
PythonSmAlltAlk
追記

ちゃんとしたバージョン.

swapa cs = map swap cs

swap 'a' = 'A'
swap 'A' = 'a'
swap c = c

パターンマッチの方が,if文を使うよりも綺麗に書けて良いかな,と.

4章

大まかな狙いは,「importは便利だよ」だと思う.

標準入力を行単位でソートする

List.sortを使っちゃおう,という問題.

import List

main = do cs <- getContents
                 putStrLn $ unlines $ sort $ lines cs

文字列を扱うイディオムとして「unlines $ (何か操作) $ lines cs」みたいに覚えちゃおう,らしい.
実行結果.

$ ./sort < lang.txt 
JavaC++.NET
PythonSmalltalk
PythonSmalltalk
RubyPerl
RubyPerl
同じ行が連続していたら一行にまとめる

List.groupを使っちゃおう,という問題.

import List

main = do cs <- getContents
                 putStrLn $ unlines $ map head $ group $ lines cs

実行結果.

$ ./uniq < lang.txt 
RubyPerl
JavaC++.NET
PythonSmalltalk

一応チラッと答を見たんだけど,なんかかっこ良かった.

import List

main = putStr . unlines . map (head) . group . lines =<< getContents

なるほどなんだが,最後の(=<<)を回答だからと言って,突然披露するのが凄いと思った.