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

Commit

Permalink
feat: add initial tests for datum and reader
Browse files Browse the repository at this point in the history
  • Loading branch information
baetheus committed Sep 18, 2020
1 parent fb532bb commit 499a778
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 1 deletion.
64 changes: 64 additions & 0 deletions testing/datum.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";

import { assertMonad } from "./assert.ts";
import { constant } from "../fns.ts";
import * as D from "../datum.ts";

const add = (a: number, b: number) => a + b;
const addOne = (n: number): number => n + 1;
const one = constant(1);

Deno.test({
name: "Datum Constructors",
fn(): void {
assertEquals(D.replete(1), { tag: "Replete", value: 1 });
assertEquals(D.initial, { tag: "Initial" });
},
});

Deno.test({
name: "Datum Destructors",
fn(): void {
const fold = D.fold(one, one, addOne, addOne);

assertEquals(fold(D.replete(1)), 2);
assertEquals(fold(D.initial), 1);
},
});

Deno.test({
name: "Datum Guards",
fn(): void {
assertEquals(D.isSome(D.initial), false);
assertEquals(D.isSome(D.replete(1)), true);
assertEquals(D.isNone(D.initial), true);
assertEquals(D.isNone(D.replete(1)), false);
},
});

Deno.test({
name: "Datum Instances",
fn(): void {
// Test Laws
assertMonad(D.Monad, "Datum");

// Monad Join
const { join } = D.Monad;

assertEquals(join(D.replete(D.replete(1))), D.replete(1));
assertEquals(join(D.replete(D.initial)), D.initial);
assertEquals(join(D.initial), D.initial);

// Foldable
const { reduce } = D.Foldable;
assertEquals(reduce(add, 0, D.replete(1)), 1);
assertEquals(reduce(add, 0, D.initial), 0);

// Traversable
const { traverse } = D.Traversable;
assertEquals(
traverse(D.Applicative, (_) => D.replete(1), D.initial),
D.replete(D.initial)
);
},
});
1 change: 1 addition & 0 deletions testing/derivations.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";

import type { _ } from "../hkts.ts";

import * as O from "../option.ts";
import { createMonad } from "../derivations.ts";

Expand Down
103 changes: 103 additions & 0 deletions testing/reader.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";

import * as R from "../reader.ts";

const fab = (n: number) => n + 1;
const fbc = (n: number): string => n.toString();
const fgab = (f: typeof fbc) => (g: typeof fab) => (n: number) => f(g(n));

Deno.test({
name: "Reader Instances",
fn(): void {
const M = R.Monad;

const fatb = (n: number) => M.of<number, number>(n + 1);
const fbtc = (n: number) => M.of<number, string>(n.toString());

const famb = (n: number) => (n < 0 ? M.of(0) : M.of<number, number>(n));
const fbmc = (n: number) => M.of<number, string>(n.toString());

// Test Laws
// Apply Composition: A.ap(A.ap(A.map(f => g => x => f(g(x)), a), u), v) ≡ A.ap(a, A.ap(u, v))
assertEquals(
M.ap(M.ap(M.map(fgab, M.of(fbc)), M.of(fab)), M.of(1))(1),
M.ap(M.of(fbc), M.ap(M.of(fab), M.of(1)))(1),
`Reader : Apply Composition`
);

// Functor Identity: F.map(x => x, a) ≡ a
assertEquals(
M.map((n: number) => n, M.of(1))(1),
M.of(1)(1),
`Reader : Functor Identity`
);

// Functor Composition: F.map(x => f(g(x)), a) ≡ F.map(f, F.map(g, a))
assertEquals(
M.map((x: number) => fbc(fab(x)), M.of(1))(1),
M.map(fbc, M.map(fab, M.of(1)))(1),
`Reader : Functor Composition`
);

// Applicative Identity: A.ap(A.of(x => x), v) ≡ v
assertEquals(
M.ap(
M.of((n: number) => n),
M.of(1)
)(1),
M.of(1)(1),
`Reader : Applicative Identity`
);

// Applicative Homomorphism: M.ap(A.of(f), A.of(x)) ≡ A.of(f(x))
assertEquals(
M.ap(M.of(fab), M.of(1))(1),
M.of(fab(1))(1),
`Reader : Applicative Homomorphism`
);

// Applicative Interchange: A.ap(u, A.of(y)) ≡ A.ap(A.of(f => f(y)), u)
assertEquals(
M.ap(M.of(fab), M.of(2))(1),
M.ap(
M.of((f: typeof fab) => f(2)),
M.of(fab)
)(1),
`Reader : Applicative Interchange`
);

// Chain Associativity: M.chain(g, M.chain(f, u)) ≡ M.chain(x => M.chain(g, f(x)), u)
assertEquals(
M.chain(fbtc, M.chain(fatb, M.of(1)))(1),
M.chain((x) => M.chain(fbtc, fatb(x)), M.of<number, number>(1))(1),
`Reader : Chain Associativity`
);

// Monad Left Identity: M.chain(f, M.of(a)) ≡ f(a)
assertEquals(
M.chain(famb, M.of(1))(1),
famb(1)(1),
`Reader : Monad Left Identity`
);

// Monad Right Identity: M.chain(M.of, u) ≡ u
assertEquals(
M.chain(M.of, M.of<number, number>(1))(1),
M.of(1)(1),
`Reader : Monad Right Identity`
);

// Monad Associativity: M.chain(b => Mc, M.chain(a => Mb, Ma)) === M.chain(a => M.chain(b => Mc, (a => Mb)(a)), Ma)
assertEquals(
M.chain(fbmc, M.chain(famb, M.of(1)))(1),
M.chain((a) => M.chain(fbmc, famb(a)), M.of<number, number>(1))(1),
`Reader : Monad Associativity 1`
);

assertEquals(
M.chain(fbmc, M.chain(famb, M.of(-1)))(1),
M.chain((a) => M.chain(fbmc, famb(a)), M.of<number, number>(-1))(1),
`Reader : Monad Associativity 2`
);
},
});
2 changes: 1 addition & 1 deletion type_classes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Predicate } from "./fns.ts";
import type { Predicate } from "./fns.ts";
import type { $ } from "./hkts.ts";

/***************************************************************************************************
Expand Down

0 comments on commit 499a778

Please sign in to comment.