External Publication
Visit Post

Http-tower-hs — A Rust Tower-inspired middleware library for Haskell

Haskell Community [Unofficial] April 7, 2026
Source

Here’s some rewrites of your example from OP, edited:

import Data.Functor ((<&>)) -- (<&>) = flip (<$>), like how (&) = flip ($)

client <- newClient
      <&> withBearerAuth "my-token"
      . withRequestId
      . withRetry (exponentialBackoff 3 0.5 2.0)
      . withTimeout 5000
      . withCircuitBreaker config breaker
      . withValidateStatus (\c -> c >= 200 && c < 300)
      . withTracing



import Data.Function ((&))

client <- newClient
let configured = client
      & withBearerAuth "my-token"
      & withRequestId
      & withRetry (exponentialBackoff 3 0.5 2.0)
      & withTimeout 5000
      & withCircuitBreaker config breaker
      & withValidateStatus (\c -> c >= 200 && c < 300)
      & withTracing

By the way, it might also be useful to give your Service type a Functor instance (can be derived automatically) and a Profunctor instance. If someone was writing a binding to a remote HTTP API, it’d provide a good way to lift a Service Http.Request Http.Response into a Service MyBinding.SomeRequest MyBinding.SomeResponse.

Discussion in the ATmosphere

Loading comments...