//Typescript
// Maybe type
// noinspection JSAnnotator
type Maybe<T> = {
map<U>(fn: (value: T) => U): Maybe<U>;
flatMap<U>(fn: (value: T) => Maybe<U>): Maybe<U>;
getOrElse(defaultValue: T): T;
};
const just = <T>(value: T): Maybe<T> => ({
map: <U>(fn: (value: T) => U) => just(fn(value)),
flatMap: <U>(fn: (value: T) => Maybe<U>) => fn(value),
getOrElse: (_: T) => value,
});
const nothing = <T>(): Maybe<T> => ({
map: <U>(_: (value: T) => U) => nothing<U>(),
flatMap: <U>(_: (value: T) => Maybe<U>) => nothing<U>(),
getOrElse: (defaultValue: T) => defaultValue,
});
// Either type
type Either<L, R> = {
map<U>(fn: (value: R) => U): Either<L, U>;
flatMap<U>(fn: (value: R) => Either<L, U>): Either<L, U>;
getOrElse(defaultValue: R): R;
isLeft: boolean;
isRight: boolean;
};
const left = <L, R>(value: L): Either<L, R> => ({
map: <U>(_: (value: R) => U) => left<L, U>(value),
flatMap: <U>(_: (value: R) => Either<L, U>) => left<L, U>(value),
getOrElse: (defaultValue: R) => defaultValue,
isLeft: true,
isRight: false,
});
const right = <L, R>(value: R): Either<L, R> => ({
map: <U>(fn: (value: R) => U) => right<L, U>(fn(value)),
flatMap: <U>(fn: (value: R) => Either<L, U>) => fn(value),
getOrElse: (_: R) => value,
isLeft: false,
isRight: true,
});
// Triple class
class Triple<T> {
constructor(public a: T, public b: T, public c: T) {}
map<U>(fn: (value: T) => U): Triple<U> {
return new Triple<U>(fn(this.a), fn(this.b), fn(this.c));
}
static of<T>(a: T, b: T, c: T): Triple<T> {
return new Triple<T>(a, b, c);
}
// Example method using Maybe and Either
divideBy(other: T): Either<string, number> {
return just(this.b)
.flatMap((numerator) =>
just(other)
.flatMap((denominator) =>
denominator !== 0 ? right(numerator / denominator) : left('Division by zero')
)
)
.getOrElse(left('Invalid input'));
}
}
// Example usage
const triple = Triple.of(1, 2, 3);
const result = triple.map((x) => x * 2);
console.log(result); // Triple { a: 2, b: 4, c: 6 }
const divisionResult = triple.divideBy(2);
console.log(divisionResult); // Either.Right { value: 1 }
const invalidDivisionResult = triple.divideBy(0);
console.log(invalidDivisionResult); // Either.Left { value: 'Division by zero' }