This repository has been archived by the owner on May 3, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix type only imports so deno test --coverage --unstable passes * move derivation functions into their own file derivations.ts * simplify derivation types so there is no need for duplicates * update imports in either.ts * update imports in option.ts * simplify types for getOptionM in optionT.ts and remove dups * prefix all exports in sequence.ts with _ denoting unstable * initial implementation of task adt * simplify types for typeclass law asserts and rename file to assert.ts * update tests that use typeclass asserts * implement initial task tests
- Loading branch information
Showing
14 changed files
with
353 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import type * as TC from "./type-classes.ts"; | ||
import { identity } from "./fns.ts"; | ||
|
||
/*************************************************************************************************** | ||
* @section Derivations | ||
**************************************************************************************************/ | ||
|
||
/** | ||
* Derive Monad from of, map, and join. | ||
*/ | ||
export function createMonad<T>({ | ||
of, | ||
chain, | ||
}: Pick<TC.Monad<T>, "of" | "chain">): TC.Monad<T> { | ||
const map: TC.Functor<T>["map"] = (fab, ta) => chain((a) => of(fab(a)), ta); | ||
return { | ||
of, | ||
map, | ||
chain, | ||
join: (tta) => chain(identity, tta), | ||
ap: (tfab, ta) => chain((f) => map(f, ta), tfab), | ||
}; | ||
} | ||
|
||
/** | ||
* Derive Monad2 from of, map, and join. | ||
*/ | ||
export function createMonad2<T>( | ||
M: Pick<TC.Monad2<T>, "of" | "chain"> | ||
): TC.Monad2<T> { | ||
return createMonad<T>(M as TC.Monad<T>) as TC.Monad2<T>; | ||
} | ||
|
||
/** | ||
* Derive MonadP from Monad or Monad2. | ||
*/ | ||
export const createPipeableMonad: { | ||
<T>(M: TC.Monad<T>): TC.MonadP<T>; | ||
<T>(M: TC.Monad2<T>): TC.Monad2P<T>; | ||
} = <T>({ of, ap, map, join, chain }: TC.Monad<T>): TC.MonadP<T> => ({ | ||
of, | ||
join, | ||
map: (fab) => (ta) => map(fab, ta), | ||
chain: (fatb) => (ta) => chain(fatb, ta), | ||
ap: (tfab) => (ta) => ap(tfab, ta), | ||
}); | ||
|
||
/** | ||
* Derive TraversableP from Traversable or Traversable2. | ||
*/ | ||
export const createPipeableTraversable: { | ||
<T>(M: TC.Traversable<T>): TC.TraversableP<T>; | ||
<T>(M: TC.Traversable2<T>): TC.Traversable2P<T>; | ||
} = <T>({ traverse, reduce, map }: TC.Traversable<T>): TC.TraversableP<T> => ({ | ||
map: (fab) => (ta) => map(fab, ta), | ||
reduce: (faba, a) => (ta) => reduce(faba, a, ta), | ||
traverse: (A, faub) => (ta) => traverse(A, faub, ta), | ||
}); | ||
|
||
/** | ||
* Derive BifunctorP from Bifunctor. | ||
*/ | ||
export const createPipeableBifunctor = <T>({ | ||
bimap, | ||
}: TC.Bifunctor<T>): TC.BifunctorP<T> => ({ | ||
bimap: (fab, fcd) => (tac) => bimap(fab, fcd, tac), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,22 @@ | ||
import { Monad, Monad2 } from "./type-classes.ts"; | ||
import { _ } from "./hkts.ts"; | ||
import type { Monad, Monad2 } from "./type-classes.ts"; | ||
import type { _ } 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<_>> => { | ||
export const getOptionM: { | ||
<T>(M: Monad<T>): C.MonadComposition<T, O.Option<_>>; | ||
<T>(M: Monad2<T>): C.MonadComposition2<T, O.Option<_>>; | ||
} = <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), | ||
chain: (fatob, toa) => | ||
M.chain((oa) => (O.isNone(oa) ? M.of(O.none) : fatob(oa.value)), toa), | ||
join: (FGFGa) => | ||
M.chain((GFGa) => (O.isNone(GFGa) ? M.of(O.none) : GFGa.value), FGFGa), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,57 @@ | ||
import { $, _, _0, _1 } from "./hkts.ts"; | ||
import { Apply, Apply2 } from "./type-classes.ts"; | ||
import type { $, _, _0, _1 } from "./hkts.ts"; | ||
import type { Apply, Apply2 } from "./type-classes.ts"; | ||
|
||
/** | ||
* @todo Credit gcanti or reimplemment | ||
* Sequence is not yet in its final implementation | ||
*/ | ||
|
||
function tuple<T extends ReadonlyArray<any>>(...t: T): T { | ||
function _tuple<T extends ReadonlyArray<any>>(...t: T): T { | ||
return t; | ||
} | ||
|
||
function curried(f: Function, n: number, acc: ReadonlyArray<unknown>) { | ||
function _curried(f: Function, n: number, acc: ReadonlyArray<unknown>) { | ||
return function (x: unknown) { | ||
const combined = Array(acc.length + 1); | ||
for (let i = 0; i < acc.length; i++) { | ||
combined[i] = acc[i]; | ||
} | ||
combined[acc.length] = x; | ||
return n === 0 ? f.apply(null, combined) : curried(f, n - 1, combined); | ||
return n === 0 ? f.apply(null, combined) : _curried(f, n - 1, combined); | ||
}; | ||
} | ||
|
||
const tupleConstructors: Record<number, (a: unknown) => any> = { | ||
const _tupleConstructors: Record<number, (a: unknown) => any> = { | ||
1: (a) => [a], | ||
2: (a) => (b: any) => [a, b], | ||
3: (a) => (b: any) => (c: any) => [a, b, c], | ||
4: (a) => (b: any) => (c: any) => (d: any) => [a, b, c, d], | ||
5: (a) => (b: any) => (c: any) => (d: any) => (e: any) => [a, b, c, d, e], | ||
}; | ||
|
||
function getTupleConstructor(len: number): (a: unknown) => any { | ||
if (!tupleConstructors.hasOwnProperty(len)) { | ||
tupleConstructors[len] = curried(tuple, len - 1, []); | ||
function _getTupleConstructor(len: number): (a: unknown) => any { | ||
if (!_tupleConstructors.hasOwnProperty(len)) { | ||
_tupleConstructors[len] = _curried(_tuple, len - 1, []); | ||
} | ||
return tupleConstructors[len]; | ||
return _tupleConstructors[len]; | ||
} | ||
|
||
export function sequenceTuple<T>({ map, ap }: Apply<T>) { | ||
export function _sequenceTuple<T>({ map, ap }: Apply<T>) { | ||
return <A, M extends $<T, [any]>[]>( | ||
head: $<T, [A]>, | ||
...tail: M | ||
): $< | ||
T, | ||
[[A, ...{ [K in keyof M]: M[K] extends $<T, [infer U]> ? U : never }]] | ||
> => tail.reduce(ap, map(getTupleConstructor(tail.length + 1), head)); | ||
> => tail.reduce(ap, map(_getTupleConstructor(tail.length + 1), head)); | ||
} | ||
|
||
export function sequenceTuple2<T>({ map, ap }: Apply2<T>) { | ||
export function _sequenceTuple2<T>({ map, ap }: Apply2<T>) { | ||
return <E, R, M extends $<T, [E, any]>[]>( | ||
head: $<T, [E, R]>, | ||
...tail: M | ||
): $< | ||
T, | ||
[E, [R, ...{ [K in keyof M]: M[K] extends $<T, [E, infer A]> ? A : never }]] | ||
> => tail.reduce(ap, map(getTupleConstructor(tail.length + 1), head)); | ||
> => tail.reduce(ap, map(_getTupleConstructor(tail.length + 1), head)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import type * as TC from "./type-classes.ts"; | ||
import type { _ } from "./hkts.ts"; | ||
import { createMonad, createPipeableMonad } from "./derivations.ts"; | ||
|
||
/*************************************************************************************************** | ||
* @section Types | ||
**************************************************************************************************/ | ||
|
||
export type Task<A> = () => Promise<A>; | ||
|
||
/*************************************************************************************************** | ||
* @section Constructors | ||
**************************************************************************************************/ | ||
|
||
export const of = <A>(a: A): Task<A> => () => Promise.resolve(a); | ||
|
||
/*************************************************************************************************** | ||
* @section Destructors | ||
**************************************************************************************************/ | ||
|
||
/*************************************************************************************************** | ||
* @section Combinators | ||
**************************************************************************************************/ | ||
|
||
export const delay = (ms: number) => <A>(ma: Task<A>): Task<A> => () => | ||
new Promise((resolve) => { | ||
setTimeout(() => { | ||
ma().then(resolve); | ||
}, ms); | ||
}); | ||
|
||
/*************************************************************************************************** | ||
* @section Guards | ||
**************************************************************************************************/ | ||
|
||
/*************************************************************************************************** | ||
* @section Modules | ||
**************************************************************************************************/ | ||
|
||
export const Monad = createMonad<Task<_>>({ | ||
of, | ||
chain: (fatb, ta) => () => ta().then((a) => fatb(a)()) as Promise<any>, | ||
}); | ||
|
||
export const Applicative: TC.Applicative<Task<_>> = { | ||
of, | ||
ap: Monad.ap, | ||
map: Monad.map, | ||
}; | ||
|
||
export const Apply: TC.Apply<Task<_>> = { | ||
ap: Monad.ap, | ||
map: Monad.map, | ||
}; | ||
|
||
/*************************************************************************************************** | ||
* @section Pipeables | ||
**************************************************************************************************/ | ||
|
||
export const { ap, map, join, chain } = createPipeableMonad(Monad); |
Oops, something went wrong.