ふと、手続き型言語だとちょっと大変かな?と思ったプログラム

前回、numberingコマンドを作ってて思ったのですが、手続き型言語はファイルから読む時に1行毎に読むと言うのをコードからも指定している訳ですが、ファイルの中身を全部逆にして、ナンバリングするコマンド(仮にrevnumberingコマンドとします)だと、手続き型言語だとちょっと大変なのかなー・・・と、考えたのですが、どうなんでしょうね?
(所詮はナンバリングコマンドの変形なので、大変って程でも無いけど)

Haskellで書く分にはnumberingコマンドのコード

import System.Environment

numbering = unlines.(map (\(x,y) -> show x ++ y)).(zip [1..]).lines

main = getArgs >>= \args -> mapM readFile args >>= return.map numbering >>= 
			(mapM_ (\(x,y) -> putStrLn $ x ++ "\n" ++ y)).zip args

に、"return.map reverse >>="を挟んでやるだけなのですが・・・

revnumberingコマンドのコード

import System.Environment

numbering = unlines.(map (\(x,y) -> show x ++ y)).(zip [1..]).lines

main = getArgs >>= \args -> mapM readFile args >>= return.map reverse >>= return.map numbering >>= 
			(mapM_ (\(x,y) -> putStrLn $ x ++ "\n" ++ y)).zip args

自分が、手続き型言語で書くとしたら、1行毎に読み込んでいるファイルの内容を一旦、文字型の配列なり文字列型なりの変数に格納して、reverseしてから、ナンバリングする感じでしょうか。

Haskellも裏では1行毎に読んでるかもしれませんが、コード上はただファイルの内容が文字列として返ってくるだけなので、こう言う、多少イレギュラーな流れの処理では関数型言語の方が楽なのかなー・・・?とか思ってみたり。

率直なご意見・ご感想・コード(これ重要)。お待ちしております。

ちょっち訂正
こっちでも行けた。

import System.Environment

numbering = unlines.(map (\(x,y) -> show x ++ y)).(zip [1..]).lines

main = getArgs >>= \args -> mapM readFile args >>=  return.map (numbering.reverse) >>= 
			(mapM_ (\(x,y) -> putStrLn $ x ++ "\n" ++ y)).zip args

でも、なぜかnumbering.reverseは関数合成で一つの関数なのに、括弧を外すと上手く動かない不思議。

あ、revnumberingコマンドで、自身のコード(revnumbering.hs)を出力するとこうなります。

revnumbering.hs
1sgra piz.))y ++ "n\" ++ x $ nLrtStup >- )y,x(\( _Mpam(
2 =>> )esrever.gnirebmun( pam.nruter  =>> sgra eliFdaer Mpam >- sgra\ =>> sgrAteg = niam
3
4senil.)]..1[ piz(.))y ++ x wohs >- )y,x(\( pam(.senilnu = gnirebmun
5
6tnemnorivnE.metsyS tropmi