Compare commits

..

No commits in common. "e696e5d9d2a9c675033002912ab2092ef9a90add" and "83a0c1cf31ee711be673637de1a792dee9941313" have entirely different histories.

3 changed files with 12 additions and 82 deletions

View File

@ -14,55 +14,15 @@ export const right = <A>(a: A): Either<A, never> => ({
// Operations // Operations
export const eitherMap = export const eitherMap =
<A, B, E>(f: (a: A) => B) => (fa: Either<A, E>): Either<B, E> => <E, A, B>(f: (a: A) => B) => (fa: Either<A, E>): Either<B, E> =>
fa._tag === 'Right' ? right(f(fa.right)) : fa fa._tag === 'Right' ? right(f(fa.right)) : fa
export const eitherChain = export const eitherChain =
<A, B, E>(f: (a: A) => Either<B, E>) => (fa: Either<A, E>): Either<B, E> => <E, A, B>(f: (a: A) => Either<B, E>) =>
(fa: Either<A, E>): Either<B, E> =>
fa._tag === 'Right' ? f(fa.right) : fa fa._tag === 'Right' ? f(fa.right) : fa
export const fold = export const fold =
<A, B, E>(onLeft: (e: E) => B, onRight: (a: A) => B) => <A, B, E>(onLeft: (e: E) => B, onRight: (a: A) => B) =>
(fa: Either<A, E>): B => (fa: Either<A, E>): B =>
fa._tag === 'Left' ? onLeft(fa.left) : onRight(fa.right) fa._tag === 'Left' ? onLeft(fa.left) : onRight(fa.right)
// Do notation
export class DoEither<T extends Record<string, unknown>, E> {
constructor(private readonly either: Either<T, E>) {}
bind<K extends string, A>(
key: K,
fa: Either<A, E>,
): DoEither<T & Record<K, A>, E> {
const newEither = eitherChain<T, T & Record<K, A>, E>((scope: T) =>
eitherMap<A, T & Record<K, A>, E>((a: A) => ({...scope, [key]: a}))(fa)
)(this.either)
return new DoEither(newEither)
}
return<B>(f: (scope: T) => B): Either<B, E> {
return eitherMap<T, B, E>(f)(this.either)
}
done(): Either<T, E> {
return this.either
}
do(fa: Either<unknown, E>): DoEither<T, E> {
const newEither = eitherChain<T, T, E>((scope: T) =>
eitherMap<unknown, T, E>(() => scope)(fa)
)(this.either)
return new DoEither(newEither)
}
doL(f: (scope: T) => Either<unknown, E>): DoEither<T, E> {
const newEither = eitherChain<T, T, E>((scope: T) =>
eitherMap<unknown, T, E>(() => scope)(f(scope))
)(this.either)
return new DoEither(newEither)
}
static start<E>(): DoEither<{}, E> {
return new DoEither(right({}))
}
}

View File

@ -10,8 +10,9 @@ export const some = <A>(value: A): Option<A> => ({
}) })
// Operations // Operations
export const map = <A, B>(f: (a: A) => B) => (fa: Option<A>): Option<B> => export const map =
fa._tag === 'Some' ? some(f(fa.value)) : none <A, B>(f: (a: A) => B) => (fa: Option<A>): Option<B> =>
fa._tag === 'Some' ? some(f(fa.value)) : none
export const chain = export const chain =
<A, B>(f: (a: A) => Option<B>) => (fa: Option<A>): Option<B> => <A, B>(f: (a: A) => Option<B>) => (fa: Option<A>): Option<B> =>
@ -19,37 +20,3 @@ export const chain =
export const getOrElse = <A>(defaultValue: A) => (fa: Option<A>): A => export const getOrElse = <A>(defaultValue: A) => (fa: Option<A>): A =>
fa._tag === 'Some' ? fa.value : defaultValue fa._tag === 'Some' ? fa.value : defaultValue
export class DoOption<T extends Record<string, unknown>> {
constructor(private readonly option: Option<T>) {}
bind<K extends string, A>(key: K, fa: Option<A>): DoOption<T & Record<K, A>> {
const newOption = chain((scope: T) =>
map((a: A) => ({...scope, [key]: a}))(fa)
)(this.option)
return new DoOption(newOption as Option<T & Record<K, A>>)
}
return<B>(f: (scope: T) => B): Option<B> {
return map(f)(this.option)
}
done(): Option<T> {
return this.option
}
do(fa: Option<unknown>): DoOption<T> {
const newOption = chain((scope: T) => map(() => scope)(fa))(this.option)
return new DoOption(newOption)
}
doL(f: (scope: T) => Option<unknown>): DoOption<T> {
const newOption = chain((scope: T) => map(() => scope)(f(scope)))(
this.option,
)
return new DoOption(newOption)
}
static start(): DoOption<{}> {
return new DoOption(some({}))
}
}

View File

@ -2,11 +2,14 @@ import { type Either, left, right } from './either'
import { none, type Option, some } from './option' import { none, type Option, some } from './option'
// Pipe function for composition // Pipe function for composition
export const pipe = <A, B, C>(a: A, ab: (a: A) => B, bc: (b: B) => C): C => export const pipe = <A, B, C>(
bc(ab(a)) a: A,
ab: (a: A) => B,
bc: (b: B) => C,
): C => bc(ab(a))
// TryCatch helper using Either // TryCatch helper using Either
export const tryCatch = <A>(f: () => A): Either<A, Error> => { export const tryCatch = <A>(f: () => A): Either<Error, A> => {
try { try {
return right(f()) return right(f())
} catch (e) { } catch (e) {