1.2.0 • Published 9 months ago

monads-lite v1.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

monads-lite

A TypeScript monad library with only the things you'll actually use.

Is this you?

I'm a JS/TS developer interested in using some more functional programming patterns in my code, but all these FP libs don't fit with the way I work!

Then mondas-lite is what you need!

monads-lite is JS/TS library that brings mondic functional programming tools that don't take over your code, and let you expore the benifits functional programming without re-writing your codebase.

Install

npm i monads-lite

Library

Result

The Result<T, E> type is a monadic construct that can represent the result of an operation which can either succeed or fail.

i.e. type OperationResult = Result.Result<number, 'oh no, I failed'>;

A Result can be infered from a Promise if a error type is provided:

import { Result } from 'monads-lite';

const promise = Promise.resolve(123);
const result: Result<number, CustomErrorType> = 
    inferFrom(promise).resultify<CustomErrorType>();

A Result can be matched on if it is an Ok or Err:

import { Result } from 'monads-lite';

// This is a powerful tool for program flow control.
const value = Result.match(result, [
    (okValue) => handleOk(okValue),
    (errValue) => handleErr(errValue),
]);

Actions can be run inside the Result monadic container so that they will only apply if the Result is of type Ok:

import { Result } from 'monads-lite';

const value = Result.act(result, (okValue) => doNextThing(okValue));

These actions can be chained:

import { Result } from 'monads-lite';

const value = Result.onResult(result)
    // These actions will only execute if the Result is Ok.
    .act(n => n + 1)
    .act(n => n * 2)
    // Unwrap the value from inside the Result.
    .done();

Actions can also be run asynchronously:

import { Result } from 'monads-lite';

const result = await Result.onResult(result)
    .actAsync(async (n) => n + 1)
    .actAsync(async (n) => n * 2)
    .done();

Errors thrown anywhere in the act chain will be resolve out as Err:

import { Result } from 'monads-lite';

const result = Result.onValue<number, Error>(2)
    .act((n) => n + 1) // This will run.
    .act(() => {
        // This will be caught and converted into an Err.
        throw new Error('fail 1');
    })
    .act((n) => n * 2) // This will not run.
    .act(() => {
        // This will not run.
        throw new Error('fail 2');
    })
    // This unwrap the Result.
    .done();

// or

const result = await Result.onValue<number, Error>(2)
    .act((n) => n + 1) // This will run.
    .act(() => {
        // This will be caught and converted into an Err.
        throw new Error('fail 1');
    })
    .act((n) => n * 2) // This will not run.
    .actAsync(async () => {
        // This will not run.
        throw new Error('fail 2');
    })
    // This unwrap the Result.
    .done();

Maybe

The Maybe<A> type is a monadic construct that can represent a value that is either present or not present.

i.e. type Username = Maybe<string>;

Actions can be run inside the Maybe monadic container so that they will only apply if the Result is of type Ok:

import { Maybe } from 'monads-lite';

const value = Maybe.act(maybe, (existingValue) => doNextThing(existingValue));

These actions can be chained:

import { Maybe } from 'monads-lite';

const value = Maybe.onResult(maybe)
    // These actions will only execute if the Result is Ok.
    .act(n => n + 1)
    .act(n => n * 2)
    // Unwrap the value from inside the Result.
    .done();

A Maybe can be matched against cases:

import { Maybe } from 'monads-lite';

// If 2, 3 or 9, repeat the digit 5 times.
const value = Maybe.match(maybe, [
    n => (n === 2 && (() => 22222)),
    n => (n === 3 && (() => 33333)),
    n => (n === 9 && (() => 99999)),
]);

When matching a Maybe a default case can also be provided:

import { Maybe } from 'monads-lite';

// If 2, 3 or 9, repeat the digit 5 times,
// otherwise leave value unchanges.
const value = Maybe.match(maybe, [
    n => (n === 2 && (() => 22222)),
    n => (n === 3 && (() => 33333)),
    n => (n === 9 && (() => 99999)),
], n => n);

curry

The curry function can be used to split a multi-argument function into a nested set of single argument functions. This technique is called currying.

import { curry } from 'monads-lite';

const add = (a: number, b: number, c: number) => {
    return a + b + c;
};

const curriedAdd = curry(add);
const addFive = curriedAdd(5);
const addTwenty = addFive(15);

const thirty: number = addTwenty(10);
1.2.0

9 months ago

1.1.5-curry.0

9 months ago

1.1.4

9 months ago

1.1.3

9 months ago

1.1.2

9 months ago

1.1.1

9 months ago

1.1.0

9 months ago

1.0.4

9 months ago

1.0.3

9 months ago

1.0.2

9 months ago

1.0.1

9 months ago

1.0.0

9 months ago