
Daniel Fischer
First of all: I'm not sure if this question is allowed here. If not, I apologize
You might want to check out the haskell-beginners list, but IMO most questions are okay to post here. Just a couple of style issues Daniel didn't mention:
process :: [Char] -> [String] process str = words (map toLower (removePunctuation str))
It's a matter of taste, but I think this reads clearer if written: process = words . map toLower . removePunctuation
unique :: (Eq a) => [a] -> [a] unique [] = [] unique (x:xs) = [x] ++ unique (filter (\s -> x /= s) xs)
Also 'filter (\s -> x /= s)' can be written as filter (x /=)
import qualified Data.Map as Map import Data.List
occurrenceCount'' :: Ord a => [a] -> [(a,Int)] occurrenceCount'' xs = Map.toList $ foldl' (\mp x -> Map.insertWith' (+) x 1 mp) Map.empty xs
Note the primes here! This is perhaps my most common use of Map, and because of laziness, it is very easy to blow the stack. Although you really want to store an Int for each key, the default is to store an unevaluated computation, in this case a tower of (1+(1+(1+..))). The foldl' and insertWith' functions are stricter, and presumably Daniel gets this right (I'm never comfortable without testing this myself :).
3) The whole process as i'm doing it now feels pretty imperatively (been working for years as a Java / PHP programmer). I've got this feeling that the occurenceCount' function could be implemented using a mapping function. What ways are there to make this more "functional"?
I don't think I agree with this sentiment - you're building a pipeline of functions, not setting variables or otherwise mixing state or other imperativeness. Why do you think it's imperative? -k -- If I haven't seen further, it is by standing in the footprints of giants