Skip to content
This repository has been archived by the owner on Feb 26, 2022. It is now read-only.

Version 0.0.1 #1

Merged
merged 1 commit into from
Apr 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.vscode
examples
node_modules
158 changes: 158 additions & 0 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
declare type FptsEither<L, A> = FptsLeft<L, A> | FptsRight<L, A>;
declare type FptsLeft<L, A> = {
readonly value: L;
readonly _tag: "Left";
readonly _A: A;
readonly _L: L;
};
declare type FptsRight<L, A> = {
readonly value: A;
readonly _tag: "Right";
readonly _A: A;
readonly _L: L;
};
declare type FptsOption<A> = FptsNone<A> | FptsSome<A>;
declare type FptsNone<A> = {
readonly _tag: "None";
readonly _A: A;
};
declare type FptsSome<A> = {
readonly value: A;
readonly _tag: "Some";
readonly _A: A;
};

declare type Maybe<A> = Just<A> | Nothing;
declare type Just<A> = {
readonly tag: "Just";
value: A;
};
declare type Nothing = {
readonly tag: "Nothing";
};
/**
* Construct Just a value.
*/
declare const Just: <A>(a: A) => Just<A>;
/**
* Nothing.
*/
declare const Nothing: Nothing;
declare const Maybe: Readonly<{
Fpts: Readonly<{
fromEither: <A>(either: FptsEither<unknown, A>) => Maybe<A>;
fromOption: <A>(option: FptsOption<A>) => Maybe<A>;
}>;
fromNullable: <A>(nullable: A | null | undefined) => Maybe<A>;
isNothing: <A>(maybe: Maybe<A>) => maybe is Nothing;
/**
* Provide a default value, turning a Maybe value into a normal value.
*/
withDefault: <A>(a: A) => (maybe: Maybe<A>) => A;
/**
* Transform a Maybe value with a given function.
*/
map: <A, B>(mapper: (a: A) => B) => (maybeA: Maybe<A>) => Maybe<B>;
/**
* Apply a function if all the arguments are Just a value.
*/
map2: <A, B, Value>(mapper: (a: A) => (b: B) => Value) => (maybeA: Maybe<A>) => (maybeB: Maybe<B>) => Maybe<Value>;
/**
* Chain together many computations that may fail.
*/
andThen: <A, B>(callback: (a: A) => Maybe<B>) => (maybeA: Maybe<A>) => Maybe<B>;
}>;

declare type Comparable<C> = (c: C) => number;
declare const Comparable: Readonly<{
date: Comparable<Date>;
}>;

declare const FArray: Readonly<{
concat: <AS extends readonly unknown[]>(nested: readonly AS[]) => Readonly<AS>;
filter: <A>(predicate: (a: A) => boolean) => (as: readonly A[]) => readonly A[];
map: <B, A>(mapper: (a: A) => B) => (as: readonly A[]) => readonly B[];
findLast: <A>(predicate: (a: A) => boolean) => (as: readonly A[]) => Maybe<A>;
sortBy: <A>(compareBy: Comparable<A>) => (as: readonly A[]) => readonly A[];
head: <A>(as: readonly A[]) => Maybe<A>;
}>;

declare const True: boolean;
declare const False: boolean;

declare const Debug: Readonly<{
log: (message: string) => <A>(a: A) => A;
}>;

