[Haskell-beginners] Re: Counting Fruits
Heinrich Apfelmus
apfelmus at quantentunnel.de
Fri Feb 20 05:15:03 EST 2009
Adolfo Builes wrote:
>
> I wanted to do a small program which read a txt with fruit's name in each
> line and then print how many fruits I have of each type. something like
> these:
> apple
> apple
>
> and then
>
> [(apple,2)]
>
> I came up with this
>
> import qualified Data.Map as Map
> import Data.List
> import System.IO
>
> main =
> do
> file <- readFile "fruits.txt"
> let answer = proccessFile $ lines file
>
> putStrLn (show answer)
>
> proccessFile :: [String] -> [(String,Int)]
> proccessFile file = Map.toAscList $ parseFile Map.empty file
> where parseFile fruits [] = fruits
> parseFile fruits_map (x:xs) = parseFile (Map.insertWith (+)
> x 1 fruits_map) xs
>
>
> It works, but I would like to know how would you do it ?, Share different
> points of view, different code. Was it a good idea to use a Map ?, Did I
> separate the code in a proper way, I mean pure - impure ? How can we
> improve the performance ?
Looks good to me. :)
Here's how I would write it
main = print . process . lines =<< readFile "fruits.txt"
process :: [String] -> [(String,Int)]
process = Map.toAscList . foldl f Map.empty
where f map x = Map.insertWith (+) x 1 map
So, the parseFile function is best expressed as a left fold and
function composition is good style.
The above works fine for smaller files. If you have larger amounts of
data, you will need a few strictness annotations or there will be a
space leak. In this case, this means using the functions
foldl' and Map.insertWith'
instead of
foldl and Map.insertWith
But I wouldn't bother about that for now.
Regards,
apfelmus
--
http://apfelmus.nfshost.com
More information about the Beginners
mailing list