Skip to content

Commit

Permalink
fix linter errors
Browse files Browse the repository at this point in the history
  • Loading branch information
vjrasane committed Jun 14, 2022
1 parent d74677e commit e618d14
Show file tree
Hide file tree
Showing 16 changed files with 502 additions and 465 deletions.
42 changes: 42 additions & 0 deletions .eslintrc
@@ -0,0 +1,42 @@
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:import/typescript",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"indent": [
"error",
2
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
],
"no-mixed-spaces-and-tabs": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-namespace": 0,
"@typescript-eslint/ban-types": 0
}
}
71 changes: 35 additions & 36 deletions src/either.api.ts
@@ -1,10 +1,10 @@
import * as Class from "./either.class";
import { NonEmptyArray } from "./utils";
import { LeftType, EitherConstructType, EitherType } from "./either.class";
import * as Class from './either.class';
import { NonEmptyArray } from './utils';
import { LeftType, EitherConstructType, EitherType } from './either.class';

export type Fold<E, A, B> = {
right: (a: A) => B,
left: (e: E) => B
right: (a: A) => B,
left: (e: E) => B
}

export type Either<E, A> = Class.Right<E, A> | Class.Left<E, A>;
Expand All @@ -13,29 +13,29 @@ export const Right = <A, E = any>(value: A): Either<E, A> => new Class.Right(val
export const Left = <E, A = any>(value: E): Either<E, A> => new Class.Left(value);

export const record = <R extends Record<string | number | symbol, Either<any, any>>>(
record: R
): Either<LeftType<R[keyof R]>, EitherConstructType<R>> => {
return Object.entries(record).reduce(
(acc, [key, value]): Either<LeftType<R[keyof R]>, EitherConstructType<R>> => {
return acc.chain(
(a): Either<LeftType<R[keyof R]>, EitherConstructType<R>> => value.map(
(v): EitherConstructType<R> => ({ ...a, [key]: v }))
);
}, Right({} as EitherConstructType<R>)
);
};
record: R
): Either<LeftType<R[keyof R]>, EitherConstructType<R>> => {
return Object.entries(record).reduce(
(acc, [key, value]): Either<LeftType<R[keyof R]>, EitherConstructType<R>> => {
return acc.chain(
(a): Either<LeftType<R[keyof R]>, EitherConstructType<R>> => value.map(
(v): EitherConstructType<R> => ({ ...a, [key]: v }))
);
}, Right({} as EitherConstructType<R>)
);
};

export const all = <T extends readonly Either<any, any>[] | []>(
arr: T
): Either<LeftType<T[number]>, EitherConstructType<T>> => {
return (arr as readonly Either<any, any>[]).reduce(
(acc, curr): Either<LeftType<T[number]>, EitherConstructType<T>> => acc.chain(
(a): Either<LeftType<T[number]>, EitherConstructType<T>> => curr.map(
(v): EitherConstructType<T> => [...(a as unknown as any[]), v] as unknown as EitherConstructType<T>)
), Right([] as unknown as EitherConstructType<T>)
);
arr: T
): Either<LeftType<T[number]>, EitherConstructType<T>> => {
return (arr as readonly Either<any, any>[]).reduce(
(acc, curr): Either<LeftType<T[number]>, EitherConstructType<T>> => acc.chain(
(a): Either<LeftType<T[number]>, EitherConstructType<T>> => curr.map(
(v): EitherConstructType<T> => [...(a as unknown as any[]), v] as unknown as EitherConstructType<T>)
), Right([] as unknown as EitherConstructType<T>)
);
};

export const array = all;

export const applyAll = <
Expand All @@ -52,7 +52,7 @@ F extends (...args: P) => any
};

export const some = <A extends NonEmptyArray<Either<LeftType<A[number]>, EitherType<A[number]>>>> (arr: A): A[number] =>
arr.reduce((acc, curr) => acc.or(curr));
arr.reduce((acc, curr) => acc.or(curr));

export const values = <A extends Array<Either<any, any>>>(arr: A): Array<EitherType<A[number]>> => {
return arr.reduce(
Expand All @@ -66,13 +66,12 @@ export const values = <A extends Array<Either<any, any>>>(arr: A): Array<EitherT
};

export const Either = {
Left,
Right,
applyAll,
all,
some,
array,
record,
values
} as const;

Left,
Right,
applyAll,
all,
some,
array,
record,
values
} as const;
186 changes: 93 additions & 93 deletions src/either.class.ts
@@ -1,114 +1,114 @@
import { Just, Maybe, Nothing } from "../maybe";
import Result, { Err, Ok } from "../result";
import { Either, Fold } from "./either.api";
import { Tuple } from "../tuple";
import { curry, FunctionInputType, FunctionOutputType } from "./utils";
import { Just, Maybe, Nothing } from '../maybe';
import Result, { Err, Ok } from '../result';
import { Either, Fold } from './either.api';
import { Tuple } from '../tuple';
import { curry, FunctionInputType, FunctionOutputType } from './utils';

export type EitherType<R> = R extends Either<any, infer T>
? T : never;
? T : never;

