The code below finds the index of the lowest unique integer on each line of the file. The numbering starts at 1, and when there's no unique value, the 0 should be output.The sample input looks like this:3 3 9 1 6 5 8 1 5 39 2 9 9 1 8 8 8 2 1 1And the sample output is this:50I wonder if this code can be simplified or made more elegant and idiomatic in any way. It's also interesting to me, could I get by w/o the IntMap and solve the problem with i.e. lists beautifully.module Main whereimport Prelude hiding (filter)import Control.Applicative ((<$>))import Data.IntMap (IntMap, alter, empty, filter, findMin, fromList, size)import System.Environmentcounts :: [(Int, Int)] -> IntMap [Int]counts = foldl f empty  where f m (i,v) = alter f' v m          where f' :: Maybe [Int] -> Maybe [Int]                f' (Just is) = Just (i:is)                f' (Nothing) = Just [i]g :: IntMap [Int] -> Intg a = i  where rs = filter ((== 1) . length) a        h m | size m == 0 = fromList [(0, [0])]            | otherwise = m        (_, [i]) = findMin $ h rsminUnique :: [Int] -> IntminUnique l = g r  where r = counts (zip [1..] l)main =  head <$> getArgs >>= readFile >>=    putStrLn . unlines . map (show . minUnique . map read . words) . lines
Find index of lowest unique integer in each line of the file
haskell
First off, your usage of alter can easily be replaced by insertWith:counts :: [(Int, Int)] -> IntMap [Int]counts = foldr f empty  where f (i,v) = insertWith (const (i:)) v [i]You could also use fromListWith, which is neater but less efficient due to the need to concatenate lists:counts :: [(Int, Int)] -> IntMap [Int]counts = fromListWith (flip (++)) . map (\(i,v) -> (v,[i]))Second, you could shorten g quite a bit as well using a view:g a = case minView $ filter ((== 1) . length) a of        Nothing      -> 0        Just ([i],_) -> iWhich is also probably slightly less efficient, as it will construct at least a thunk for the rest of the IntMap.Concerning different approaches - you could make a recursive function that removes all duplicates:import Data.Listimport Data.Orddedup :: [(Int,Int)] -> [(Int,Int)]dedup [] = []dedup ((i,v):ps)  | null dups = (i,v):dedup ps  | otherwise = dedup ndups  where (dups, ndups) = partition ((==v) . snd) psminUnique :: [Int] -> IntminUnique l  | null ddups = 0  | otherwise  = fst $ minimumBy (comparing snd) $ ddups  where ddups = dedup $ zip [1..] lOnce more this trades for a bit of efficiency, as the traversal in partition makes it O(n). Not sure whether that can be helped though without involving more complex data structures.