diff --git a/task.ts b/task.ts
index 8a2e4a1..4b71f97 100644
--- a/task.ts
+++ b/task.ts
@@ -2,7 +2,7 @@ import type * as HKT from "./hkt.ts";
import type * as TC from "./type_classes.ts";
import { Lazy } from "./types.ts";
-import { apply, flow, wait } from "./fns.ts";
+import { apply, flow, wait, identity } from "./fns.ts";
import { createDo } from "./derivations.ts";
/*******************************************************************************
@@ -30,6 +30,8 @@ declare module "./hkt.ts" {
* Combinators
******************************************************************************/
+export const make = (a: A): Task => () => Promise.resolve(a);
+
export const delay = (ms: number) =>
(ma: Task): Task => () => wait(ms).then(ma);
@@ -75,7 +77,7 @@ export const Monad: TC.Monad = {
of: Applicative.of,
ap: Apply.ap,
map: Functor.map,
- join: (tta) => () => tta().then(apply()),
+ join: Chain.chain(identity),
chain: Chain.chain,
};
@@ -92,7 +94,7 @@ export const MonadSeq: TC.Monad = {
of: Applicative.of,
ap: ApplySeq.ap,
map: Functor.map,
- join: (tta) => () => tta().then(apply()),
+ join: Chain.chain(identity),
chain: Chain.chain,
};
@@ -102,6 +104,8 @@ export const MonadSeq: TC.Monad = {
export const { of, ap, map, join, chain } = Monad;
+export const { ap: apSeq } = ApplySeq;
+
/*******************************************************************************
* Do Notation
******************************************************************************/
diff --git a/testing/task.test.ts b/testing/task.test.ts
new file mode 100644
index 0000000..9c0d604
--- /dev/null
+++ b/testing/task.test.ts
@@ -0,0 +1,69 @@
+import { assertEquals } from "https://deno.land/std/testing/asserts.ts";
+
+import * as T from "../task.ts";
+import { _, pipe } from "../fns.ts";
+
+import * as AS from "./assert.ts";
+
+const assertEqualsT = async (a: T.Task, b: T.Task) =>
+ assertEquals(await a(), await b());
+
+Deno.test("Task make", async () => {
+ await assertEqualsT(T.make(0), T.make(0));
+});
+
+Deno.test("Task delay", async () => {
+ await assertEqualsT(pipe(T.make(0), T.delay(200)), T.make(0));
+});
+
+Deno.test("Task fromThunk", async () => {
+ await assertEqualsT(T.fromThunk(() => 0), T.make(0));
+});
+
+Deno.test("Task tryCatch", async () => {
+ await assertEqualsT(T.tryCatch(_, () => 0), T.make(0));
+ await assertEqualsT(T.tryCatch(() => 1, () => 0), T.make(1));
+});
+
+Deno.test("Task of", async () => {
+ await assertEqualsT(T.of(1), T.make(1));
+});
+
+Deno.test("Task ap", async () => {
+ await assertEqualsT(pipe(T.of(1), T.ap(T.of(AS.add))), T.of(2));
+});
+
+Deno.test("Task map", async () => {
+ await assertEqualsT(pipe(T.of(1), T.map(AS.add)), T.of(2));
+});
+
+Deno.test("Task join", async () => {
+ await assertEqualsT(T.join(T.of(T.of(1))), T.of(1));
+});
+
+Deno.test("Task chain", async () => {
+ await assertEqualsT(pipe(T.of(1), T.chain((n) => T.of(n + 1))), T.of(2));
+});
+
+Deno.test("Task apSeq", async () => {
+ await assertEqualsT(pipe(T.of(1), T.apSeq(T.of(AS.add))), T.of(2));
+});
+
+Deno.test("Task Do, bind, bindTo", () => {
+ assertEqualsT(
+ pipe(
+ T.Do(),
+ T.bind("one", () => T.make(1)),
+ T.bind("two", ({ one }) => T.make(one + one)),
+ T.map(({ one, two }) => one + two),
+ ),
+ T.make(3),
+ );
+ assertEqualsT(
+ pipe(
+ T.make(1),
+ T.bindTo("one"),
+ ),
+ T.make({ one: 1 }),
+ );
+});