■
自作ライブラリとそれを使った成果物。
LLだとここまでライブラリ化するとreverse使わない場面でもメモリに溜め込みまくったり、それを解消するためにイテレータ作りまくったりする必要があるんじゃなかろうか。
それでなくとも副作用と純粋部分が分かれてない処理があるとライブラリ化しにくい。
rpコマンドはreplaceとかrepと付けたかったけど、sudo apt installしてないパッケージに同名のコマンドが複数あるらしいので。
rpコマンド、なるべくユニークな文字列にしないと危険だけど、関数名や引数の名前や順序変えた時に複数ファイル・複数箇所を修正するので地味に大活躍…。
Myfunc.hs(自作ライブラリ) module Myfunc where import Data.List import Text.Printf consnum::(Int,String) -> String consnum (i,xs) = printf "%4d:%s" i xs fline f = unlines.f.lines fnumbering f = fline ((map consnum).(zip [1..]).f) redstr::String -> String redstr [] = [] redstr w = printf "\ESC[1m\ESC[31m%s\ESC[39m\ESC[0m" w bluestr::String -> String bluestr [] = [] bluestr w = printf "\ESC[34m%s\ESC[39m" w grep w = fline (filter (isInfixOf w)) replace _ _ [] = [] replace [] _ cs = cs replace w nw cs | w == take (length w) cs = nw ++ replace w nw (drop (length w) cs) replace w nw (c:cs) = c:replace w nw cs putfc (f,c) = printf "%s\n%s" f c writefc (f,c) = writeFile f c mfptn fs f ofs output = mapM readFile fs >>= return.(zip ofs).map f >>= mapM_ output mfput f fs = mfptn fs f (map bluestr fs) putfc mfwrite f fs = let tfs = map (++ ".temp") fs in mfptn fs f tfs writefc >> mfptn tfs id fs writefc number.hs(ナンバリングコマンド) import System.Environment import Myfunc main = getArgs >>= mfput (fnumbering id) revnumber.hs(行番号付き行の逆順表示コマンド) import System.Environment import Myfunc main = getArgs >>= mfput (fnumbering reverse) mygrep.hs(検索文字列のある行を表示するコマンド。見つかった文字列を強調赤字で表示) import System.Environment import Myfunc main = getArgs >>= \(w:fs) -> mfput ((replace w (redstr w)).(grep w).fnumbering id) fs rp.hs(文字列置換コマンド) import System.Environment import Myfunc main = getArgs >>= \(w:nw:fs) -> mfwrite (replace w nw) fs