Skip to content

Commit

Permalink
feat: add neither, notBoth, xEither, xNeither to Function
Browse files Browse the repository at this point in the history
  • Loading branch information
brekk committed May 6, 2024
1 parent 575adb1 commit b2972ba
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
58 changes: 58 additions & 0 deletions prelude/__internal__/Function.mad
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,19 @@ export flip = (f) => ((b, a) => f(a, b))
either :: (a -> Boolean) -> (a -> Boolean) -> a -> Boolean
export either = (predA, predB, x) => predA(x) || predB(x)


/**
* Functional "nor", given two predicates and a value, return true if neither predicate is true.
*
* @since 0.23.13
* @example
*
* neither(equals("A"), equals("B"))("B") // false
* neither(equals("A"), equals("B"))("C") // true
*/
neither :: (a -> Boolean) -> (a -> Boolean) -> a -> Boolean
export neither = (predA, predB, x) => not(either(predA, predB, x))

/**
* Functional "and", given two predicates and a value, return true if both predicates are true.
*
Expand All @@ -168,3 +181,48 @@ export either = (predA, predB, x) => predA(x) || predB(x)
*/
both :: (a -> Boolean) -> (a -> Boolean) -> a -> Boolean
export both = (predA, predB, x) => predA(x) && predB(x)


/**
* Functional "nand", given two predicates and a value, return true if either predicates are true, but not both.
*
* @since 0.23.13
* @example
*
* import {lt} from "Compare"
* // as `lt` applies arguments backwards, 70 is greater than both 50 and 60
* notBoth(lt(50), lt(60))(70) // false
* notBoth(lt(50), lt(60))(55) // true
*/
notBoth :: (a -> Boolean) -> (a -> Boolean) -> a -> Boolean
export notBoth = (predA, predB, x) => not(both(predA, predB, x))

/**
* Functional "xor", given two predicates and a value, return true if either predicate is true, but not both, nor neither.
*
* @since 0.23.13
* @example
*
* import {lt} from "Compare"
* // as `lt` applies arguments backwards, 70 is greater than both 50 and 60
* xEither(lt(50), lt(60))(70) // false
* xEither(lt(50), lt(60))(40) // false
* xEither(lt(50), lt(60))(55) // true
*/
xEither :: (a -> Boolean) -> (a -> Boolean) -> a -> Boolean
export xEither = (predA, predB, x) => predA(x) != predB(x)

/**
* Functional "xnor", given two predicates and a value, return false if either predicate is false, but not both, nor neither.
*
* @since 0.13.0
* @example
*
* import {lt} from "Compare"
* // as `lt` applies arguments backwards, 70 is greater than both 50 and 60
* xEither(lt(50), lt(60))(70) // true
* xEither(lt(50), lt(60))(40) // true
* xEither(lt(50), lt(60))(55) // false
*/
xNeither :: (a -> Boolean) -> (a -> Boolean) -> a -> Boolean
export xNeither = (predA, predB, x) => not(xEither(predA, predB, x))
45 changes: 45 additions & 0 deletions prelude/__internal__/Function.spec.mad
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ import {
flip,
identity,
ifElse,
neither,
not,
notBoth,
notEquals,
tailRec,
unless,
when,
xEither,
xNeither,
} from "./Function"


Expand All @@ -43,11 +47,15 @@ import {
flip,
identity,
ifElse,
neither,
not,
notBoth,
notEquals,
tailRec,
unless,
when,
xEither,
xNeither,
} from "./Function"


Expand Down Expand Up @@ -199,3 +207,40 @@ test(
test("unless - true", () => assertEquals(unless(equals(5), (x) => x * 2, 5), 5))

test("unless - false", () => assertEquals(unless(equals(5), (x) => x * 2, 10), 20))

test(
"notBoth",
() => do {
_ <- assertEquals(notBoth(lt(50), lt(60))(70), false)
return assertEquals(notBoth(lt(50), lt(60))(55), true)
},
)

test(
"neither",
() => do {
notAB = neither(equals("A"), equals("B"))
_ <- assertEquals(notAB("A"), false)
_ <- assertEquals(notAB("B"), false)
return assertEquals(notAB("C"), true)
},
)

test(
"xEither",
() => do {
sclusy = xEither(lt(50), lt(60))
_ <- assertEquals(sclusy(70), false)
_ <- assertEquals(sclusy(30), false)
return assertEquals(sclusy(55), true)
},
)

test(
"xNeither",
() => do {
_ <- assertEquals(xNeither(lt(50), lt(60))(70), true)
_ <- assertEquals(xNeither(lt(50), lt(60))(30), true)
return assertEquals(xNeither(lt(50), lt(60))(55), false)
},
)

0 comments on commit b2972ba

Please sign in to comment.