ふつける 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

ずーっと右側に伸びていきそうなんだけど、どこで折り返すべきなんだろうか。

まとめ

今日ははまりまくり。


型ってムズイ。