一個のリストから何個もの情報をとりだすコードはどう書くのがいいんだろう
例えば、下の行数カウントプログラムは、次のように書くのが一番キレイだと思う。
-- 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
(続きたい)