Count frequency of characters in a file Some patterns are emerging ("fmap (b->a) . fmap (c->b) . .. . (IO z)"). Also infix zip is kind-of a hack.

What is:


Best practice in point-free style?
Best practice?


Elegance > Performance;  Functional > Imperative

import qualified Data.Map.Lazy as M
import qualified Data.ByteString.Char8 as BS

fromFile :: FilePath -&gt; IO (M.Map Char Int)
fromFile = fmap (M.fromListWith (+)) . fmap (`zip` [1,1..]) . readFile
    where readFile = fmap BS.unpack . BS.readFile
Best practice would be to separate the pure operations of your program from those that actually require IO. Counting the frequency of elements in a list doesn't require any IO, so you should tease that fromFile function apart into its constituent components for reusability, testing, comprehensibility, or whatever other purpose you'd like.

frequencies :: Ord k =&gt; [k] -&gt; Map k Int
frequencies = fromListWith (+) . (`zip` [1,1..])

fromFile :: FilePath -&gt; IO (Map Char Int)
fromFile = fmap frequencies . fmap unpack . readFile


I'd tweak this just a bit further, using repeat from the Prelude to build the infinite list instead of abusing list ranges, and to take advantage of the Functor laws and drop a few characters. I flip back and forth on writing functions in pointfree style when it requires infix sectioning too, in this case I'd probably keep the points but I don't know that one choice is clearly better than the other.

frequencies ks = fromListWith (+) $ zip ks (repeat 1)

fromFile = fmap (frequencies . unpack) . readFile