packages feed

tower-hs 0.3.0.0 → 0.3.0.1

raw patch · 3 files changed

+26/−41 lines, 3 filesdep +transformers

Dependencies added: transformers

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Changelog +## 0.3.0.1 — 2026-04-08++- Refactor: derive `Functor`, `Profunctor`, `Category`, `Arrow`, and `ArrowChoice` for `Service` via `Kleisli (ExceptT ServiceError IO)`, to which `Service` is isomorphic. No behavioral or API changes — all instances match the prior hand-written semantics exactly (including `Left` short-circuit on `>>>`, `first`, and `left`).+- New transitive dependency: `transformers` (GHC boot library).+ ## 0.3.0.0 — 2026-04-07  - Add `Category` instance for `Service` — compose services sequentially with `>>>`, errors short-circuit automatically
src/Tower/Service.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DerivingVia #-}+ -- | -- Module      : Tower.Service -- Description : Core Service and Middleware abstractions@@ -9,7 +11,8 @@ -- -- 'Service' forms a 'Category' (sequential composition via '>>>') and an -- 'Arrow', so you can use arrow combinators and proc-notation to wire--- services together.+-- services together. All instances are derived via+-- @'Kleisli' ('ExceptT' 'ServiceError' 'IO')@, which 'Service' is isomorphic to. module Tower.Service   ( Service(..)   , Middleware@@ -19,19 +22,25 @@   , composeMiddleware   ) where -import Control.Arrow (Arrow(..), ArrowChoice(..))-import Control.Category (Category(..))+import Control.Arrow (Arrow, ArrowChoice, Kleisli(..))+import Control.Category (Category, (.))+import Control.Monad.Trans.Except (ExceptT(..)) import Data.Profunctor (Profunctor(..))+import GHC.IO (IO(..)) -- bring IO's newtype constructor into scope so DerivingVia can coerce through it import Prelude hiding (id, (.)) import Tower.Error (ServiceError)  -- | A service transforms a request into an effectful response. -- This is the fundamental building block — middleware wraps services. ----- 'Service' is a 'Functor' in its response type and a 'Profunctor' over--- both request and response types. Use 'fmap' to transform responses,--- 'lmap' to transform requests, or 'dimap' to transform both — useful for--- lifting a @Service Http.Request Http.Response@ into a+-- 'Service' is isomorphic to @'Kleisli' ('ExceptT' 'ServiceError' 'IO')@,+-- and all of its instances ('Functor', 'Profunctor', 'Category', 'Arrow',+-- 'ArrowChoice') are derived from that representation. Composition via+-- '>>>' short-circuits on the first 'Left'.+--+-- Use 'fmap' to transform responses, 'lmap' to transform requests, or+-- 'dimap' to transform both — useful for lifting a+-- @Service Http.Request Http.Response@ into a -- @Service MyBinding.SomeRequest MyBinding.SomeResponse@. -- -- @@@ -43,39 +52,9 @@   { runService :: req -> IO (Either ServiceError res)     -- ^ Execute the service with a request, returning either an error or a response.   }--instance Functor (Service req) where-  fmap f (Service run) = Service $ \req -> fmap (fmap f) (run req)--instance Profunctor Service where-  dimap f g (Service run) = Service $ \req -> fmap (fmap g) (run (f req))-  lmap f (Service run) = Service (run . f)-  rmap = fmap--instance Category Service where-  id = Service (pure . Right)-  (Service g) . (Service f) = Service $ \req -> do-    result <- f req-    case result of-      Left err -> pure (Left err)-      Right mid -> g mid--instance Arrow Service where-  arr f = Service (pure . Right . f)-  first (Service f) = Service $ \(a, c) -> do-    result <- f a-    case result of-      Left err -> pure (Left err)-      Right b -> pure (Right (b, c))--instance ArrowChoice Service where-  left (Service f) = Service $ \eac -> case eac of-    Left a -> do-      result <- f a-      case result of-        Left err -> pure (Left err)-        Right b -> pure (Right (Left b))-    Right c -> pure (Right (Right c))+  deriving (Functor) via (Kleisli (ExceptT ServiceError IO) req)+  deriving (Profunctor, Category, Arrow, ArrowChoice)+    via (Kleisli (ExceptT ServiceError IO))  -- | Middleware wraps a service to add behavior (retry, timeout, logging, etc.) --
tower-hs.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           tower-hs-version:        0.3.0.0+version:        0.3.0.1 synopsis:       Composable service middleware for Haskell, inspired by Rust's Tower description:    tower-hs provides a composable middleware abstraction for any service type.                 Build middleware stacks with retry, timeout, circuit breaker, and more — all with@@ -57,6 +57,7 @@     , stm ==2.5.*     , text >=2.0 && <2.2     , time >=1.11 && <1.15+    , transformers >=0.5 && <0.7   default-language: Haskell2010  test-suite tower-hs-test