HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Count frequency of characters in a file

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
frequencycountcharactersfile

Problem

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 -> IO (M.Map Char Int)
fromFile = fmap (M.fromListWith (+)) . fmap (`zip` [1,1..]) . readFile
    where readFile = fmap BS.unpack . BS.readFile

Solution

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 => [k] -> Map k Int
frequencies = fromListWith (+) . (`zip` [1,1..])

fromFile :: FilePath -> 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

Code Snippets

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

fromFile :: FilePath -> IO (Map Char Int)
fromFile = fmap frequencies . fmap unpack . readFile
frequencies ks = fromListWith (+) $ zip ks (repeat 1)

fromFile = fmap (frequencies . unpack) . readFile

Context

StackExchange Code Review Q#61571, answer score: 4

Revisions (0)

No revisions yet.