/**
* Given a value, returns exactly the same value.
*/
declare const identity: <A>(a: A) => A;
/**
* Create a function that always returns the same value.
*/
declare const always: <A>(a: A) => (ignored?: unknown) => A;
/**
* Create a function that always returns `void`.
*/
declare const alwaysVoid: (_ignored?: unknown) => void;
/**
* Create a function that always returns `void` but its type signature is `never`.
*/
declare const alwaysNever: (ignored?: unknown) => never;
declare const flip: <A, B, C>(f: (a: A) => (b: B) => C) => (a: B) => (b: A) => C;
declare const dot: <A, K extends keyof A>(key: K) => (record: A) => A[K];
declare const compose: {
<A, B, C>(b: (a: A) => B, c: (b: B) => C): (a: A) => C;
<A, B, C>(b: (a: A) => B, c: (b: B) => C): (a: A) => C;
<A, B, C, D>(b: (a: A) => B, c: (b: B) => C, d: (c: C) => D): (a: A) => D;
<A, B, C, D, E>(b: (a: A) => B, c: (b: B) => C, d: (c: C) => D, e: (d: D) => E): (a: A) => E;
<A, B, C, D, E, F>(b: (a: A) => B, c: (b: B) => C, d: (c: C) => D, e: (d: D) => E, f: (e: E) => F): (a: A) => F;
<A, B, C, D, E, F, G>(b: (a: A) => B, c: (b: B) => C, d: (c: C) => D, e: (d: D) => E, f: (e: E) => F, g: (f: F) => G): (a: A) => G;
};
declare const pipe: {
<A, B>(a: A, b: (a: A) => B): B;
<A, B, C>(a: A, b: (a: A) => B, c: (b: B) => C): C;
<A, B, C, D>(a: A, b: (a: A) => B, c: (b: B) => C, d: (c: C) => D): D;
<A, B, C, D, E>(a: A, b: (a: A) => B, c: (b: B) => C, d: (c: C) => D, e: (d: D) => E): E;
<A, B, C, D, E, F>(a: A, b: (a: A) => B, c: (b: B) => C, d: (c: C) => D, e: (d: D) => E, f: (e: E) => F): F;
<A, B, C, D, E, F, G>(a: A, b: (a: A) => B, c: (b: B) => C, d: (c: C) => D, e: (d: D) => E, f: (e: E) => F, g: (f: F) => G): G;
};

declare type Result<ErrResult, Value> = Ok<Value> | Err<ErrResult>;
declare type Ok<A> = {
tag: "Ok";
value: A;
};
declare type Err<X> = {
tag: "Err";
error: X;
};
declare const Ok: <A>(value: A) => Ok<A>;
declare const Err: <X>(error: X) => Err<X>;
declare const Result: Readonly<{
map: <X, A, B>(mapper: (a: A) => B) => (resultA: Result<X, A>) => Result<X, B>;
mapError: <X, Y, A>(mapper: (a: X) => Y) => (resultA: Result<X, A>) => Result<Y, A>;
}>;

declare const tag: unique symbol;
declare const run: unique symbol;
declare type Task<A> = {
readonly tag: typeof tag;
readonly run?: typeof run;
readonly [run]: () => PromiseLike<Result<Error, A>>;
};
declare const Task: Readonly<{
reasonToError: (reason: unknown) => Error;
attempt: <A>(callback: (result: Result<Error, A>) => void) => (task: Task<A>) => void;
fromPromise: <A>(promiseLazy: () => PromiseLike<A>) => Task<A>;
fromCallback: <I, A>(fun: (input: I, callback: (e: unknown, r?: A | undefined) => void) => void) => (input: I) => Task<A>;
fromMaybe: (errorWhenNothing: Error) => <A>(maybe: Maybe<A>) => Task<A>;
map: <A, B>(mapper: (a: A) => B) => (taskA: Task<A>) => Task<B>;
succeed: <A>(a: A) => Task<A>;
fail: (error: Error) => Task<never>;
andThen: <A, B>(callback: (a: A) => Task<B>) => (taskA: Task<A>) => Task<B>;
sleep: (inMillis: number) => Task<number>;
}>;

export { Comparable, Debug, Err, FArray, False, Just, Maybe, Nothing, Ok, Result, Task, True, always, alwaysNever, alwaysVoid, compose, dot, flip, identity, pipe };
184 changes: 184 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const fromNullable = (nullable) => nullable === null || nullable === undefined ? Nothing : Just(nullable);
const isNothing = (maybe) => maybe === Nothing;
const withDefault = (a) => (maybe) => isNothing(maybe) ? a : maybe.value;
const map = (mapper) => (maybeA) => isNothing(maybeA) ? Nothing : Just(mapper(maybeA.value));
const map2 = (mapper) => (maybeA) => (maybeB) => isNothing(maybeA) || isNothing(maybeB)
? Nothing
: Just(mapper(maybeA.value)(maybeB.value));
const andThen = (callback) => (maybeA) => isNothing(maybeA)
? Nothing
: callback(maybeA.value);
const Fpts = Object.freeze({
fromEither: (either) => either._tag === "Left" ? Nothing : Just(either.value),
fromOption: (option) => option._tag === "None" ? Nothing : Just(option.value)
});
const Just = (a) => ({ tag: "Just", value: a });
const Nothing = Object.freeze({ tag: "Nothing" });
const Maybe = Object.freeze({
Fpts,
fromNullable,
isNothing,
withDefault,
map,
map2,
andThen
});

