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 54 of 100

How do you handle real-time data streams in Haskell? Are there specific libraries you would use for this?

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

Handling real-time data streams in Haskell can be achieved using various libraries and techniques. Some popular libraries include Conduit, Pipes, and streaming. However, one of the most powerful and flexible libraries for this purpose is ‘pipes‘.

‘pipes‘ is a library that enables composability and resource management for streaming computations. It is built around the concept of Producers, Consumers, and Pipes, which can be combined to create complex streaming data pipelines.

Let’s briefly discuss the main components of the ‘pipes‘ library:

1. *Producers*: A Producer is a stream generator that produces values of a specific type. You can think of it as an iterator or a source of a streaming computation.

2. *Consumers*: A Consumer is a stream consumer that processes values of a specific type. You can think of it as a sink or a target of a streaming computation.

3. *Pipes*: A Pipe is a stream transformer that consumes values of one type and produces values of another type. You can think of it as a function that transforms one stream of data into another.

4. *Composability*: Producers, Consumers, and Pipes can be composed to form larger streaming computations using the ‘(>->)‘ operator for connecting pipes and the ‘(&)‘ operator for connecting a producer to a consumer.

Let’s see a simple example, using ‘pipes‘, of an integer stream and a consumer that calculates the sum of the received integers:

import Pipes
import qualified Pipes.Prelude as P

integerStream :: Monad m => Producer Int m ()
integerStream = mapM_ yield [1..10]

sumIntegers :: Monad m => Consumer Int m Int
sumIntegers = P.sum

Now, let’s connect the ‘integerStream‘ to the ‘sumIntegers‘ consumer using the ‘(&)‘ operator and run the pipeline:

import Control.Monad.IO.Class (liftIO)

main = do
  sum <- runEffect $ integerStream & sumIntegers
  putStrLn $ "The sum is: " ++ show sum

In this example, ‘integerStream‘ is a ‘Producer‘ that generates integers from 1 to 10. ‘sumIntegers‘ is a ‘Consumer‘ that consumes integers and calculates their sum. Finally, we connect the producer and the consumer using the ‘(&)‘ operator, and run the resulting Effect action.

Another powerful feature of the ‘pipes‘ library is its support for bidirectional streaming using the concept of Proxy. A Proxy is a generalization that can act as a Producer, a Consumer, a Pipe, or a combination of these.

Let’s see an example of an interactive ‘Proxy‘ that calculates the sum of integers it receives and asks the user for each integer:

import Pipes
import qualified Pipes.Prelude as P
import Control.Monad.IO.Class (liftIO)

-- Producer that asks the user for integer input
askUser :: (MonadIO m) => Producer Int m ()
askUser = forever $ do
  liftIO $ putStrLn "Enter an integer:"
  n <- read <$> liftIO getLine
  yield n

-- A simple Proxy that calculates the sum and shows it continuously.
interactiveSum :: (MonadIO m) => Proxy () Int () Int m r
interactiveSum = go 0 where
  go acc = do
    n <- await
    let newAcc = acc + n
    liftIO $ putStrLn $ "Current sum: " ++ show newAcc
    yield newAcc
    go newAcc

To use this interactive sum Proxy, we can run the following pipeline:

main :: IO ()
main = runEffect $ askUser >-> interactiveSum >-> P.drain

Here, ‘askUser‘ is a producer that continuously asks the user for input integers, and ‘interactiveSum‘ is a bidirectional ‘Proxy‘ that calculates the sum of integers it receives and prints it. ‘P.drain‘ is a consumer that does nothing with its input and discards it, effectively stopping the pipeline when ‘interactiveSum‘ yields a value.

In summary, handling real-time data streams in Haskell can be efficiently done using the ‘pipes‘ library, which provides powerful abstractions and composability for creating complex streaming pipelines. Other libraries, such as Conduit, provide similar functionality and can also be used for this purpose.

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