ふつける 4章 - ユニークにならない
久しぶりにふつける読み。
はまりまくりっすよ。はまりまくり。
uniqを作れ
(ヒント: group使えばいいよ!!)
って書いてあるんだけど、全然ユニークにならない。
groupは隣接してれば、グループにまとめるみたい。
Prelude> import List Prelude List> group [1, 1, 2, 1, 1] [[1,1],[2],[1,1]]
だめじゃん。
groupはuniqするには向いてないと思うんだよ。
じゃ、お兄さんがuniq書いちゃうぞ〜
と思って書いてみたらはまりまくり。
remove :: (a -> Bool) -> [a] -> [a] remove f [] = [] remove f (x:xs) = if (f x) then remove f xs else x : remove f xs uniq :: (Eq a) => [a] -> [a] uniq [] = [] uniq (x:xs) = x : (uniq $ remove (x ==) xs) test = uniq ["ABC" , "XYZ", "ABC", "XYZ", "ABC"] -- ["ABC", "XYZ"]
uniq :: [a] -> [a]ってやってたら、型エラーでまくり。
uniq :: [String] -> [String]はうまくいくんだよ。
[a]にするとダメ。
んじゃーと思って、groupの真似して、(Eq a) => ってのを付けてみたら、うまくいった。
(Eq a) => ってナンダ・・・。
型クラス
何故型エラーが出るのかわからないので、ちと9章を先読み。
問題は、uniq内で"=="を使ってることが問題っぽい。
[a]はリストなら何でも来い。という型。
でも、==を使ってしまった場合、「aという型は比較するためのメソッドが必要となる」という制約を受ける。
だから、Eqクラスを継承したオブジェクトじゃないと比較できないジャン!!と言いたいらしい。
総称型で==使う時は(Eq a) =>が必要となる。っと。
foldlで書き直し
fold使えばいい。
remove :: (a -> Bool) -> [a] -> [a] remove f s = foldl (\acc x -> if (f x) then acc else x:acc) [] s uniq :: (Eq a) => [a] -> [a] uniq s = foldl (\acc x -> x : (remove (x ==) acc)) [] s
ずーっと右側に伸びていきそうなんだけど、どこで折り返すべきなんだろうか。
まとめ
今日ははまりまくり。
型ってムズイ。