@jamashita/publikum-monad v3.12.0
Publikum/Monad
Installation
npm install --save @jamashita/publikum-monad
yarn add @jamashita/publikum-monad What this package supplies
Prerequisite
These are the definition of type aliases for the class description.
type UnaryFunction<I, O> = (arg: I) => O;
type Predicate<T> = (arg: T) => boolean;
type Consumer<T> = (arg: T) => unknown | void;
type Supplier<T> = () => T;
type Peek = () => unknown | void;
type SyncAsync<T> = T | PromiseLike<T>;What is Unscharferelation?
This is an Optional class that can deal with Promise.
Motivation
Prerequisite for Unscahrferelation
Optional is easily built in TypeScript
By doing this, you can build sooooo easily.
type Some<T> = Readonly<{
present: true;
value: T;
}>;
type None = Readonly<{
present: false;
}>;
type Optional<T> = Some<T> | None;An obstacle appears!
Promise brings us a tragedy.
Promise is a class for asynchronous action in JavaScript and TypeScript. This class is essential for nowadays
TypeScript development. This class can be a problem, because this is just a ticket for the future response. Promise
does actually exist, but not guarantee that the future response exists. So Optional<Promise<T>> is
definitely Some<Promise<T>>. In other words, Optional<Promise<T>> does not make any sense.
const optional: Optional<Promise<User | null>> = findUserByID(1999);
if (optional.present) {
// finally you have to check the value is null or not!
const res: User | null = await optional.value;
}
else {
// ...
}What Unscharfeleration enables
- Unscharfeleration enables us not to consider the value is
nullableor not - Unscharfeleration enables us not to consider the value is Synchronous or Asynchronous
Unscharfeleration API
What is Epoque? What is Heisenberg? See here!
(static) of<P>(func: UnaryFunction<Epoque<M>, unknown>): Unscharferelation<P>
Forge a Unscharferelation instance. The callback argument is not the same as Promise, such as
Unscharferelation.of<Response>((epoque: Epoque<Response>) => {
db.query('SELECT * FROM ...', (res?: Response) => {
try {
if (res === null || res === undefined) {
return epoque.decline();
}
return epoque.accept(res);
}
catch (err: unknown) {
return epoque.throw(err);
}
});
});(static) maybe<P>(value: SyncAsync<P>): Unscharferelation<P>
- When
SyncAsync<non-null>value given, returns Present Unscharferelation - When
SyncAsync<null | undefined>given, returns Absent Unscharferelation - When rejected
Promisegiven, returns Lost Unscharferelation
Unscharferelation.maybe<null>(null);
// Absent Unscharferelation
Unscharferelation.maybe<undefined>(undefined);
// Absent Unscharferelation
Unscharferelation.maybe<null>(Promise.resolve<null>(null));
// Absent Unscharferelation
Unscharferelation.maybe<undefined>(Promise.resolve<undefined>(undefined));
// Absent Unscharferelation(static) all<P>(unscharferelations: Iterable<Unscharferelation<P>>): Unscharferelation<Array<P>>
Alike Promise.all(), it aggregates all Unscharferelations.
- Only when all
Unscharferelationsare Present, returns Present Unscharferelation - When at least one of them is to be Absent, returns Absent Unscharferelation
- When at least one of them is to be Lost, Returns Lost Unscharferelation
const array: Array<Unscharferelation<Response>> = [unscharferelation1, unscharferelation2, unscharferelation3];
const unscharferelations: Unscharferelation<Array<Response>> = Unscharferelation.all<Response>(array);When Absent and Lost are satisfied together, Unscharfeleration will be Lost.
(static) anyway<P>(unscharferelations: Iterable<Unscharferelation<P>>): Promise<Array<Heisenberg<P>>>
Unlike to Unscharferelation.all(), this executes all Unscharfelerations even if they are going to be Absent or Lost.
const array: Array<Unscharferelation<Response>> = [unscharferelation1, unscharferelation2, unscharferelation3];
const heisenbergs: Array<Heisenberg<Response>> = await Unscharferelation.anyway<Response>(array);(static) ofHeisenberg<P>(heisenberg: Heisenberg<P>): Unscharferelation<P>
Forge a Unscharferelation instance.
(static) present<P>(value: SyncAsync<P>): Unscharferelation<P>
- When
SyncAsync<non-null>value given, returns Present Unscharferelation - When rejected
Promisegiven, returns Lost Unscharferelation
(static) absent<P>(value: SyncAsync<null | undefined>): Unscharferelation<P>
- When
SyncAsync<non-null>given, returns Absent Unscharferelation - When rejected
Promisegiven, returns Lost Unscharferelation
(instance) get(): Promise<P>
Get the retaining value.
- When
Unscharferelationis Absent,UnscharferelationErrorwill be thrown - When
Unscharferelationis Lost, its retaining value will be thrown
(instance) terminate(): Promise<Heisenberg<P>>
Unscharferelation supports method chain. This method is prepared to wait for all the chains done.
Please use this method to avoid to be thrown errors when using get() when its Unscharfeleration is going to
be Absent, Lost.
(instance) filter(predicate: Predicate<P>): Unscharferelation<P>
If Unscharferelation is Present, predicate is invoked and if it returns false, Unscharferelation becomes Absent.
(instance) map<Q = P>(mapper: UnaryFunction<P, SyncAsync<Unscharferelation<Q> | Q>>): Unscharferelation<Q>
- When
Unscharferelationis Present,mapperis going to be invoked and the nextUnscharferelationbecomesPresent, Absentdue to the return value- When an error is thrown, the next
Unscharferelationis going to beLost
- When an error is thrown, the next
- When
Unscharferelationis not Present,mapperis not going be invoked
(instance) recover<Q = P>(mapper: Supplier<SyncAsync<Unscharferelation<Q> | Q>>): Unscharferelation<P | Q>;
- When
Unscharferelationis Absent,mapperis going to be invoked and the nextUnscharferelationbecomesPresent, Absentdue to the return value- When an error is thrown, the next
Unscharferelationis going to beLost
- When an error is thrown, the next
- When
Unscharferelationis not Absent,mapperis not going be invoked
(instance) ifPresent(consumer: Consumer<P>): this
(instance) ifAbsent(consumer: Consumer<void>): this
(instance) ifLost(consumer: Consumer<unknown>): this
(instance) peek(peek: Peek): this
These methods are used for peeking.
Chaining
Unscharferelation supports method chain. You can chan as much as you want and get the result by adding terminate()
at the last of them.
const address: string = await Unscharferelation.maybe<Response>(userRepositoty.selectByName('foo bar')).map<User>((res: Response) => {
return res.user;
}).map<Company>((user: User) => {
return companyRepository.findByUserID(user.userID);
}).map<string>((company: Company) => {
return company.address;
}).recover<string>((err: UnscharferelationError) => {
// ...
return 'xxxx';
}).terminate();What is Superposition?
This is a Try class that can deal with Promise.
Motivation
Prerequisite for Superposition
Try is easily built in TypeScript
By doing this, you can easily build sooooo easily.
type Success<T> = Readonly<{
success: true;
value: T;
}>;
type Failure = Readonly<{
success: false;
error: unknown;
}>;
type Try<T> = Success<T> | Failure;An obstacle appears
Promise brings us a tragedy.
Promise is a class for asynchronous action in JavaScript and TypeScript. This class is essential for nowadays
TypeScript development. This class can be a problem, because this is just a ticket for the future response. Promise
absolutely does not throw errors but its retaining action may throw them. Try<Promise<T>, E>
is definitely Success<Promise<T>, E>. In other words, Try<Promise<T>, E> does not make any sense.
const tried: Try<Promise<UserID>> = createUser(user);
if (tried.success) {
// does not this really throw any errors?
try {
const userID: UserID = await tried.value;
}
catch (err: unknown) {
// ...
}
}
else {
// This tried is Failure
}What Superposition enables
- Superposition enables us not to consider nor investigate the method throws errors
- Superposition enables us not to consider the action is Synchronous or Asynchronous
Superposition API
What is Chrono? What is Schrodinger? See here!
(static) of<A, D>(func: UnaryFunction<Chrono<A, D>, unknown>, ...errors: Array<DeadConstructor<D>>): Superposition<A, D>
Forge a Superposition instance. The callback argument is not the same as Promise, such as
Superposition.of<number, SyntaxError>((chrono: Chrono<number, SyntaxError>) => {
try {
return chrono.accept(JSON.parse(str));
}
catch (err: unknown) {
if (err instanceof SyntaxError) {
return chrono.decline(err);
}
return chrono.throw(err);
}
}, SyntaxError);(static) playground<A, D>(supplier: Supplier<SyncAsync<A>>, ...errors: Array<DeadConstructor<D>>): Superposition<A, D>
- When
SyncAsync<non-error>value is given, returns Alive Superposition - When
SyncAsync<error>given, returns Dead Superposition - When a thrown error is not contained in
errors, returns Contradiction Superposition
Superposition.playground<User, DBError>(() => {
return db.query('SELECT * FROM ....');
}, DBError);(static) all<A, D>(superpositions: Iterable<Superposition<A, D>>): Superposition<Array<A>, D>
Alike Promise.all(), it aggregates all Superpositions.
- Only when all
Superpositionsare Alive, returns AliveSuperposition<Array<A>, D> - When at least one of them is to be Dead, returns Dead
Superposition<Array<A>, D> - When at least one of them is to be Contradiction, Returns Contradiction
Superposition<Array<A>, D>
const array: Array<Superposition<Response>> = [superposition1, superposition2, superposition3];
const superpositions: Superposition<Array<Response>> = Superposition.all<Response>(array);When Dead and Contradiction are satisfied together, Superposition is going to be Contradiction.
(static) anyway<A, D>(superpositions: Iterable<Superposition<A, D>>): Promise<Array<Schrodinger<A, D>>> {
Unlike to Superposition.all(), this executes all Superpositions even if they are going to be Dead or Contradiction.
const array: Array<Superposition<Response>> = [superposition1, superposition2, superposition3];
const schrodingers: Array<Schrodinger<Response>> = await Superposition.anyway<Response>(array);(static) ofSchrodinger<AT, DT extends Error>(schrodinger: Schrodinger<AT, DT>, ...errors: ReadonlyArray<DeadConstructor<DT>>): Superposition<A, D>
Forge a Superposition instance.
(static) alive<A, D>(value: SyncAsync<A>, ...errors: Array<DeadConstructor<D>>): Superposition<A, D> {
- When
SyncAsync<non-error>value is given, returns Alive Superposition - When rejected
Promisegiven, returns Contradiction Superposition
(static) dead<A, D>(error: PromiseLike<A> | D, ...errors: Array<DeadConstructor<D>>): Superposition<A, D>
- When
SyncAsync<error>given, returns Dead Superposition - When rejected
Promisegiven, returns Dead or Contradiction Superposition- When an error is contained in
errors, returns Dead Superposition, otherwise returns Contradiction Superposition
- When an error is contained in
(instance) get(): Promise<A>
Get the retaining value.
(instance) terminate(): Promise<Schrodinger<A, D>>
Superposition supports method chain. This method is prepared to wait for all the chains done.
Please use this method to avoid to be thrown errors when using get() when its Superposition is going to
be Dead, Contradiction.
(instance) filter(predicate: Predicate<A>): Superposition<A, D | SuperpositionError>
if Superposition is Alive, predicate is invoked and if it returns false, Superposition becomes Dead.
(instance) map<B = A, E = D>(mapper: UnaryFunction<A, SyncAsync<Superposition<B, E> | B>>, ...errors: Array<DeadConstructor<E>>): Superposition<B, D | E>
- When
Superpositionis Alive,mapperis going to be invoked and the nextSuperpositionbecomesAlive, Deaddue to the return value and error- When an error is thrown, as far as its retaining
errorsand givenerrorscontain the error, the nextSuperpositionis going to beDead, otherwise,Superpositionis going to beContradiction
- When an error is thrown, as far as its retaining
- When
Superpositionis not Alive,mapperis not going be invoked
(instance) recover<B = A, E = D>(mapper: UnaryFunction<D, SyncAsync<Superposition<B, E> | Detoxicated<B>>>, ...errors: Array<DeadConstructor<E>>): Superposition<A | B, E>
- When
Superpositionis Dead,mapperis going to be invoked and the nextSuperpositionbecomesAlive, Deaddue to the return value and error- When an error is thrown, as far as given
errorscontain the error, the nextSuperpositionis going to beDeadotherwise,Superpositionis going to beContradiction
- When an error is thrown, as far as given
- When
Superpositionis not Dead,mapperis not going be invoked
(instance) transform<B = A, E = D>(alive: UnaryFunction<A, SyncAsync<Superposition<B, E> | B>>, dead: UnaryFunction<D, SyncAsync<Superposition<B, E> | B>>, ...errors: Array<DeadConstructor<E>>): Superposition<B, E>
- When
Superpositionis Alive,aliveis going to be invoked and the nextSuperpositionbecomesAlive, Deaddue to the return value and error- When an error is thrown, as far as given
errorscontain the error, the nextSuperpositionis going to beDead, otherwise,Superpositionis going to beContradiction
- When an error is thrown, as far as given
- When
Superpositionis Dead,deadis going to be invoked and the nextSuperpositionbecomesAlive, Deaddue to the return value and error- When an error is thrown, as far as given
errorscontain the error, the nextSuperpositionis going to beDeadotherwise,Superpositionis going to beContradiction
- When an error is thrown, as far as given
- When
Superpositionis not Alive nor Dead,alive, deadare not going be invoked
(instance) ifAlive(consumer: Consumer<A>): this
(instance) ifDead(consumer: Consumer<D>): this
(instance) ifContradiction(consumer: Consumer<unknown>): this
(instance) peek(peek: Peek): this
These methods are used for peeking.
Chaining
Superposition supports method chain. You can chan as much as you want and get the result by adding terminate()
at the last of them.
const address: string = await Superposition.playground<Response, UserError>(() => {
return userRepositoty.selectByName('foo bar');
}, UserError).map<User, UserError>((res: Response) => {
return res.user;
}).map<Company, UserError | CompanyError>((user: User) => {
return companyRepository.findByUserID(user.userID);
}, CompanyError).map<string, UserError | CompanyError>((company: Company) => {
return company.address;
}).recover<string, Error>((err: UserError | CompanyError) => {
// ...
return 'xxxx';
}).terminate();5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago