Polysemy: Onion architecture

Until now we only seen "low-level" effects (either classical Monad, or technical effects).

On of my main motivation with effects systems is to be used in an Onion architecture.

Doing so, we can imagine to modelise a car return within a car rental business.

For example, last year we introduced a Cache effect:

returnCar :: Members '[Bookings, Cars, DamageReferences] r => BookingRef -> [CarObservations] -> Sem r Bill
returnCar ref observations = do
  booking <- fetchBooking ref
  car <- fetchCar booking.carRef
  let newDamages = inducedDamages car observations
  registerReturnedCar car.ref newDamages
  pricedDamages <- mapM (fetchPricedDamage car.model) newDamages
  return $ createBill booking car pricedDamages

with the following effects for Repositories:

data Bookings (m :: Type -> Type) a where
  FetchBooking :: BookingRef -> Bookings m Booking

makeSem ''Bookings

data Cars (m :: Type -> Type) a where
  FetchCar :: CarRef -> Cars m Car
  RegisterReturnedCar :: CarRef -> [CarDamage] -> Cars m ()

makeSem ''Cars

data DamageReferences (m :: Type -> Type) a where
  FetchPricedDamage :: () -> CarDamage -> DamageReferences m CarPricedDamage

makeSem ''DamageReferences

See the full the code here.