Skip to content

Commit

Permalink
feat: caseof can pattern match strings and numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
ritesh404 committed Jan 16, 2021
1 parent c8cff5a commit 4628d35
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 18 deletions.
6 changes: 4 additions & 2 deletions src/adt/Either/either.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,15 @@ test("Either", t => {

caseOf(
{
Right: v => t.equal(v, 1, "successful Right pattern match")
Right: v => t.equal(v, 1, "successful Right pattern match"),
Left: x => x
},
a
);
caseOf(
{
Left: v => t.equal(v, 1, "successful Left pattern match")
Left: v => t.equal(v, 1, "successful Left pattern match"),
Right: x => x
},
e
);
Expand Down
6 changes: 4 additions & 2 deletions src/adt/Either/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ class Left<A, B> extends Either<A, B> {
return `Left(${this.getValue()})`;
}

public caseOf(o: { Left: Function }) {
public caseOf(o: { Left: Function; Right: Function }) {
if (!o.Right) throw new Error("Either: case for Right missing");
if (o.Left) return o.Left(this.getValue());
else throw Error("Either: Expected Left!");
}
Expand Down Expand Up @@ -210,7 +211,8 @@ class Right<A, B> extends Either<A, B> {
return `Right(${this.getValue()})`;
}

public caseOf(o: { Right: Function }) {
public caseOf(o: { Right: Function; Left: Function }) {
if (!o.Left) throw new Error("Either: case for Left missing");
if (o.Right) return o.Right(this.getValue());
else throw Error("Either: Expected Right");
}
Expand Down
6 changes: 4 additions & 2 deletions src/adt/Maybe/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ export class Nothing<A> extends Maybe<A> {
return "Nothing()";
}

public caseOf(o: { Nothing: Function }) {
public caseOf(o: { Nothing: Function; Just: Function }) {
if (!o.Just) throw new Error("Maybe: case for Just missing");
if (o.Nothing) return o.Nothing();
else throw Error("Maybe: Expected Nothing!");
}
Expand Down Expand Up @@ -172,7 +173,8 @@ export class Just<A> extends Maybe<A> {
return `Just(${this.getValue()})`;
}

public caseOf(o: { Just: Function }) {
public caseOf(o: { Just: Function; Nothing: Function }) {
if (!o.Nothing) throw new Error("Maybe: case for Nothing missing");
if (o.Just) return o.Just(this.getValue());
else throw Error("Maybe: Expected Just");
}
Expand Down
6 changes: 4 additions & 2 deletions src/adt/Maybe/maybe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,15 @@ test("Maybe", t => {

caseOf(
{
Just: v => t.equal(v, 1, "successful Just pattern match")
Just: v => t.equal(v, 1, "successful Just pattern match"),
Nothing: x => x
},
a
);
caseOf(
{
Nothing: v => t.notOk(v, "successful Nothing pattern match")
Nothing: v => t.notOk(v, "successful Nothing pattern match"),
Just: x => x
},
e
);
Expand Down
36 changes: 36 additions & 0 deletions src/function/caseOf/caseof.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as test from "tape";
import caseOf from "./";

import Either from "../../adt/Either";

test("caseOf", t => {
const e1 = Either.of(1);
t.equals(
caseOf({ Right: v => v + 1, Left: x => x }, e1),
2,
"pattern match"
);
t.throws(
() => caseOf({ Right: v => v + 1, Left: x => x }, "hello"),
"pattern match fail"
);
t.equals(
caseOf({ string: x => x, _: x => x }, "string"),
"string",
"pattern match strings"
);
t.equals(
caseOf({ string: x => x, _: x => x }, 1),
1,
"pattern match numbers"
);
t.throws(
() => caseOf({ str: x => x }, "hello"),
"Must provide default case for strings"
);
t.throws(
() => caseOf({ 5: x => x }, 1),
"Must provide default case for numbers"
);
t.end();
});
17 changes: 14 additions & 3 deletions src/function/caseOf/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@ import PatternMatch from "../../interface/Patternmatch";
import curry from "../curry";
import isFunction from "../isFunction";

function caseOf(o: { [k: string]: (a: any) => any }, p: PatternMatch): any {
if (isFunction(p.caseOf)) return p.caseOf(o);
else throw Error("Unable to pattern match");
function caseOf(
o: { [k: string]: (a: any) => any },
p: PatternMatch | string | number
): any {
if (typeof p === "string" || p instanceof String || typeof p === "number") {
if (!o._ && !o.default) throw Error("caseOf: Default case missing");
else {
// @ts-ignore
if (o[p]) return o[p](p);
if (o._) return o._(p);
if (o.default) return o.default(p);
}
} else if (isFunction(p.caseOf)) return p.caseOf(o);
else throw Error("caseOf: Unable to pattern match");
}
export default curry(caseOf);
7 changes: 0 additions & 7 deletions src/function/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import bimap from "./bimap";
import chain from "./chain";
import constant from "./constant";
import compose from "./compose";
import caseOf from "./caseOf";
import curry from "./curry";
import Either from "../adt/Either";
import fmap from "./fmap";
Expand Down Expand Up @@ -128,12 +127,6 @@ test("Helpers", t => {
"compose return the same result as calling the functions individually"
);

t.equals(caseOf({ Right: v => v + 1 }, e1), 2, "pattern match");
t.throws(
() => caseOf({ Right: v => v + 1 }, "hello"),
"pattern match fail"
);

t.throws(() => liftAn(1, [e1]), "liftAn expects a function");
t.throws(() => liftAn(add2, []), "liftAn expects a Array of Apply");
t.equals(unwrap(liftAn(add2, [e1])), 3, "liftAn");
Expand Down

0 comments on commit 4628d35

Please sign in to comment.