# Revision history for monad-rail ## 0.1.0.0 -- 2026-03-18 * First release. * `RailT` monad transformer for Railway-Oriented Programming. * `Rail` type alias for `RailT Failure IO`. * `throwError` for single-error failures. Accepts any error type with `HasErrorInfo`, `Show`, and `Typeable` constraints — wraps it in `SomeError` automatically. * `` operator for parallel validation with error accumulation. * `HasErrorInfo` typeclass for custom error types. Only `errorPublicMessage :: e -> Text` is required. All other methods have defaults: * `errorCode :: e -> Text` — defaults to the constructor name via `Data.toConstr` (requires `Data`). * `errorDetails :: e -> Maybe SomeErrorDetails` — defaults to `Nothing`. Uses the existential `SomeErrorDetails` wrapper (see below). * `errorSeverity :: e -> ErrorSeverity` — defaults to `Error`. * `errorInternalMessage`, `errorException`, `errorCallStack` — all default to `Nothing`. * `publicErrorInfo :: HasErrorInfo e => e -> PublicErrorInfo` — assembles the user-facing error record from an instance. * `internalErrorInfo :: HasErrorInfo e => e -> InternalErrorInfo` — assembles the internal diagnostic record from an instance. * `SomeErrorDetails` existential wrapper — holds any value with `ToJSON`, `Show`, and `Typeable` constraints. Preserves the original type at runtime, allowing recovery via `Data.Typeable.cast` while supporting JSON serialization. Used by `errorDetails` and `PublicErrorInfo.details`. * `PublicErrorInfo` with fields `publicMessage`, `code`, and `details` (where `details :: Maybe SomeErrorDetails`). Serializes to JSON as `message`, `code`, and `details`. Null fields are omitted from JSON output. * `InternalErrorInfo` with fields `internalMessage`, `severity`, `exception`, and `callStack`. Implements `ToJSON` for structured log output; null fields are omitted. Never included in public API responses. * `SomeError` existential wrapper — holds any error with `HasErrorInfo`, `Show`, and `Typeable` constraints. The `Typeable` constraint allows recovery of the original error type via `Data.Typeable.cast`. * `ErrorSeverity` with `Error` and `Critical` levels. * `UnhandledException` data type for wrapping runtime exceptions as Railway errors, with fields `unhandledCode`, `unhandledException`, `unhandledCallStack`, and `unhandledMessage`. `unhandledCode` is `Maybe Text` and defaults to `"UnhandledException"` when `Nothing`. * `tryRail` (with `HasCallStack`) for lifting IO actions that may throw into the Railway, converting any exception to an `UnhandledException` error with `Critical` severity and an automatic call stack. * `tryRailWithCode` (with `HasCallStack`) — like `tryRail` but accepts a function `SomeException -> Text` as the first argument, allowing the error code to be derived from the caught exception. Pass `const "MyCode"` for a fixed code, or inspect the exception to return different codes dynamically. * `tryRailWithError` (with `HasCallStack`, `HasErrorInfo e`) — like `tryRailWithCode`, but takes an error-building function `SomeException -> e` and uses `errorCode` and `errorPublicMessage` from the resulting `HasErrorInfo` instance as the error code and public message. * `throwUnhandledException` (with `HasCallStack`) — convenience function for throwing an `UnhandledException` with the default code `"UnhandledException"`. Captures the call stack automatically at the call site. * `throwUnhandledExceptionWithCode` (with `HasCallStack`) — like `throwUnhandledException` but accepts a domain-specific error code as the first argument. * `runRailT` — the general form of `runRail` for custom base monads. Use when `RailT` is stacked on top of `StateT`, `ReaderT`, or any other transformer.