Skip to content

Reader

Reader: object

Defined in: Core/Reader.ts:26

apply: <R2, A>(arg) => <B, R1>(reader) => Reader<R1 & R2, B>

Applies a function wrapped in a Reader to a value wrapped in a Reader. Combines environment requirements via intersection.

R2

A

Reader<R2, A>

<B, R1>(reader) => Reader<R1 & R2, B>

chain to sequence dependent Reader computations.

const add = (a: number) => (b: number) => a + b;
pipe(
  Reader.make<Config, typeof add>(add),
  Reader.apply((c: Config) => c.timeout),
  Reader.apply(Reader.make(5))
)(appConfig);

ask: <R>() => Reader<R, R>

Returns the full environment as the result. The fundamental way to access the environment in a pipeline.

R

Reader<R, R>

make to lift a static value that ignores the environment.

pipe(
  Reader.ask<Config>(),
  Reader.map(config => config.baseUrl)
)(appConfig); // "https://api.example.com"

assign: <K, R2, A, B>(key, transform) => <R1>(reader) => Reader<R1 & R2, A & { [P in string]: B }>

Evaluates a new Reader using the current accumulator and attaches the output to a new key.

K extends string

R2

A

B

K

(value) => Reader<R2, B>

<R1>(reader) => Reader<R1 & R2, A & { [P in string]: B }>

assignTo to initialize the accumulator record.

pipe(
  Reader.make({ a: 1 }),
  Reader.assign("b", ({ a }) => Reader.make(a + 1))
); // Reader({ a: 1, b: 2 })

assignTo: <K>(key) => <R, A>(reader) => Reader<R, { [P in string]: A }>

Lifts a Reader value into an accumulator object.

K extends string

K

<R, A>(reader) => Reader<R, { [P in string]: A }>

assign to accumulate subsequent Reader values into the object.

pipe(Reader.make(42), Reader.assignTo("value")); // Reader({ value: 42 })

chain: <A, R2, B>(transform) => <R1>(reader) => Reader<R1 & R2, B> = chainReader

Sequences two Readers. Both see the environment. The output of the first is passed to transform, which returns the next Reader.

A

R2

B

(value) => Reader<R2, B>

<R1>(reader) => Reader<R1 & R2, B>

map to transform the value without returning a new Reader.

const buildUrl = (path: string): Reader<Config, string> =>
  c => `${c.baseUrl}${path}`;

const addAuth = (url: string): Reader<Config, string> =>
  c => `${url}?key=${c.apiKey}`;

pipe(
  buildUrl("/items"),
  Reader.chain(addAuth)
)(appConfig); // "https://api.example.com/items?key=secret"

local: <R2, R>(transform) => <A>(reader) => Reader<R2, A>

Adapts a Reader to work with a different (typically wider) environment by transforming the environment before passing it to the Reader. This lets you compose Readers that expect different environments.

R2

R

(env) => R

<A>(reader) => Reader<R2, A>

run to supply the final environment rather than transforming it.

type AppEnv = { db: DbPool; config: Config; logger: Logger };

// buildUrl only needs Config
const buildUrl: Reader<Config, string> = c => c.baseUrl;

// Zoom in from AppEnv to Config
const buildUrlFromApp: Reader<AppEnv, string> =
  pipe(buildUrl, Reader.local((env: AppEnv) => env.config));

buildUrlFromApp(appEnv); // works with the full AppEnv

make: <R, A>(value) => Reader<R, A>

Lifts a pure value into a Reader. The environment is ignored.

R = unknown

A = never

A

Reader<R, A>

ask to retrieve the environment instead of ignoring it.

const always42: Reader<Config, number> = Reader.make(42);
always42(anyConfig); // 42

map: <A, B>(transform) => <R>(reader) => Reader<R, B> = mapReader

Transforms the value produced by a Reader.

A

B

(value) => B

<R>(reader) => Reader<R, B>

chain to sequence a computation that also reads from the environment.

pipe(
  (c: Config) => c.baseUrl,
  Reader.map(url => url.toUpperCase())
)(appConfig); // "HTTPS://API.EXAMPLE.COM"

run: <R>(env) => <A>(reader) => A

Runs a Reader by supplying the environment. Use this at the edge of your program where the environment is available.

R

R

<A>(reader) => A

local to adapt the environment before execution.

pipe(
  buildEndpoint("/users"),
  Reader.run(appConfig)
); // "https://api.example.com/users?key=secret"

tap: <A>(sideEffect) => <R>(reader) => Reader<R, A>

Executes a side effect on the produced value without changing the Reader. Useful for logging or debugging inside a pipeline.

A

(value) => void

<R>(reader) => Reader<R, A>

map to transform the value instead of executing a side effect.

pipe(
  buildUrl("/users"),
  Reader.tap(url => console.log("Requesting:", url)),
  Reader.chain(addAuth)
)(appConfig);