Skip to content
This repository has been archived by the owner on May 3, 2021. It is now read-only.

Commit

Permalink
feat: implement more taskEither and either fns
Browse files Browse the repository at this point in the history
* add stringifyJSON to either.ts
* add fromFailableTask to task_either.ts
* add fromEither to task_either.ts
* add orElse to task_either.ts
* add underived Functor to task_either.ts
* add MonadThrow to task_either.ts
* add Bifunctor to task_either.ts
* add Chain to task_either.ts
* add Extends (maybe unusable) to task_either.ts
* add pipeable bimap and mapleft to task_either.ts
  • Loading branch information
baetheus committed Oct 1, 2020
1 parent e38046a commit 89e5c14
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 4 deletions.
5 changes: 5 additions & 0 deletions either.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ export const orElse = <E, A, M>(onLeft: (e: E) => Either<M, A>) =>
ma: Either<E, A>,
): Either<M, A> => (isLeft(ma) ? onLeft(ma.left) : ma);

export const stringifyJSON = <E>(
u: unknown,
onError: (reason: unknown) => E,
): Either<E, string> => tryCatch(() => JSON.stringify(u), onError);

/***************************************************************************************************
* @section Guards
**************************************************************************************************/
Expand Down
54 changes: 50 additions & 4 deletions task_either.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type * as TC from "./type_classes.ts";
import type { _0, _1, _2, _3 } from "./hkts.ts";
import type { Lazy } from "./fns.ts";
import { Lazy, pipe } from "./fns.ts";

import * as E from "./either.ts";
import * as T from "./task.ts";
Expand All @@ -19,6 +19,7 @@ export type TaskEither<L, R> = T.Task<E.Either<L, R>>;

export const left = <E = never, A = never>(left: E): TaskEither<E, A> =>
T.of(E.left(left));

export const right = <E = never, A = never>(right: A): TaskEither<E, A> =>
T.of(E.right(right));

Expand All @@ -33,33 +34,78 @@ export const tryCatch = <E, A>(
}
};

export const fromFailableTask = <E, A>(onError: (e: unknown) => E) =>
(ta: T.Task<A>): TaskEither<E, A> =>
() => ta().then(E.right).catch((e) => E.left(onError(e)));

export const fromEither = <E, A>(ta: E.Either<E, A>): TaskEither<E, A> =>
pipe(ta, E.fold((e) => left(e), right));

export const orElse = <E, A, M>(onLeft: (e: E) => TaskEither<M, A>) =>
(ma: TaskEither<E, A>): TaskEither<M, A> =>
pipe(
ma,
T.chain(E.fold(onLeft, right)),
);

/***************************************************************************************************
* @section Modules
**************************************************************************************************/

export const Functor: TC.Functor<TaskEither<_0, _1>, 2> = {
map: (fab, ta) => () => ta().then(E.map(fab)),
};

export const Bifunctor: TC.Bifunctor<TaskEither<_0, _1>> = {
bimap: (fab, fcd, tac) => () => tac().then(E.bimap(fab, fcd)),
mapLeft: (fef, tea) => () => tea().then(E.mapLeft(fef)),
};

export const Monad = E.getEitherM(T.Monad);

export const Functor: TC.Functor<TaskEither<_0, _1>, 2> = {
map: Monad.map,
export const MonadThrow: TC.MonadThrow<TaskEither<_0, _1>, 2> = {
...Monad,
throwError: left,
};

export const Alt: TC.Alt<TaskEither<_0, _1>, 2> = ({
map: Monad.map,
alt: (ta, tb) => () => ta().then((te) => E.isLeft(te) ? tb() : te),
});

export const Applicative: TC.Applicative<TaskEither<_0, _1>, 2> = {
of: Monad.of,
ap: Monad.ap,
map: Monad.map,
map: Functor.map,
};

export const Apply: TC.Apply<TaskEither<_0, _1>, 2> = {
ap: Monad.ap,
map: Functor.map,
};

export const Chain: TC.Chain<TaskEither<_0, _1>, 2> = {
ap: Monad.ap,
map: Functor.map,
chain: Monad.chain,
};

/**
* @note Not sure if tfab is constructable in javascript..
*/
export const Extends: TC.Extend<TaskEither<_0, _1>, 2> = {
map: Functor.map,
extend: (tfab, ta) => right(tfab(ta)),
};

/***************************************************************************************************
* @section Pipeables
**************************************************************************************************/

export const { of, ap, map, join, chain } = D.createPipeableMonad(Monad);

export const { bimap, mapLeft } = D.createPipeableBifunctor(Bifunctor);

/***************************************************************************************************
* @section Sequence
**************************************************************************************************/
Expand Down

0 comments on commit 89e5c14

Please sign in to comment.