const concat = (nested) => [].concat(...nested);
const filter = (predicate) => (as) => as.filter(predicate);
const map$1 = (mapper) => (as) => as.map(mapper);
const findLast = (predicate) => (as) => {
for (let i = as.length - 1; i >= 0; --i) {
const a = as[i];
if (predicate(a)) {
return Just(a);
}
}
return Nothing;
};
const sortBy = (compareBy) => (as) => as.slice().sort((a, b) => compareBy(a) - compareBy(b));
const head = (as) => as.length === 0 ? Nothing : Just(as[0]);
const FArray = Object.freeze({
concat,
filter,
map: map$1,
findLast,
sortBy,
head
});

const True = true;
const False = false;

const date = d => d.valueOf();
const Comparable = Object.freeze({
date
});

const log = (message) => (a) => {
message.length > 0 ? console.log(message, a) : console.log(a);
return a;
};
const Debug = Object.freeze({
log
});

const stepFun = (prevRetVal, fun) => fun(prevRetVal);
const identity = (a) => a;
const always = (a) => () => a;
const alwaysVoid = (_ignored) => { };
const alwaysNever = alwaysVoid;
const flip = (f) => b => a => f(a)(b);
const dot = (key) => (record) => record[key];
const compose = (...funs) => a => funs.reduce(stepFun, a);
const pipe = (a, ...funs) => funs.reduce(stepFun, a);

const Ok = (value) => ({
tag: "Ok",
value
});
const Err = (error) => ({
tag: "Err",
error
});
const map$2 = (mapper) => (resultA) => resultA.tag === "Err" ? resultA : Ok(mapper(resultA.value));
const mapError = (mapper) => (resultA) => resultA.tag === "Ok" ? resultA : Err(mapper(resultA.error));
const Result = Object.freeze({
map: map$2,
mapError
});

const tag = Symbol("Task");
const run = Symbol("run task");
const reasonToError = (reason) => {
return reason instanceof Error
? reason
: typeof reason === "string"
? new Error(reason)
: reason === undefined
? new Error()
: new Error(String(reason));
};
const fromPromise = (promiseLazy) => ({
tag,
[run]: () => promiseLazy().then(Ok)
});
const fromCallback = (fun) => input => {
const cbPromise = new Promise(resolve => {
fun(input, (err, value) => {
err !== null || err !== undefined
? resolve(Err(reasonToError(err)))
: value === null || value === undefined
? resolve(Err(new Error("fromCallback: Value missing")))
: resolve(Ok(value));
});
});
return {
tag,
[run]: () => cbPromise
};
};
const fromMaybe = (errorWhenNothing) => (maybe) => Maybe.isNothing(maybe) ? fail(errorWhenNothing) : succeed(maybe.value);
const succeed = (a) => ({
tag,
[run]: () => Promise.resolve(Ok(a))
});
const fail = (error) => ({
tag,
[run]: () => Promise.resolve(Err(error))
});
const map$3 = (mapper) => (taskA) => ({
tag,
[run]: () => taskA[run]().then(Result.map(mapper))
});
const andThen$1 = (callback) => (taskA) => ({
tag,
[run]: () => taskA[run]()
.then(result => result.tag === "Err" ? fail(result.error) : callback(result.value))
.then(nextTask => nextTask[run]())
});
const attempt = (callback) => (task) => Promise.resolve()
.then(task[run])
.then(callback, compose(reasonToError, Err, callback))
.then(alwaysVoid, alwaysVoid);
const sleep = (inMillis) => ({
tag,
[run]: () => new Promise((resolve) => setTimeout(() => resolve(Ok(inMillis)), inMillis))
});
const Task = Object.freeze({
reasonToError,
attempt,
fromPromise,
fromCallback,
fromMaybe,
map: map$3,
succeed,
fail,
andThen: andThen$1,
sleep
});

exports.Comparable = Comparable;
exports.Debug = Debug;
exports.Err = Err;
exports.FArray = FArray;
exports.False = False;
exports.Just = Just;
exports.Maybe = Maybe;
exports.Nothing = Nothing;
exports.Ok = Ok;
exports.Result = Result;
exports.Task = Task;
exports.True = True;
exports.always = always;
exports.alwaysNever = alwaysNever;
exports.alwaysVoid = alwaysVoid;
exports.compose = compose;
exports.dot = dot;
exports.flip = flip;
exports.identity = identity;
exports.pipe = pipe;
Loading