patternModerate
My Haskell word count program
Viewed 0 times
countwordprogramhaskell
Problem
Here's my first significant Haskell program - it presents a count of each word seen on stdin. Any comments are welcome.
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 (
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) . wordsSome 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 is Map a Integer -> Integer, and so I'll get a type error if I change the definition of emptyMap to empty :: Map String Int. Ideally I'd like to make the choice between Int and Integer in one place for all three definitions.Solution
Your usage of
If you give all of the functions explicit type declarations, so that the Monomorphism Restriction doesn't apply, you can use generic integral types:
Some quick style-related things you could change:
First:
... is the same as
Second:
You don't need parens around many of your function calls; if you have something like
Third:
You use very long indentations. A tip is to insert newlines after
Data.Map is sound. I see nothing that could be improved as long as you stay with Data.Map.If you give all of the functions explicit type declarations, so that the Monomorphism Restriction doesn't apply, you can use generic integral types:
mapTotal :: Integral i => Map a i -> iSome quick style-related things you could change:
First:
(\x -> case x of
Nothing -> Just 1
Just n -> Just (n+1))... is the same as
Just . maybe 1 (+1)Second:
You don't need parens around many of your function calls; if you have something like
a +.- (foo bar baz) ¤: b, it means the same thing as a +.- foo bar baz ¤: b because every operator has lower precedence than function application.Third:
You use very long indentations. A tip is to insert newlines after
= and before control structures like case to make the code more compact. I find this style to be quite good.Code Snippets
mapTotal :: Integral i => Map a i -> i(\x -> case x of
Nothing -> Just 1
Just n -> Just (n+1))Just . maybe 1 (+1)Context
StackExchange Code Review Q#8904, answer score: 12
Revisions (0)
No revisions yet.