Я частенько тоже в хацкеле так делаю, хоть это и не ООП-язык:
process fname = do
putStrLn $ "Processing " ++ fname ++ " ..."
dat <- readFile fname
let dat2 = dat
|> lines
|> map (map (\c -> [c]))
|> map (map (\s -> if s == "\t" then "\t0" else s))
|> map concat
|> map words
|> filter (\xs -> length xs > 6)
|> map (\(time: inorg:incompr:intransm:outorg:outcompr:outtransm:_) ->
(time,[inorg,incompr,intransm,outorg,outcompr,outtransm]))
|> map (\(time, xs) -> (take 2 (if length time == 5 then '0':time else time)
,map (read :: String -> Int) xs))
|> groupBy (\(t1, _) (t2, _) -> t1 == t2) -- сгруппируем по часам
|> map (\xs -> (fst $ head xs, map snd xs))
|> map (\(time, xs) ->
(time, map (\[inorg,incompr,intransm,outorg,outcompr,outtransm] ->
(inorg,incompr,intransm,outorg,outcompr,outtransm)) xs))
|> map (\(time, xs) -> (time, unzip6 xs))
|> map (\(time, (inorg,incompr,intransm,outorg,outcompr,outtransm)) ->
(time, [inorg,incompr,intransm,outorg,outcompr,outtransm]))
|> map (\(time, xs) -> (time, map sum xs))
|> map (\(time, xs) -> (time, map (\x -> trunc3 $ fromIntegral x / (1024*1024::Double)) xs))
|> map (\(time, xs) -> unwords' (time:(map show xs)))
writeFile (fname ++ ".out") $ unlines dat2Здесь оператор |> создаёт конвейер типа как pipe в юниксовой консоли. Его можно по сути считать в данном случае точкой, разделяющей объект и вызов его метода в том же Расте.
Проблема таких конвейерных обработок -- через какое-то время трудно понять что там задумывалось, даже более того -- стоит отвлечься на что-то во время написания этого кода -- и уже приходится соображать, что надо дальше в этом конвейере сделать.
Так что иногда всё же вставляю дополнительные переменные, указываю их тип, а то начинаю париться с этими типами ))
Ну, для одноразовых скриптиков можно и так наговнякать )))