fp-lib/README.md
2025-06-07 20:52:15 -05:00

183 lines
6.0 KiB
Markdown

# Functional Programming Library Documentation
## Table of Contents
1. [Overview](#overview)
2. [Either Module](#either-module)
3. [List Module](#list-module)
4. [Option Module](#option-module)
5. [Utility Module](#utility-module)
6. [Bun Extensions](#bun-extensions)
## Overview <a name="overview"></a>
This zero-dependency functional programming library provides type-safe implementations of common FP constructs optimized for Bun runtime. Core features include:
- `Either` for error handling
- `Option` for nullable values
- Immutable linked `List`
- Do-notation for monadic composition
- Bun-specific file and environment utilities
## Either Module <a name="either-module"></a>
Represents computations that can succeed (`Right`) or fail (`Left`).
### Types
```typescript
type Left<E> = { readonly _tag: 'Left'; readonly left: E }
type Right<A> = { readonly _tag: 'Right'; readonly right: A }
type Either<A, E> = Left<E> | Right<A>
```
### Constructors
| Function | Description | Example |
|----------|-------------|---------|
| `left<E>(e: E)` | Creates failure case | `left('error')` |
| `right<A>(a: A)` | Creates success case | `right(42)` |
### Operations
| Function | Description | Type Signature |
|----------|-------------|----------------|
| `eitherMap` | Maps over success value | `<A, B, E>(f: (a: A) => B) => (fa: Either<A, E>) => Either<B, E>` |
| `eitherChain` | Chains Either-returning functions | `<A, B, E>(f: (a: A) => Either<B, E>) => (fa: Either<A, E>) => Either<B, E>` |
| `fold` | Handles both cases | `<A, E, B>(onLeft: (e: E) => B, onRight: (a: A) => B) => (fa: Either<A, E>) => B` |
### Do Notation
```typescript
const result = DoEither.start<{ x: number }, string>()
.bind('x', right(5))
.bind('y', right(10))
.return(scope => scope.x + scope.y)
// Returns Either<number, string>
```
| Method | Description |
|--------|-------------|
| `bind(key, either)` | Binds named value from Either |
| `return(f)` | Transforms final scope |
| `do(either)` | Executes effect without binding |
| `doL(f)` | Executes scope-dependent effect |
## List Module <a name="list-module"></a>
Immutable linked list implementation.
### Types
```typescript
type Nil = { readonly _tag: 'Nil' }
type Cons<A> = {
readonly _tag: 'Cons'
readonly head: A
readonly tail: List<A>
}
type List<A> = Nil | Cons<A>
```
### Constructors
| Function | Description | Example |
|----------|-------------|---------|
| `nil` | Empty list | `nil` |
| `cons` | Creates list node | `cons(1, cons(2, nil))` |
| `fromArray` | Converts array to list | `fromArray([1, 2, 3])` |
### Operations
| Function | Description | Type Signature |
|----------|-------------|----------------|
| `listMap` | Transforms list elements | `<A, B>(f: (a: A) => B) => (fa: List<A>) => List<B>` |
| `listReduce` | Reduces list to value | `<A, B>(f: (b: B, a: A) => B, initial: B) => (fa: List<A>) => B` |
| `toArray` | Converts list to array | `<A>(fa: List<A>) => Array<A>` |
## Option Module <a name="option-module"></a>
Represents optional values (`Some` or `None`).
### Types
```typescript
type None = { readonly _tag: 'None' }
type Some<A> = { readonly _tag: 'Some'; readonly value: A }
type Option<A> = None | Some<A>
```
### Constructors
| Function | Description | Example |
|----------|-------------|---------|
| `none` | Empty value | `none` |
| `some` | Wraps a value | `some(42)` |
| `fromNullable` | Converts nullable | `fromNullable(null) → none` |
### Operations
| Function | Description | Type Signature |
|----------|-------------|----------------|
| `map` | Transforms value | `<A, B>(f: (a: A) => B) => (fa: Option<A>) => Option<B>` |
| `chain` | Chains computations | `<A, B>(f: (a: A) => Option<B>) => (fa: Option<A>) => Option<B>` |
| `getOrElse` | Default value | `<A>(defaultValue: A) => (fa: Option<A>) => A` |
### Do Notation (Sync)
```typescript
DoOption.start()
.bind('user', getUser())
.bind('profile', getProfile())
.return(scope => `${scope.user.name}: ${scope.profile.bio}`)
```
### Async Do Notation
```typescript
AsyncDoOption.start()
.bind('user', fetchUser())
.bindL('posts', scope => fetchPosts(scope.user.id))
.return(scope => renderPage(scope))
```
| Async Method | Description |
|--------------|-------------|
| `bind(key, promise)` | Binds async Option |
| `bindL(key, f)` | Binds scope-dependent async Option |
| `do(promise)` | Executes async effect |
| `doL(f)` | Executes scope-dependent async effect |
## Utility Module <a name="utility-module"></a>
### Function Composition
| Function | Description | Example |
|----------|-------------|---------|
| `pipe` | Left-to-right composition | `pipe(1, x => x+1, x => x*2) → 4` |
| `compose` | Right-to-left composition | `compose(x => x*2, x => x+1)(1) → 4` |
### Error Handling
| Function | Description | Example |
|----------|-------------|---------|
| `tryCatch` | Safely execute function | `tryCatch(() => JSON.parse(str))` |
### Type Utilities
| Function | Description |
|----------|-------------|
| `hasTag` | Creates tag predicate | `list.filter(hasTag('Cons'))` |
## Bun Extensions <a name="bun-extensions"></a>
Optimized utilities for Bun runtime.
### File Operations
| Function | Description | Type Signature |
|----------|-------------|----------------|
| `readFileSafe` | Reads file safely | `(path: string) => Promise<Either<string, Error>>` |
| `listToFile` | Writes list to file | `(list: List<string>, path: string) => Promise<Either<void, Error>>` |
### JSON & Environment
| Function | Description |
|----------|-------------|
| `safeJsonParse` | Safe JSON parsing | `safeJsonParse<T>(data): Either<T, Error>` |
| `envOption` | Environment variable as Option | `envOption('PORT')` |
### Server Utilities
| Function | Description | Example |
|----------|-------------|---------|
| `createServer` | Creates HTTP server | `createServer(handleRequest)` |
| `asyncReduce` | Async list reduction | `asyncReduce(list, reducer, initial)` |
### Server Example
```typescript
const handleRequest = (req: Request): Either<Response, Error> => {
return req.url === '/'
? right(new Response('Hello'))
: left(new Error('Not found'))
}
createServer(handleRequest)