npm package: @nand.computer/monads
Description: TypeScript monad utilities for functional programming
Author: Yazalde Filimone
Latest version: 1.0.0

A minimal functional utility library for TypeScript, inspired by Rust's `Result` and `Option`. It provides safe, composable handling of errors and optional values.

- [`Result<T>`](#result) – represents a computation that may succeed (`ok`) or fail (`err`).
- [`Option<T>` / `Maybe<T>`](#option) – represents a value that may exist (`Some`) or be absent (`None`).
- [`SafePromise<T>`](#safepromise) – wraps async computations, converting exceptions into `Result<T>`.
- Supports chainable operations: `map`, `andThen`, `filter`, `zip`, `transpose`, `mapErr`, `or`, `orElse`, `unwrap`, `expect`, `inspect`.

Goals:

1. Explore functional programming in TypeScript.
2. Provide a small, dependency-free, composable monads toolkit.
3. Enable safe handling of errors and optional values without exceptions.

> Status: eperimental. API may change. contributions welcome.

### Installation

```sh
bun add @nand.computer/monads
```

```ts
import { ok, err, Some, None, wrap, todo } from "@nand.computer/monads";
```

### Result

`Result<T>` is either:

- `ok(value: T)` – success
- `err(message: string)` – failure

### Methods

- `.map(fn)` – transform success value
- `.andThen(fn)` – chain computations
- `.mapErr(fn)` – transform the error
- `.filter(predicate, errMsg)` – fail if predicate is false
- `.zip(otherResult)` – combine two results
- `.transpose()` – convert `Result<Option<T>>` → `Option<Result<T>>`
- `.unwrap()` – return value or throw
- `.expect(msg)` – return value or throw with custom message
- `.ok()` – returns the value or `null`
- `.err()` – returns the error message or `null`

## Option / Maybe

`Option<T>` represents an optional value:

- `Some(value)` – value exists
- `None()` – value absent

### Methods

- `.map(fn)` – transform value
- `.andThen(fn)` – chain computations
- `.unwrap()` – return value or throw
- `.expect(msg)` – return value or throw with message
- `.filter(predicate)` – convert to `None` if predicate fails

## SafePromise

Wraps async functions to automatically return `Result<T>`:

```ts
const safe = await wrap(async () => 10 * 2);
console.log(safe.ok()); // 20
```

## Examples

```ts
// Basic map/andThen/mapErr
const r1 = ok(10)
  .map((x) => x * 2)
  .andThen((x) => (x > 15 ? ok(x) : err<number>("Too small")))
  .mapErr((e) => `Error happened: ${e}`);
console.log(r1.ok(), r1.err()); // 20, null

// Filter
const filtered = ok(100).filter((x) => x > 50, "Less than 50");
console.log(filtered.ok(), filtered.err()); // 100, null

// Zip
const zipped = ok(10).zip(ok("hello"));
console.log(zipped.ok()); // [10, "hello"]

// Option + transpose
const rOpt: Result<Option<number>> = ok(Some(5));
const transposed = rOpt.transpose();
console.log(transposed.isSome ? transposed.value!.ok() : null); // 5

const rOptNone: Result<Option<number>> = ok(None());
const transposedNone = rOptNone.transpose();
console.log(transposedNone.isNone); // true

// SafePromise / wrap
const asyncFunc = async (x: number) =>
  x > 0
    ? x * 2
    : (() => {
        throw new Error("Negative");
      })();
const safe = await wrap(() => asyncFunc(5));
console.log(safe.ok()); // 10
const safeErr = await wrap(() => asyncFunc(-1));
console.log(safeErr.err()); // "Unexpected error"

// Complex chaining
const complex = await wrap(async () => 20).then((r) =>
  r
    .filter((x) => x > 10, "Too small")
    .andThen((x) => ok(x * 3))
    .zip(ok(50))
    .map(([a, b]) => a + b),
);
console.log(complex.ok()); // 110
```

## Goals

1. Learn, experiment, and have fun with functional patterns.
2. Provide a safe, composable substrate for async and optional computations.
3. Maintain simplicity and extensibility.