How to calculate Reading Time in Haskell

by||2 min read

Many content writers and bloggers out there tend to indicate reading time on top of their content. It should give the reader the opportunity to decide upfront to read or not to read the article. As well, it motivates most of the audience to read articles which indicate less than 5 minutes.

As you probably noticed on top of this very article it is indicated less than 1 minutes, which means, this topic is easy to understand!

Basics of reading time

According to a study humans tend to read 238 words per minute. Often this number is reduced to 200 to simplify things. I won't, since I don't see any reason to do so.

To calculate the reading time we need to count words in a text. Luckily this already exists in form of the words function which operates on a given Text input. The given amount of words can be divided by 238. This will give us the according time in minutes to read the article.

       Formula: reading time in minutes = amount of words / 238

Implementing reading time in Haskell

The implementation is not as simple as in JavaScript or PHP but still very short. 

First, we need to take our formula and transform it into Haskell code:

calcMinutes :: Text -> Int
calcMinutes text = (ceiling $ (fromIntegral $ length $ words text) / 238.00)

Here we cast the amount of words (since length is an Int) into a decimal number to be able to run the division function. 

With the ceiling function we can get back to our end result, which is Int.
I have chosen ceiling in favor of floor since I want to cover as well those articles with lass than one reading minute. We end up being more generous, but still very close to the average reading speed.

Finally we can use the human-readable-duration package to display our reading time:

import qualified Data.Duration as D
import qualified Data.Text as T

readingTime :: Text -> Text
readingTime input = (T.pack $ D.humanReadableDuration (readingTimeMinutes input)) <> " read"

readingTimeMinutes :: Text -> D.Seconds
readingTimeMinutes input = (D.minute * calc input)

calc :: Real a => Text -> a
calc input = fromIntegral $ calcMinutes input

Thank you for reading this far! Let’s connect. You can @ me on Twitter (@debilofant) with comments, or feel free to follow. Please like/share this article so that it reaches others as well.

© Copyright 2022 - Ersocon - All rights reservedVer. 2.3.5.2