Here's my first significant Haskell program - it presents a count of each word seen on stdin. Any comments are welcome.
import Data.Map
emptyMap = empty :: Map String Integer
countWord m s = alter (\x -> case x of
Nothing -> Just 1
Just n -> Just (n+1)) s m
mapPairs m = concat [ k ++ ": " ++ (show v) ++ "\n" | (k,v) <- toList m ]
mapTotal = sum . elems
mapOutput m = (mapPairs m) ++ "Total words: " ++ (show (mapTotal m)) ++ "\n"
wc = interact $ mapOutput . (foldl countWord emptyMap) . words
Some of the questions I have are:
Am I using Map efficiently here? (I realize there are other solutions which do not use a Map - the main point of this exercise was to learn how to use Data.Map.)
How can I make sure that emptyMap, countWord and mapTotal all use the same integral type (
Int
vs.Integer
)? For instance, the type of mapTotal isMap a Integer -> Integer
, and so I'll get a type error if I change the definition of emptyMap toempty :: Map String Int
. Ideally I'd like to make the choice betweenInt
andInteger
in one place for all three definitions.
fromListWith
; you can replacefoldl countWord emptyMap
with something likefromListWith (+) . flip zip (repeat 1)
and skip definingcountWord
at all. – Daniel Wagner Feb 12 '12 at 4:26