Comment

Comment by NM-Super

This article is from 2017. In the meantime, the Haskell community has been playing around a lot with Effect Systems, which give you similar benefits with much better performance and generally less boilerplate. In particular, the effectful package (https://hackage.haskell.org/package/effectful) would let you write the code in the article as:

  reserve :: (SearchTrains :> es, GetTypology :> es, Log :> es, RequestReservation :> es) => ReservationRequest -> Eff es ReservationResult
  reserve request = do
    trains <- send (SearchTrain (_dateTime request)) -- Search for trains at date-time
    forM trains $ \train ->                   -- Loop on all the trains
      typology <- send (GetTypology train)           -- Get the typology of a train
      ...                                     -- Implement the reservation rules
      send (Log "Confirming reservation")          
      confirmed <- send (RequestReservation reservation)
      ...
(In actual usage you won't tend to use the send function - you'll write wrappers that do it for you).

This lets you avoid having to write an interpreter for some particular ReservationExpr monad - instead, you specify individual effect handlers, then use them as you want. For example, we could write something like this:

  -- Make search train never return any trains
  runWithoutTrains :: Eff (SearchTrains ': es) a -> Eff es a
  runWithoutTrains = interpret $ \_unusedHere (SearchTrain name) -> pure []

  ignoreLogs :: Eff (Log ': es) a -> Eff es a
  ignoreLogs = interpret $ \_unusedHere (Log _message) -> pure ()

What's even more fun is that you can actually interpose effects. So, I can write this:

  loggingTrainSearches :: (Log :> es, SearchTrain :> es) => Eff es a -> Eff es a
  loggingTrainSearches = interpose $ \_unusedHere (SearchTrain name) -> do
    send (Log ("Searching for train " <> show name))
    send (SearchTrain name)

Being able to play around with handlers like this is really useful, both for testing and for adding on niceties to business logic.
parent NM-Super 3 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton