WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Haskell · Advanced · question 58 of 100

Describe a situation where you would use the ’Reader’ monad in Haskell.?

📕 Buy this interview preparation book: 100 Haskell questions & answers — PDF + EPUB for $5

The ‘Reader‘ monad in Haskell is particularly useful when you have a set of functions that require access to a read-only configuration or environment. Instead of passing the environment explicitly as an argument to each function, you can use the ‘Reader‘ monad to implicitly manage this environment.

Let’s consider a simple example. Suppose we are developing an application that processes and analyzes data from various sensors of an IoT device. The application needs to have access to a configuration, such as calibration settings, sampling rates, or gain factors that depend on the unique properties of each IoT device.

First, let’s define our environment and some dummy data:

data Environment = Environment
    { gainFactor    :: Double
    , samplingRate  :: Double
    , calibrationOffset :: Double
    }

env :: Environment
env = Environment
    { gainFactor    = 2.0
    , samplingRate  = 100.0
    , calibrationOffset = 0.1
    }

sensorsData :: [Double]
sensorsData = [1.0, 2.0, 3.0, 4.0, 5.0]

Now we will define three functions that perform some operations on the raw sensor data, utilizing the read-only ‘Environment‘:

1. ‘applyGainFactor‘: Apply the gain factor to the raw data.

2. ‘resample‘: Perform a resampling operation on the data.

3. ‘calibrate‘: Apply a calibration offset to the data.

Instead of explicitly passing the ‘Environment‘ to each function, we can use the ‘Reader‘ monad. First, we need to import the necessary libraries and define a type alias for the ‘Reader‘:

import Control.Monad.Reader

type SensorReader a = Reader Environment a

Now let’s define our functions using the ‘Reader‘ monad:

applyGainFactor :: Double -> SensorReader Double
applyGainFactor rawData = do
    gf <- asks gainFactor
    return (rawData * gf)

resample :: Double -> SensorReader Double
resample rawData = do
    sr <- asks samplingRate
    return (rawData * sr / 100.0)

calibrate :: Double -> SensorReader Double
calibrate rawData = do
    co <- asks calibrationOffset
    return (rawData - co)

We can compose these functions using the ‘Reader‘ monad, which will enable us to process the sensor data:

processSensorData :: Double -> SensorReader Double
processSensorData rawData = do
    gfApplied <- applyGainFactor rawData
    resampled <- resample gfApplied
    calibrated <- calibrate resampled
    return calibrated

Finally, we can use the ‘runReader‘ function to execute our ‘Reader‘ monad with a particular environment and process our sensor data:

processedData :: [Double]
processedData = map (rawData -> runReader (processSensorData rawData) env) sensorsData

So, in this scenario where the application requires access to a read-only configuration, the ‘Reader‘ monad allows us to implicitly pass the ‘Environment‘ to our functions, thus simplifying our code and improving readability.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Haskell interview — then scores it.
📞 Practice Haskell — free 15 min
📕 Buy this interview preparation book: 100 Haskell questions & answers — PDF + EPUB for $5

All 100 Haskell questions · All topics