一個のリストから何個もの情報をとりだすコードはどう書くのがいいんだろう

例えば、下の行数カウントプログラムは、次のように書くのが一番キレイだと思う。

-- xsが各ファイルの行数のリスト
-- (<100行未満のファイルの個数>, <100行以上のファイルの個数>)を返す
lineStatics :: [Int] -> (Int,Int)
lineStatics xs = (length $ filter (< 100) xs,
	          length $ filter (>= 100) xs)

でも、リストを二回も走査してるのが無駄な気がする。とういうわけで、foldを使って書き直したりする。

f (a,b) x = if x < 100 then
                (a+1,b)
            else
                (a,b+1)

lineStatics xs = foldl f (0,0) xs

でも毎回関数を書くのは面倒だよね。できれば、既存の関数を適当なコンビネータで継ぎたい。
とうわで、Arrowを使ってみたりする。

countFor p x = arr $ \n -> if p x then n + 1 else n

g x = countFor (< 100) x *** countFor(>= 100) x
lineStatics xs = foldl (flip g) (0,0) x

(続きたい)