Skip to content

Commit da5fdfb

Browse files
authored
feat(integers): add more operations (#6)
* feat(integers): add more operations * test(decode): separate test file * test(integer): increase coverage to 100% * test(natural-number): add missing tests * test(decode): modify description * test(list-operations): separate file for tests * feat(integer): more operations * test(integer): fix tests
1 parent cd33f15 commit da5fdfb

9 files changed

Lines changed: 725 additions & 308 deletions

lib/integer.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { NOT, IF, OR } from './boolean';
1+
import { NOT, IF, OR, AND, T, F } from './boolean';
22
import {
33
zeroNat,
44
isZeroNat,
@@ -8,7 +8,8 @@ import {
88
isEqualNat,
99
mulNat,
1010
modNat,
11-
expNat
11+
expNat,
12+
isLessThanNat
1213
} from './natural-number';
1314

1415
export const pair = (a, b) => selector => selector(a, b);
@@ -52,7 +53,22 @@ export const mul = (a, b) =>
5253
);
5354
export const exp = (pow, int) =>
5455
IF(
55-
isZeroNat(modNat(pow, inc(inc(zero)))),
56-
() => pair(expNat(pow, abs(int)), zeroNat),
57-
() => pair(zeroNat, expNat(pow, abs(int)))
56+
isZeroNat(modNat(abs(pow), incNat(incNat(zeroNat)))),
57+
() => pair(expNat(abs(pow), abs(int)), zeroNat),
58+
() => pair(zeroNat, expNat(abs(pow), abs(int)))
5859
)();
60+
export const isNegative = a => NOT(isZeroNat(second(normalize(a))));
61+
export const isLessThan = (a, b) =>
62+
IF(
63+
OR(AND(isNegative(a), isNegative(b)), AND(NOT(isNegative(a)), NOT(isNegative(b)))),
64+
() =>
65+
IF(
66+
AND(isNegative(a), isNegative(b)),
67+
() => NOT(isLessThanNat(abs(a), abs(b))),
68+
() => isLessThanNat(abs(a), abs(b))
69+
)(),
70+
() => IF(isNegative(a), () => T, () => F)()
71+
)();
72+
export const isLessThanEqual = (a, b) => OR(isLessThan(a, b), isEqual(a, b));
73+
export const isGreaterThan = (a, b) => isLessThan(b, a);
74+
export const isGreaterThanEqual = (a, b) => isLessThanEqual(b, a);

lib/natural-number.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const isEqualNat = (a, b) =>
1616
export const mulNat = (a, b) =>
1717
IF(isZeroNat(b), () => zeroNat, () => addNat(a, mulNat(a, decNat(b))))();
1818
export const expNat = (pow, num) =>
19-
IF(isZeroNat(pow), () => incNat(zeroNat), () => mulNat(num, expNat(decNat(num), num)));
19+
IF(isZeroNat(pow), () => incNat(zeroNat), () => mulNat(num, expNat(decNat(pow), num)))();
2020
export const isLessThanNat = (a, b) =>
2121
IF(
2222
AND(isZeroNat(a), isZeroNat(b)),

test/boolean.test.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { T, F, IF, AND, OR, NOT } from '../lib';
2+
3+
describe('Church Encoding for Booleans', () => {
4+
describe('T', () => {
5+
it('is a function', () => {
6+
expect(T).toBeFunction();
7+
});
8+
it('evaluates the left branch', () => {
9+
expect(T(true, false)).toBeTrue();
10+
});
11+
});
12+
13+
describe('F', () => {
14+
it('is a function', () => {
15+
expect(F).toBeFunction();
16+
});
17+
it('evaluates the right branch', () => {
18+
expect(F(true, false)).toBeFalse();
19+
});
20+
});
21+
22+
describe('IF', () => {
23+
it('is a function', () => {
24+
expect(IF).toBeFunction();
25+
});
26+
it('evalutes the predicate with the left and right branches', () => {
27+
expect(IF(T, true, false)).toBeTrue();
28+
});
29+
});
30+
31+
describe('AND', () => {
32+
it('is a function', () => {
33+
expect(AND).toBeFunction();
34+
});
35+
it('returns true if both values are true, false otherwise', () => {
36+
expect(IF(AND(T, F), true, false)).toBeFalse();
37+
expect(IF(AND(F, T), true, false)).toBeFalse();
38+
expect(IF(AND(T, T), true, false)).toBeTrue();
39+
});
40+
});
41+
42+
describe('OR', () => {
43+
it('is a function', () => {
44+
expect(OR).toBeFunction();
45+
});
46+
it('returns true if either value is true, false otherwise', () => {
47+
expect(IF(OR(T, F), true, false)).toBeTrue();
48+
expect(IF(OR(F, T), true, false)).toBeTrue();
49+
expect(IF(OR(T, T), true, false)).toBeTrue();
50+
expect(IF(OR(F, F), true, false)).toBeFalse();
51+
});
52+
});
53+
54+
describe('NOT', () => {
55+
it('is a function', () => {
56+
expect(NOT).toBeFunction();
57+
});
58+
it('negates the value', () => {
59+
expect(IF(NOT(T), true, false)).toBeFalse();
60+
expect(IF(NOT(F), true, false)).toBeTrue();
61+
expect(IF(NOT(AND(T, F)), true, false)).toBeTrue();
62+
});
63+
});
64+
});

0 commit comments

Comments
 (0)