export type LeftType<R> = R extends Either<infer T, any> ? T : never;

export type EitherConstructType<
A extends readonly Either<unknown, unknown>[] | Record<string | symbol | number, Either<unknown, unknown>>
A extends readonly Either<unknown, unknown>[] | Record<string | symbol | number, Either<unknown, unknown>>
> = { -readonly [P in keyof A]: EitherType<A[P]> };


interface IEither<E, A> {
base: { tag: 'left', value: E } | { tag: 'right', value: A }
map: <B>(fab: (a: A) => B) => Either<E, B>,
mapLeft: <F>(fef: (e: E) => F) => Either<F, A>,
chain: <B>(fab: (a: A) => Either<E, B>) => Either<E, B>,
apply: (v: Either<E, FunctionInputType<A>>) => Either<E, FunctionOutputType<A>>
join: () => A extends Either<E, infer T> ? Either<E, T> : never,
swap: () => Either<A, E>,
fold: <B>(f: Fold<E, A, B>) => B,
or: (ra: Either<E, A>) => Either<E, A>,
orElse: (ra: Either<E, A>) => Either<E, A>,
default: (a: A) => Either<E, A>,
toMaybe: () => Maybe<A>,
toResult: () => Result<E, A>,
toTuple: () => Tuple<Maybe<E>, Maybe<A>>
get: () => A | undefined,
getOrElse: (def: A) => A,
getRight: () => Maybe<A>,
getLeft: () => Maybe<E>,
toString: () => string,
}
base: { tag: 'left', value: E } | { tag: 'right', value: A }
map: <B>(fab: (a: A) => B) => Either<E, B>,
mapLeft: <F>(fef: (e: E) => F) => Either<F, A>,
chain: <B>(fab: (a: A) => Either<E, B>) => Either<E, B>,
apply: (v: Either<E, FunctionInputType<A>>) => Either<E, FunctionOutputType<A>>
join: () => A extends Either<E, infer T> ? Either<E, T> : never,
swap: () => Either<A, E>,
fold: <B>(f: Fold<E, A, B>) => B,
or: (ra: Either<E, A>) => Either<E, A>,
orElse: (ra: Either<E, A>) => Either<E, A>,
default: (a: A) => Either<E, A>,
toMaybe: () => Maybe<A>,
toResult: () => Result<E, A>,
toTuple: () => Tuple<Maybe<E>, Maybe<A>>
get: () => A | undefined,
getOrElse: (def: A) => A,
getRight: () => Maybe<A>,
getLeft: () => Maybe<E>,
toString: () => string,
}

