ファイル名を10文字にする関数(重複があっても大丈夫)

30分プログラム、その608。ファイル名を一括して先頭10文字に短くするバッチ - バッチもん研究所 bloghttp://gauc.no-ip.org/awk-users-jp/blis.cgi/DoukakuAWK_172にインスパイアされて、ファイル名を10文字にする関数を書いてみる。
元のスクリプトでは先頭10文字をとるだけだけど、これだとファイル名を被っちゃうかもしれない。
それは嫌なので、ファイル名が重複したら連番を振るようにした。例えば、["a123456789a","a123456789b","a123456789c"]は先頭10文字が同じなので、["a123456789","a123456789(1)","a123456789(2)"]のように番号を振って重複を回避する。

使い方

*Main> shorten ["a123456789a","a123456789b","a123456789c","z"]
["a123456789","a123456789(1)","a123456789(2)","z"]

ソースコード

import Test.HUnit.Base
import Test.HUnit.Text
import Data.List
import Text.Printf

count :: Eq a => a -> [a] -> Int
count x xs = length $ filter (==x) xs

nodup :: Eq a => (a->[a]->a) -> [a] -> [a]
nodup f xs = nodup' [] xs
    where nodup' _ [] = []
          nodup' prev (x:xs) = if x `elem` prev then
                                   (f x $ filter (==x) prev):nodup' (x:prev) xs
                               else
                                   x:nodup' (x:prev) xs

shorten :: [String] -> [String]
shorten xs = nodup (\x prev -> printf "%s(%d)" x (count x prev)) $ map (take 10) xs

test1 = ["foo","bar"]                     ~=? shorten ["foo","bar"]
test2 = ["a123456789","b123456789"]       ~=? shorten ["a123456789_______","b123456789_____"]
test3 = ["a123456789","a123456789(1)","a123456789(2)","z"] ~=? shorten ["a123456789a","a123456789b","a123456789c","z"]

main = runTestTT $ TestList [test1,test2,test3]