Skip to content
LogoLogo

Function Channels

Reference for values, errors, and requirements

Every VibeLang function is analyzed across three conceptual channels, but all runtime values use ordinary types:

ParameterMeaningRuntime representation
Asuccess valuethe success variant of Result<A, E>
Eexpected errorsthe error variant of Result<A, E>
Rrequired capabilitiescompiler-tracked context, provided by Layers

For an infallible function, the return type remains A. For a fallible function it is Result<A, E>; for a fallible async function it is Promise<Result<A, E>>.

Example

function getUser(
  id: string,
): Result<User, DatabaseError | NotFound> {
  const db = Database.context()
  const log = Logger.context()
  const row = db.find(id).unwrap()
  if (row === null) throw new NotFound(id)
  log.info(`user:${id}`)
  return User.from(row)
}

The compiler sees:

A = User
E = DatabaseError | NotFound
R = Database | Logger

Composition

OperationEffect on EEffect on R
return a Resultunion returned errorsunion called requirements
.unwrap()propagate the Result errorunchanged
Result.match / recoverremove or transform handled errorsunchanged
throw ErrorSubclassadd that Error typeunchanged
Layer.provideinclude layer initialization errorsremove provided capabilities; add layer requirements
awaitunwrap Promise only; leave Resultunchanged

Duplicate Error members collapse in unions.

Public Signatures

export declare function boundary(): Result<A, E>
export declare function asyncBoundary(): Promise<Result<A, E>>

These are ordinary generic return types, not failure annotations. Context requirements are inferred from Capability.context() and retained in VibeLang analysis metadata. The declaration-file representation for R remains compiler-owned.

Inference and Lifting

An unannotated implementation may infer both A and E from its body. Once a function is fallible, plain returns and throws are lowered into Result variants. Returning an existing compatible Result does not produce Result<Result<A, E>, E>.

No marker opts a function into inference. Public API authors should spell Result<A, E> explicitly for stability.

TypeScript Boundaries

An imported TypeScript function that might throw is adapted to a Result at its declared VibeLang boundary. Unknown exceptions become UnhandledException until an adapter maps them to a domain Error. Runtime TypeScript use also adds the built-in TypeScript requirement; type-only imports do not.

Async Boundary

VibeLang does not add an error generic to Promise. It wraps an ordinary Result:

Promise<Result<A, E>>

Authored VibeLang uses only await for Promise consumption. The compiler rejects .then, .catch, and .finally calls.