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

Commit

Permalink
feat: initial work with monad transformers
Browse files Browse the repository at this point in the history
* simple implementation of optionT getOptionM and getOptionM2
  • Loading branch information
baetheus committed Sep 12, 2020
1 parent fad661f commit cd8ceaf
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 4 deletions.
154 changes: 154 additions & 0 deletions composition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { $ } from "./hkts.ts";
import * as TC from "./type-classes.ts";

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

/**
* Functor Composition
*/
export type FunctorComposition<F, G> = {
map: <A, B>(fab: (a: A) => B, FGa: $<F, [$<G, [A]>]>) => $<F, [$<G, [B]>]>;
};

export type FunctorComposition2<F, G> = {
map: <E, A, B>(
fab: (a: A) => B,
FGa: $<F, [E, $<G, [A]>]>
) => $<F, [E, $<G, [B]>]>;
};

/**
* Apply Composition
*/
export type ApplyComposition<F, G> = FunctorComposition<F, G> & {
ap: <A, B>(
FGfab: $<F, [$<G, [(a: A) => B]>]>,
FGa: $<F, [$<G, [A]>]>
) => $<F, [$<G, [B]>]>;
};

export type ApplyComposition2<F, G> = FunctorComposition2<F, G> & {
ap: <E, A, B>(
FGefab: $<F, [E, $<G, [(a: A) => B]>]>,
FGea: $<F, [E, $<G, [A]>]>
) => $<F, [E, $<G, [B]>]>;
};

/**
* Applicative Composition
*/
export type ApplicativeComposition<F, G> = ApplyComposition<F, G> & {
of: <A>(a: A) => $<F, [$<G, [A]>]>;
};

export type ApplicativeComposition2<F, G> = ApplyComposition2<F, G> & {
of: <E, A>(a: A) => $<F, [E, $<G, [A]>]>;
};

/**
* Chain Composition
* I'm not sure creating this composition generally is possible, see:
* @todo http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf
*/
export type ChainComposition<F, G> = ApplyComposition<F, G> & {
chain: <A, B>(
faFGb: (a: A) => $<F, [$<G, [B]>]>,
FGa: $<F, [$<G, [A]>]>
) => $<F, [$<G, [B]>]>;
};

export type ChainComposition2<F, G> = ApplyComposition2<F, G> & {
chain: <E, A, B>(
faFGeb: (a: A) => $<F, [E, $<G, [B]>]>,
FGa: $<F, [E, $<G, [A]>]>
) => $<F, [E, $<G, [B]>]>;
};

/**
* Monad Composition
* I'm not sure creating this composition generally is possible, see:
* @todo http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf
*/
export type MonadComposition<F, G> = ApplicativeComposition<F, G> &
ChainComposition<F, G> & {
join: <A>(FGFGa: $<F, [$<G, [$<F, [$<G, [A]>]>]>]>) => $<F, [$<G, [A]>]>;
};

export type MonadComposition2<F, G> = ApplicativeComposition2<F, G> &
ChainComposition2<F, G> & {
join: <E, A>(
FGFGea: $<F, [E, $<G, [$<F, [E, $<G, [A]>]>]>]>
) => $<F, [E, $<G, [A]>]>;
};

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

/**
* Functor
*/
export const getFunctorComposition = <F, G>(
F: TC.Functor<F>,
G: TC.Functor<G>
): FunctorComposition<F, G> => ({
map: (fab, FGa) => F.map((Ga) => G.map(fab, Ga), FGa),
});

export const getFunctor2Composition = <F, G>(
F: TC.Functor2<F>,
G: TC.Functor<G>
): FunctorComposition2<F, G> => ({
map: (fab, fga) => F.map((ga) => G.map(fab, ga), fga),
});

/**
* Apply
*/
export const getApplyComposition = <F, G>(
F: TC.Apply<F>,
G: TC.Apply<G>
): ApplyComposition<F, G> => ({
...getFunctorComposition(F, G),
ap: <A, B>(FGfab: $<F, [$<G, [(a: A) => B]>]>, FGfa: $<F, [$<G, [A]>]>) =>
F.ap(
F.map((h) => (ga: $<G, [A]>) => G.ap(h, ga), FGfab),
FGfa
),
});

export const getApply2Composition = <F, G>(
F: TC.Apply2<F>,
G: TC.Apply<G>
): ApplyComposition2<F, G> => ({
...getFunctor2Composition(F, G),
ap: <E, A, B>(
FGfab: $<F, [E, $<G, [(a: A) => B]>]>,
FGfa: $<F, [E, $<G, [A]>]>
) =>
F.ap(
F.map((h) => (ga: $<G, [A]>) => G.ap(h, ga), FGfab),
FGfa
),
});

/**
* Applicative
*/
export const getApplicativeComposition = <F, G>(
F: TC.Applicative<F>,
G: TC.Applicative<G>
): ApplicativeComposition<F, G> => ({
...getApplyComposition(F, G),
of: (a) => F.of(G.of(a)),
});

export const getApplicative2Composition = <F, G>(
F: TC.Applicative2<F>,
G: TC.Applicative<G>
): ApplicativeComposition2<F, G> => ({
...getApply2Composition(F, G),
of: (a) => F.of(G.of(a)),
});
37 changes: 37 additions & 0 deletions optionT.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Monad, Monad2 } from "./type-classes.ts";
import { _ } from "./hkts.ts";
import * as O from "./option.ts";
import * as C from "./composition.ts";

export const getOptionM = <T>(
M: Monad<T>
): C.MonadComposition<T, O.Option<_>> => {
const { of, ap, map } = C.getApplicativeComposition(M, O.Applicative);

const chain: C.MonadComposition<T, O.Option<_>>["chain"] = (fatob, toa) =>
M.chain((oa) => (O.isNone(oa) ? M.of(O.none) : fatob(oa.value)), toa);

return {
of,
ap,
map,
chain,
join: (FGFGa) => chain((x) => x, FGFGa),
};
};

export const getOptionM2 = <T>(
M: Monad2<T>
): C.MonadComposition2<T, O.Option<_>> => {
const { of, ap, map } = C.getApplicative2Composition(M, O.Applicative);
const chain: C.MonadComposition2<T, O.Option<_>>["chain"] = (fatob, toa) =>
M.chain((oa) => (O.isNone(oa) ? M.of(O.none) : fatob(oa.value)), toa);

return {
of,
ap,
map,
chain,
join: (FGFGa) => chain((x) => x, FGFGa),
};
};
4 changes: 0 additions & 4 deletions type-classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,6 @@ export type Traversable2P<T> = Functor2P<T> &
) => (ta: $<T, [E, A]>) => $<U, [$<T, [E, B]>]>;
};

/***************************************************************************************************
* @section Composition
**************************************************************************************************/

/***************************************************************************************************
* @section Derivations
**************************************************************************************************/
Expand Down

0 comments on commit cd8ceaf

Please sign in to comment.