HaskellでFizzBuzz問題を解く(4)

 前々回http://d.hatena.ne.jp/marony0607/20111025/1319547210の続きです。
 ruiccさんにコメント欄でElem型に比較演算子などを定義する方法を教えていただいたので、それを自分なりに使用して綺麗なコードに書き換えてみました。

 まず、Elem型をShow, Eq, Ord型から派生?させました。

data Elem = I Int | S String deriving (Show, Eq, Ord)
 これで、showの引数で使えたり比較演算子が定義されたりします。よって、前々回の比較関数などがごっそり必要なくなりました。

 そのおかげでmyElem演算子(関数)もだいぶすっきりしました。

 -- myElem(引数xがリストyに含まれていたらTrue)
myElem :: Elem -> [Elem] -> Bool
myElem (I x) ((I y):ys) | x < y = False
| x == y = True
| otherwise = myElem (I x) ys -- ここなんでただの"x"じゃダメなんだろう?
myElem _ _ = False

 あとは、fizzBuzz関数で3回違う引数で関数を呼び出しているのを綺麗に纏めたいとか、mainも関数を連鎖で呼び出しているので綺麗に纏めたいとかあるんですが、ひとまずこれで倍数の集合(無限のリスト)を使ってFizzBuzz問題を解くのは終わりにしようと思います。
 識者の方の改善案は随時コメント欄で募集中です。
 ではでは。

 -- Int型を持つIとString型を持つSのどちらか
data Elem = I Int | S String deriving (Show, Eq, Ord)

-- myElem(引数xがリストyに含まれていたらTrue)
myElem :: Elem -> [Elem] -> Bool
myElem (I x) ((I y):ys) | x < y = False
| x == y = True
| otherwise = myElem (I x) ys -- ここなんでただの"x"じゃダメなんだろう?
myElem _ _ = False

-- zがyに含まれていたらxに変換(引数の順番が嫌…)
f :: String -> [Elem] -> Elem -> Elem
f x y z = if z `myElem` y
then S x
else z

-- Elemのリストを"Fizz", "Buzz", "FizzBuzz"の含まれたリストに変換
fizzBuzz :: [Elem] -> [Elem]
fizzBuzz x = map fizz (map buzz (map fizzbuzz x)) -- ここを'.'演算子にしたい
where fizz = f "Fizz" $ map I [3, 6..]
buzz = f "Buzz" $ map I [5, 10..]
fizzbuzz = f "FizzBuzz" $ map I [15, 30..]

-- メイン関数
main = putStrLn $ unwords a
where a = map show b
b = map (\x -> x) c -- 何もしてない
c = fizzBuzz $ map I [1..100]