abstract class AEither<E, A> implements IEither<E, A> {
protected abstract self: Either<E, A>;

get base(): { tag: 'left', value: E } | { tag: 'right', value: A } {
switch(this.self.tag) {
case "left":
return { tag: 'left', value: this.self.value };
default:
return { tag: "right", value: this.self.value }
}
}


get = () => this.toMaybe().get();
getOrElse = (def: A) => this.toMaybe().getOrElse(def);
default = (def: A) => this.self.tag === "right" ? this.self : new Right<E, A>(def);
or = (other: Either<E, A>) => {
switch(this.self.tag) {
case "right":
return this.self;
default:
return other.tag === "right" ? other : this.self;
}
}
orElse = (other: Either<E, A>) => other.or(this.self);
map = <B>(fab: (a: A) => B): Either<E, B> => this.self.tag === "right"
? new Right<E, B>(fab(this.self.value))
: new Left<E, B>(this.self.value)
mapLeft = <F>(fef: (e: E) => F): Either<F, A> => this.self.tag === "right"
? new Right<F, A>(this.self.value)
: new Left<F, A>(fef(this.self.value))

chain = <B>(fab: (a: A) => Either<E, B>): Either<E, B> => this.self.tag === "right"
? fab(this.self.value) : new Left(this.self.value);
apply = (ra: Either<E, FunctionInputType<A>>): Either<E, FunctionOutputType<A>> =>
this.chain((f) => ra.map((a) => typeof f === 'function'
? curry(f as unknown as (...args: any[]) => any)(a)
: a)) as Either<E, FunctionOutputType<A>>;
join = (): A extends Either<E, infer T> ? Either<E, T> : never =>
this.chain(
(m) => m instanceof AEither
? m as unknown as A extends Either<E, infer T> ? Either<E, T> : never
: new Right(m) as unknown as A extends Either<E, infer T> ? Either<E, T> : never
) as A extends Either<E, infer T> ? Either<E, T> : never;
swap = () => this.self.tag === "right" ? new Left<A, E>(this.self.value) : new Right<A, E>(this.self.value)
fold = <B>(f: Fold<E, A, B>) => this.self.tag === "right" ? f.right(this.self.value) : f.left(this.self.value);
toMaybe = () => this.getRight();
toResult = () => this.self.tag === "right" ? Ok(this.self.value) : Err(this.self.value);
toTuple = () => Tuple(this.getLeft(), this.getRight());
getRight = () => this.self.tag === "right" ? Just(this.self.value) : Nothing<A>();
getLeft = () => this.self.tag === "right" ? Nothing<E>() : Just(this.self.value);
toString = () => {
switch(this.self.tag) {
case "right":
return `Right(${this.self.value})`;
default:
return `Left(${this.self.value})`;
}
};
protected abstract self: Either<E, A>;

get base(): { tag: 'left', value: E } | { tag: 'right', value: A } {
switch(this.self.tag) {
case 'left':
return { tag: 'left', value: this.self.value };
default:
return { tag: 'right', value: this.self.value };
}
}


get = () => this.toMaybe().get();
getOrElse = (def: A) => this.toMaybe().getOrElse(def);
default = (def: A) => this.self.tag === 'right' ? this.self : new Right<E, A>(def);
or = (other: Either<E, A>) => {
switch(this.self.tag) {
case 'right':
return this.self;
default:
return other.tag === 'right' ? other : this.self;
}
};
orElse = (other: Either<E, A>) => other.or(this.self);
map = <B>(fab: (a: A) => B): Either<E, B> => this.self.tag === 'right'
? new Right<E, B>(fab(this.self.value))
: new Left<E, B>(this.self.value);
mapLeft = <F>(fef: (e: E) => F): Either<F, A> => this.self.tag === 'right'
? new Right<F, A>(this.self.value)
: new Left<F, A>(fef(this.self.value));

chain = <B>(fab: (a: A) => Either<E, B>): Either<E, B> => this.self.tag === 'right'
? fab(this.self.value) : new Left(this.self.value);
apply = (ra: Either<E, FunctionInputType<A>>): Either<E, FunctionOutputType<A>> =>
this.chain((f) => ra.map((a) => typeof f === 'function'
? curry(f as unknown as (...args: any[]) => any)(a)
: a)) as Either<E, FunctionOutputType<A>>;
join = (): A extends Either<E, infer T> ? Either<E, T> : never =>
this.chain(
(m) => m instanceof AEither
? m as unknown as A extends Either<E, infer T> ? Either<E, T> : never
: new Right(m) as unknown as A extends Either<E, infer T> ? Either<E, T> : never
) as A extends Either<E, infer T> ? Either<E, T> : never;
swap = () => this.self.tag === 'right' ? new Left<A, E>(this.self.value) : new Right<A, E>(this.self.value);
fold = <B>(f: Fold<E, A, B>) => this.self.tag === 'right' ? f.right(this.self.value) : f.left(this.self.value);
toMaybe = () => this.getRight();
toResult = () => this.self.tag === 'right' ? Ok(this.self.value) : Err(this.self.value);
toTuple = () => Tuple(this.getLeft(), this.getRight());
getRight = () => this.self.tag === 'right' ? Just(this.self.value) : Nothing<A>();
getLeft = () => this.self.tag === 'right' ? Nothing<E>() : Just(this.self.value);
toString = () => {
switch(this.self.tag) {
case 'right':
return `Right(${this.self.value})`;
default:
return `Left(${this.self.value})`;
}
};
}

export class Right<E, A> extends AEither<E, A> {
readonly tag = "right";
readonly tag = 'right';

constructor(readonly value: A) { super(); }
constructor(readonly value: A) { super(); }

protected self = this;
}
protected self = this;
}

export class Left<E, A> extends AEither<E, A> {
readonly tag = "left";
readonly tag = 'left';

constructor(readonly value: E) { super(); }
constructor(readonly value: E) { super(); }

protected self = this;
}
protected self = this;
}
14 changes: 7 additions & 7 deletions src/maybe.api.ts
@@ -1,5 +1,5 @@
import * as Class from "./maybe.class";
import { MaybeConstructType, MaybeType } from "./maybe.class";
import * as Class from './maybe.class';
import { MaybeConstructType, MaybeType } from './maybe.class';

export type Maybe<A> = Class.Just<A> | Class.Nothing<A>;

Expand Down Expand Up @@ -85,13 +85,13 @@ export const first = <A>(arr: Array<A>): Maybe<A> => nth(0, arr);
export const last = <A>(arr: Array<A>): Maybe<A> => nth(arr.length - 1, arr);

export const find =
<A, T extends readonly A[]>(f: (a: A) => boolean, arr: T): Maybe<A> => fromOptional(arr.find(f));
<A, T extends readonly A[]>(f: (a: A) => boolean, arr: T): Maybe<A> => fromOptional(arr.find(f));

export const some = <A extends Array<Maybe<MaybeType<A[number]>>>> (arr: A): Maybe<MaybeType<A[number]>> =>
arr.reduce(
(acc, curr): Maybe<MaybeType<A[number]>> => acc.or(curr),
Nothing<MaybeType<A[number]>>()
);
arr.reduce(
(acc, curr): Maybe<MaybeType<A[number]>> => acc.or(curr),
Nothing<MaybeType<A[number]>>()
);

export const values = <A extends Array<Maybe<any>>>(arr: A): Array<MaybeType<A[number]>> => {
return arr.reduce(
Expand Down

0 comments on commit e618d14

Please sign in to comment.