├── .circleci
└── config.yml
├── .config
├── .eslintrc.json
├── .github
├── CONTRIBUTING.md
└── FUNDING.yml
├── .gitignore
├── .npmrc
├── LICENSE
├── README.md
├── dist
└── bundle.js
├── index.js
├── package.json
├── scripts
├── .eslintrc.json
├── bundle
├── generate-readme
├── lint
└── prepublish
└── test
├── .eslintrc.json
├── I.js
├── Just.js
├── K.js
├── Left.js
├── NODE_ENV.js
├── Nothing.js
├── Pair.js
├── Right.js
├── T.js
├── add.js
├── all.js
├── alt.js
├── and.js
├── any.js
├── ap.js
├── apFirst.js
├── apSecond.js
├── append.js
├── array.js
├── bimap.js
├── boolean.js
├── chain.js
├── chainRec.js
├── clamp.js
├── complement.js
├── compose.js
├── concat.js
├── contramap.js
├── create.js
├── div.js
├── drop.js
├── dropLast.js
├── dropWhile.js
├── duplicate.js
├── either.js
├── elem.js
├── elem_.js
├── empty.js
├── encase.js
├── env.js
├── equals.js
├── even.js
├── extend.js
├── extract.js
├── filter.js
├── find.js
├── findMap.js
├── flip.js
├── foldMap.js
├── fromEither.js
├── fromLeft.js
├── fromMaybe.js
├── fromMaybe_.js
├── fromPairs.js
├── fromRight.js
├── fst.js
├── get.js
├── gets.js
├── groupBy.js
├── gt.js
├── gte.js
├── head.js
├── id.js
├── ifElse.js
├── init.js
├── insert.js
├── intercalate.js
├── internal
├── List.cjs
├── List.mjs
├── Sum.cjs
├── Sum.mjs
├── area.js
├── factorial.js
├── rem.js
├── sanctuary.js
└── strMap.js
├── invert.js
├── is.js
├── isJust.js
├── isLeft.js
├── isNothing.js
├── isRight.js
├── join.js
├── joinWith.js
├── justs.js
├── keys.js
├── last.js
├── lefts.js
├── lift2.js
├── lift3.js
├── lines.js
├── lt.js
├── lte.js
├── map.js
├── mapLeft.js
├── mapMaybe.js
├── match.js
├── matchAll.js
├── max.js
├── maybe.js
├── maybeToNullable.js
├── maybe_.js
├── min.js
├── mult.js
├── negate.js
├── none.js
├── not.js
├── odd.js
├── of.js
├── on.js
├── or.js
├── package.json
├── pairs.js
├── pair~.js
├── parseDate.js
├── parseFloat.js
├── parseInt.js
├── parseJson.js
├── pipe.js
├── pipeK.js
├── pow.js
├── prepend.js
├── product.js
├── promap.js
├── prop.js
├── props.js
├── range.js
├── reduce.js
├── reduce_.js
├── regex.js
├── regexEscape.js
├── reject.js
├── remove.js
├── replace.js
├── reverse.js
├── rights.js
├── sequence.js
├── show.js
├── singleton.js
├── size.js
├── snd.js
├── sort.js
├── sortBy.js
├── splitOn.js
├── splitOnRegex.js
├── stripPrefix.js
├── stripSuffix.js
├── sub.js
├── sum.js
├── swap.js
├── tagBy.js
├── tail.js
├── take.js
├── takeLast.js
├── takeWhile.js
├── test.js
├── toLower.js
├── toUpper.js
├── traverse.js
├── trim.js
├── type.js
├── unchecked.js
├── unfold.js
├── unless.js
├── unlines.js
├── unwords.js
├── value.js
├── values.js
├── when.js
├── words.js
├── zero.js
├── zip.js
└── zipWith.js
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | orbs:
4 | node: circleci/node@6.3.0
5 |
6 | workflows:
7 | test:
8 | jobs:
9 | - node/test:
10 | setup:
11 | # derive cache key from package.json
12 | - run: cp package.json package-lock.json
13 | override-ci-command: rm package-lock.json && npm install && git checkout -- package.json
14 | matrix:
15 | parameters:
16 | version:
17 | - 18.0.0
18 | - 20.0.0
19 | - 22.0.0
20 |
--------------------------------------------------------------------------------
/.config:
--------------------------------------------------------------------------------
1 | repo-owner = sanctuary-js
2 | repo-name = sanctuary
3 | contributing-file = .github/CONTRIBUTING.md
4 | module-type = commonjs
5 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["./node_modules/sanctuary-style/eslint.json"],
4 | "overrides": [
5 | {
6 | "files": ["index.js"],
7 | "globals": {"__doctest": "readonly", "define": "readonly", "module": "readonly", "process": "readonly", "require": "readonly", "self": "readonly"},
8 | "rules": {
9 | "max-len": ["error", {"code": 79, "ignoreUrls": true, "ignoreTemplateLiterals": true, "ignorePattern": "^ *//(# | .* :: |[.] > |[.] // |[.] \\[.*\\]: |[.] .* Function x )"}],
10 | "no-param-reassign": ["off"]
11 | }
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Note: __README.md__ is generated from comments in __index.js__. Do not modify
4 | __README.md__ directly.
5 |
6 | 1. Update local main branch:
7 |
8 | $ git checkout main
9 | $ git pull upstream main
10 |
11 | 2. Create feature branch:
12 |
13 | $ git checkout -b feature-x
14 |
15 | 3. Make one or more atomic commits, and ensure that each commit has a
16 | descriptive commit message. Commit messages should be line wrapped
17 | at 72 characters.
18 |
19 | 4. Run `npm test`, and address any errors. Preferably, fix commits in place
20 | using `git rebase` or `git commit --amend` to make the changes easier to
21 | review.
22 |
23 | 5. Push:
24 |
25 | $ git push origin feature-x
26 |
27 | 6. Open a pull request.
28 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [davidchambers, Avaq]
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage/
2 | /node_modules/
3 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2020 Sanctuary
4 | Copyright (c) 2016 Plaid Technologies, Inc.
5 |
6 | Permission is hereby granted, free of charge, to any person
7 | obtaining a copy of this software and associated documentation
8 | files (the "Software"), to deal in the Software without
9 | restriction, including without limitation the rights to use,
10 | copy, modify, merge, publish, distribute, sublicense, and/or
11 | sell copies of the Software, and to permit persons to whom the
12 | Software is furnished to do so, subject to the following
13 | conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | OTHER DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sanctuary",
3 | "version": "3.1.0",
4 | "description": "Refuge from unsafe JavaScript",
5 | "license": "MIT",
6 | "repository": {
7 | "type": "git",
8 | "url": "git://github.com/sanctuary-js/sanctuary.git"
9 | },
10 | "scripts": {
11 | "doctest": "sanctuary-doctest",
12 | "lint": "sanctuary-lint",
13 | "release": "sanctuary-release",
14 | "test": "npm run lint && sanctuary-test && npm run doctest"
15 | },
16 | "dependencies": {
17 | "sanctuary-def": "0.22.0",
18 | "sanctuary-either": "2.1.0",
19 | "sanctuary-maybe": "2.1.0",
20 | "sanctuary-pair": "2.1.0",
21 | "sanctuary-show": "2.0.0",
22 | "sanctuary-type-classes": "12.1.0",
23 | "sanctuary-type-identifiers": "3.0.0"
24 | },
25 | "devDependencies": {
26 | "fantasy-land": "5.0.0",
27 | "jsverify": "0.8.x",
28 | "sanctuary-descending": "2.1.0",
29 | "sanctuary-identity": "2.1.0",
30 | "sanctuary-scripts": "7.0.x"
31 | },
32 | "files": [
33 | "/LICENSE",
34 | "/README.md",
35 | "/index.js",
36 | "/package.json"
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/scripts/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["../.eslintrc.json"],
4 | "env": {"node": true}
5 | }
6 |
--------------------------------------------------------------------------------
/scripts/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | 'use strict';
4 |
5 | const fs = require ('node:fs');
6 | const path = require ('node:path');
7 |
8 | const sanctuary = require ('../package.json');
9 |
10 |
11 | if (!(Object.prototype.hasOwnProperty.call (process.env, 'VERSION'))) {
12 | process.stderr.write ('VERSION not specified\n');
13 | process.exit (1);
14 | }
15 | const VERSION = process.env.VERSION;
16 |
17 | // expandDependencies :: StrMap String -> StrMap (Array String)
18 | const expandDependencies = children => {
19 | const descendants = Object.create (null);
20 | const todo = Object.keys (children);
21 | while (todo.length > 0) {
22 | const name = todo.shift ();
23 | descendants[name] = Object.keys (
24 | (require (`../node_modules/${name}/package.json`)).dependencies
25 | );
26 | Array.prototype.push.apply (todo, descendants[name]);
27 | }
28 | return descendants;
29 | };
30 |
31 | // orderDependencies :: StrMap (Array String) -> Array String
32 | const orderDependencies = deps => {
33 | const done = [];
34 | const todo = (Object.keys (deps)).sort ();
35 | while (todo.length > 0) {
36 | const name = todo.shift ();
37 | (deps[name].every (name => done.includes (name)) ? done : todo)
38 | .push (name);
39 | }
40 | return done;
41 | };
42 |
43 | // dependencies :: Array String
44 | const dependencies =
45 | orderDependencies (expandDependencies (sanctuary.dependencies));
46 |
47 | process.stdout.write (
48 | `// sanctuary@${VERSION} with bundled dependencies:
49 | //
50 | ${dependencies
51 | .map (name => `// - ${name}@${(require (name + '/package.json')).version}`)
52 | .join ('\n')}
53 |
54 | ${dependencies
55 | .map (name => fs.readFileSync (path.join ('node_modules', name, 'index.js'),
56 | 'utf8'))
57 | .join ('\n')}
58 | ${fs.readFileSync ('index.js', 'utf8')}`
59 | );
60 |
--------------------------------------------------------------------------------
/scripts/generate-readme:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euf -o pipefail
3 |
4 | cp index.js index.js.orig
5 | trap 'mv index.js.orig index.js' EXIT
6 |
7 | awk '
8 | {
9 | if ($1 == "//." && $2 ~ /^#{1,6}$/) {
10 | text = "❑ "
11 | slug = "section:"
12 | for (n = 3 ; ; n += 1) {
13 | text = text $n
14 | gsub(/\W/, "", $n)
15 | slug = slug tolower($n)
16 | if (n == NF) {
17 | break
18 | }
19 | text = text " "
20 | slug = slug "-"
21 | }
22 | print "//. " $2 " " text ""
23 | } else {
24 | print
25 | }
26 | }
27 | ' index.js.orig >index.js
28 |
29 | node_modules/.bin/sanctuary-generate-readme
30 |
--------------------------------------------------------------------------------
/scripts/lint:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euf -o pipefail
3 |
4 | node_modules/.bin/sanctuary-lint "$@"
5 |
6 | node_modules/.bin/eslint \
7 | --report-unused-disable-directives \
8 | -- scripts/bundle
9 |
--------------------------------------------------------------------------------
/scripts/prepublish:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euf -o pipefail
3 |
4 | node_modules/.bin/sanctuary-prepublish "$@"
5 |
6 | rm -rf node_modules
7 | npm install
8 | mkdir -p -- dist
9 | scripts/bundle >dist/bundle.js
10 | git add -- dist/bundle.js
11 |
--------------------------------------------------------------------------------
/test/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["../.eslintrc.json"],
4 | "parserOptions": {"ecmaVersion": 2020, "sourceType": "module"},
5 | "env": {"node": true},
6 | "rules": {
7 | "max-len": ["off"]
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/test/I.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('I', () => {
9 |
10 | eq (String (S.I), 'I :: a -> a');
11 |
12 | eq (S.I ([1, 2, 3]), [1, 2, 3]);
13 | eq (S.I (['foo', 42]), ['foo', 42]);
14 |
15 | const x = Symbol ('x');
16 | eq (S.I (x) === x, true);
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/test/Just.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('Just', () => {
9 |
10 | eq (String (S.Just), 'Just :: a -> Maybe a');
11 |
12 | eq (S.Just (42), S.Just (42));
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/K.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('K', () => {
9 |
10 | eq (String (S.K), 'K :: a -> b -> a');
11 |
12 | eq (S.K (21) ([]), 21);
13 | eq (S.K (42) (null), 42);
14 | eq (S.K (84) (undefined), 84);
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/test/Left.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('Left', () => {
9 |
10 | eq (String (S.Left), 'Left :: a -> Either a b');
11 |
12 | eq (S.Left (42), S.Left (42));
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/NODE_ENV.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq, throws} from 'node:assert';
2 | import fs from 'node:fs';
3 | import module from 'node:module';
4 | import path from 'node:path';
5 | import url from 'node:url';
6 | import vm from 'node:vm';
7 |
8 | import test from 'oletus';
9 |
10 |
11 | const __filename = url.fileURLToPath (import.meta.url);
12 | const __dirname = path.dirname (__filename);
13 |
14 | const source = fs.readFileSync (path.join (__dirname, '..', 'index.js'), 'utf8');
15 |
16 | const {version: $$version} = (
17 | JSON.parse (
18 | fs.readFileSync (
19 | path.join (__dirname, '..', 'node_modules', 'sanctuary-def', 'package.json')
20 | )
21 | )
22 | );
23 |
24 | const expected = new TypeError ([
25 | 'Invalid value',
26 | '',
27 | 'add :: FiniteNumber -> FiniteNumber -> FiniteNumber',
28 | ' ^^^^^^^^^^^^',
29 | ' 1',
30 | '',
31 | '1) "foo" :: String',
32 | '',
33 | 'The value at position 1 is not a member of ‘FiniteNumber’.',
34 | '',
35 | 'See https://github.com/sanctuary-js/sanctuary-def/tree/v' + $$version + '#FiniteNumber for information about the FiniteNumber type.',
36 | '',
37 | ].join ('\n'));
38 |
39 | test ('typeof process === "undefined"', () => {
40 | const context = {
41 | module: {exports: {}},
42 | require: module.createRequire (import.meta.url),
43 | };
44 | vm.runInNewContext (source, context);
45 |
46 | throws (() => { context.module.exports.add ('foo'); }, expected);
47 | });
48 |
49 | test ('typeof process !== "undefined" && process == null', () => {
50 | const context = {
51 | module: {exports: {}},
52 | process: null,
53 | require: module.createRequire (import.meta.url),
54 | };
55 | vm.runInNewContext (source, context);
56 |
57 | throws (() => { context.module.exports.add ('foo'); }, expected);
58 | });
59 |
60 | test ('typeof process !== "undefined" && process != null && process.env == null', () => {
61 | const context = {
62 | module: {exports: {}},
63 | process: {},
64 | require: module.createRequire (import.meta.url),
65 | };
66 | vm.runInNewContext (source, context);
67 |
68 | throws (() => { context.module.exports.add ('foo'); }, expected);
69 | });
70 |
71 | test ('typeof process !== "undefined" && process != null && process.env != null && process.env.NODE_ENV == null', () => {
72 | const context = {
73 | module: {exports: {}},
74 | process: {env: {}},
75 | require: module.createRequire (import.meta.url),
76 | };
77 | vm.runInNewContext (source, context);
78 |
79 | throws (() => { context.module.exports.add ('foo'); }, expected);
80 | });
81 |
82 | test ('typeof process !== "undefined" && process != null && process.env != null && process.env.NODE_ENV !== "production"', () => {
83 | const context = {
84 | module: {exports: {}},
85 | process: {env: {NODE_ENV: 'XXX'}},
86 | require: module.createRequire (import.meta.url),
87 | };
88 | vm.runInNewContext (source, context);
89 |
90 | throws (() => { context.module.exports.add ('foo'); }, expected);
91 | });
92 |
93 | test ('typeof process !== "undefined" && process != null && process.env != null && process.env.NODE_ENV === "production"', () => {
94 | const context = {
95 | module: {exports: {}},
96 | process: {env: {NODE_ENV: 'production'}},
97 | require: module.createRequire (import.meta.url),
98 | };
99 | vm.runInNewContext (source, context);
100 |
101 | eq (context.module.exports.add ('foo') ('bar'), 'foobar');
102 | });
103 |
--------------------------------------------------------------------------------
/test/Nothing.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('Nothing', () => {
9 |
10 | eq (S.show (S.Nothing), 'Nothing');
11 |
12 | eq (S.Nothing, S.Nothing);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/Pair.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('Pair', () => {
9 |
10 | eq (String (S.Pair), 'Pair :: a -> b -> Pair a b');
11 |
12 | eq (S.Pair ('foo') (42), S.Pair ('foo') (42));
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/Right.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('Right', () => {
9 |
10 | eq (String (S.Right), 'Right :: b -> Either a b');
11 |
12 | eq (S.Right (42), S.Right (42));
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/T.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('T', () => {
9 |
10 | eq (String (S.T), 'T :: a -> (a -> b) -> b');
11 |
12 | eq (S.T ('!') (S.concat ('foo')), 'foo!');
13 | eq (S.T ('!') (S.concat ('bar')), 'bar!');
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/add.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('add', () => {
9 |
10 | eq (String (S.add), 'add :: FiniteNumber -> FiniteNumber -> FiniteNumber');
11 |
12 | eq (S.add (1) (1), 2);
13 | eq (S.add (-1) (-1), -2);
14 | eq (S.add (1.5) (1), 2.5);
15 | eq (S.add (-1.5) (-1), -2.5);
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/all.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('all', () => {
11 |
12 | eq (String (S.all), 'all :: Foldable f => (a -> Boolean) -> f a -> Boolean');
13 |
14 | eq (S.all (S.gt (0)) ([]), true);
15 | eq (S.all (S.gt (0)) ([0]), false);
16 | eq (S.all (S.gt (0)) ([1]), true);
17 | eq (S.all (S.gt (0)) ([0, 0]), false);
18 | eq (S.all (S.gt (0)) ([0, 1]), false);
19 | eq (S.all (S.gt (0)) ([1, 0]), false);
20 | eq (S.all (S.gt (0)) ([1, 1]), true);
21 |
22 | eq (S.all (S.gt (0)) (Nil), true);
23 | eq (S.all (S.gt (0)) (Cons (0) (Nil)), false);
24 | eq (S.all (S.gt (0)) (Cons (1) (Nil)), true);
25 | eq (S.all (S.gt (0)) (Cons (0) (Cons (0) (Nil))), false);
26 | eq (S.all (S.gt (0)) (Cons (0) (Cons (1) (Nil))), false);
27 | eq (S.all (S.gt (0)) (Cons (1) (Cons (0) (Nil))), false);
28 | eq (S.all (S.gt (0)) (Cons (1) (Cons (1) (Nil))), true);
29 |
30 | eq (S.all (S.gt (0)) (S.Nothing), true);
31 | eq (S.all (S.gt (0)) (S.Just (0)), false);
32 | eq (S.all (S.gt (0)) (S.Just (1)), true);
33 |
34 | });
35 |
--------------------------------------------------------------------------------
/test/alt.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('alt', () => {
9 |
10 | eq (String (S.alt), 'alt :: Alt f => f a -> f a -> f a');
11 |
12 | eq (S.alt ([]) ([]), []);
13 | eq (S.alt ([1, 2, 3]) ([]), [1, 2, 3]);
14 | eq (S.alt ([]) ([1, 2, 3]), [1, 2, 3]);
15 | eq (S.alt ([4, 5, 6]) ([1, 2, 3]), [1, 2, 3, 4, 5, 6]);
16 | eq (S.alt ({}) ({}), {});
17 | eq (S.alt ({a: 1, b: 2, c: 3}) ({}), {a: 1, b: 2, c: 3});
18 | eq (S.alt ({}) ({a: 1, b: 2, c: 3}), {a: 1, b: 2, c: 3});
19 | eq (S.alt ({d: 4, e: 5, f: 6}) ({a: 1, b: 2, c: 3}), {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6});
20 | eq (S.alt ({c: 4, d: 5, e: 6}) ({a: 1, b: 2, c: 3}), {a: 1, b: 2, c: 4, d: 5, e: 6});
21 | eq (S.alt (S.Nothing) (S.Nothing), S.Nothing);
22 | eq (S.alt (S.Just (1)) (S.Nothing), S.Just (1));
23 | eq (S.alt (S.Nothing) (S.Just (2)), S.Just (2));
24 | eq (S.alt (S.Just (4)) (S.Just (3)), S.Just (3));
25 |
26 | });
27 |
--------------------------------------------------------------------------------
/test/and.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('and', () => {
9 |
10 | eq (String (S.and), 'and :: Boolean -> Boolean -> Boolean');
11 |
12 | eq (S.and (false) (false), false);
13 | eq (S.and (false) (true), false);
14 | eq (S.and (true) (false), false);
15 | eq (S.and (true) (true), true);
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/any.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('any', () => {
11 |
12 | eq (String (S.any), 'any :: Foldable f => (a -> Boolean) -> f a -> Boolean');
13 |
14 | eq (S.any (S.gt (0)) ([]), false);
15 | eq (S.any (S.gt (0)) ([0]), false);
16 | eq (S.any (S.gt (0)) ([1]), true);
17 | eq (S.any (S.gt (0)) ([0, 0]), false);
18 | eq (S.any (S.gt (0)) ([0, 1]), true);
19 | eq (S.any (S.gt (0)) ([1, 0]), true);
20 | eq (S.any (S.gt (0)) ([1, 1]), true);
21 |
22 | eq (S.any (S.gt (0)) (Nil), false);
23 | eq (S.any (S.gt (0)) (Cons (0) (Nil)), false);
24 | eq (S.any (S.gt (0)) (Cons (1) (Nil)), true);
25 | eq (S.any (S.gt (0)) (Cons (0) (Cons (0) (Nil))), false);
26 | eq (S.any (S.gt (0)) (Cons (0) (Cons (1) (Nil))), true);
27 | eq (S.any (S.gt (0)) (Cons (1) (Cons (0) (Nil))), true);
28 | eq (S.any (S.gt (0)) (Cons (1) (Cons (1) (Nil))), true);
29 |
30 | eq (S.any (S.gt (0)) (S.Nothing), false);
31 | eq (S.any (S.gt (0)) (S.Just (0)), false);
32 | eq (S.any (S.gt (0)) (S.Just (1)), true);
33 |
34 | });
35 |
--------------------------------------------------------------------------------
/test/ap.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('ap', () => {
9 |
10 | eq (String (S.ap), 'ap :: Apply f => f (a -> b) -> f a -> f b');
11 |
12 | eq (S.ap ([]) ([]), []);
13 | eq (S.ap ([]) ([1, 2, 3]), []);
14 | eq (S.ap ([S.add (1)]) ([]), []);
15 | eq (S.ap ([S.add (1)]) ([1, 2, 3]), [2, 3, 4]);
16 | eq (S.ap ([S.sub (1), Math.sqrt]) ([1, 4, 9]), [0, 3, 8, 1, 2, 3]);
17 | eq (S.ap ({}) ({}), {});
18 | eq (S.ap ({}) ({x: 1, y: 2, z: 3}), {});
19 | eq (S.ap ({x: S.add (1)}) ({}), {});
20 | eq (S.ap ({x: S.add (1)}) ({x: 1}), {x: 2});
21 | eq (S.ap ({x: S.add (1), y: S.sub (1), z: Math.sqrt}) ({w: 0, x: 1, y: 2}), {x: 2, y: 1});
22 | eq (S.ap (S.Nothing) (S.Nothing), S.Nothing);
23 | eq (S.ap (S.Nothing) (S.Just (9)), S.Nothing);
24 | eq (S.ap (S.Just (Math.sqrt)) (S.Nothing), S.Nothing);
25 | eq (S.ap (S.Just (Math.sqrt)) (S.Just (9)), S.Just (3));
26 |
27 | });
28 |
--------------------------------------------------------------------------------
/test/apFirst.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('apFirst', () => {
9 |
10 | eq (String (S.apFirst), 'apFirst :: Apply f => f a -> f b -> f a');
11 |
12 | eq (S.apFirst ([1, 2]) ([3, 4]), [1, 1, 2, 2]);
13 | eq (S.apFirst (S.Just (1)) (S.Just (2)), S.Just (1));
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/apSecond.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('apSecond', () => {
9 |
10 | eq (String (S.apSecond), 'apSecond :: Apply f => f a -> f b -> f b');
11 |
12 | eq (S.apSecond ([1, 2]) ([3, 4]), [3, 4, 3, 4]);
13 | eq (S.apSecond (S.Just (1)) (S.Just (2)), S.Just (2));
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/append.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('append', () => {
9 |
10 | eq (String (S.append), 'append :: (Applicative f, Semigroup f) => a -> f a -> f a');
11 |
12 | eq (S.append (3) ([]), [3]);
13 | eq (S.append (3) ([1, 2]), [1, 2, 3]);
14 | eq (S.append ([5, 6]) ([[1, 2], [3, 4]]), [[1, 2], [3, 4], [5, 6]]);
15 |
16 | eq (S.append ([2]) (S.Nothing), S.Just ([2]));
17 | eq (S.append ([2]) (S.Just ([1])), S.Just ([1, 2]));
18 |
19 | eq (S.append ([2]) (S.Left ('error')), S.Right ([2]));
20 | eq (S.append ([2]) (S.Right ([1])), S.Right ([1, 2]));
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/test/array.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('array', () => {
9 |
10 | eq (String (S.array), 'array :: b -> (a -> Array a -> b) -> Array a -> b');
11 |
12 | const size = S.array (0) (head => tail => 1 + size (tail));
13 | eq (size ([]), 0);
14 | eq (size (['foo']), 1);
15 | eq (size (['foo', 'bar']), 2);
16 | eq (size (['foo', 'bar', 'baz']), 3);
17 |
18 | const reverse = S.array ([]) (head => tail => S.append (head) (reverse (tail)));
19 | eq (reverse ([]), []);
20 | eq (reverse (['foo']), ['foo']);
21 | eq (reverse (['foo', 'bar']), ['bar', 'foo']);
22 | eq (reverse (['foo', 'bar', 'baz']), ['baz', 'bar', 'foo']);
23 |
24 | const tail = S.array (S.Nothing) (S.K (S.Just));
25 | eq (tail ([]), S.Nothing);
26 | eq (tail (['foo']), S.Just ([]));
27 | eq (tail (['foo', 'bar']), S.Just (['bar']));
28 | eq (tail (['foo', 'bar', 'baz']), S.Just (['bar', 'baz']));
29 |
30 | });
31 |
--------------------------------------------------------------------------------
/test/bimap.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('bimap', () => {
9 |
10 | eq (String (S.bimap), 'bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d');
11 |
12 | eq (S.bimap (S.toUpper) (S.add (1)) (S.Left ('xxx')), S.Left ('XXX'));
13 | eq (S.bimap (S.toUpper) (S.add (1)) (S.Right (1000)), S.Right (1001));
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/boolean.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('boolean', () => {
9 |
10 | eq (String (S.boolean), 'boolean :: a -> a -> Boolean -> a');
11 |
12 | eq (S.boolean ('no') ('yes') (false), 'no');
13 | eq (S.boolean ('no') ('yes') (true), 'yes');
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/chain.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('chain', () => {
9 |
10 | eq (String (S.chain), 'chain :: Chain m => (a -> m b) -> m a -> m b');
11 |
12 | eq (S.chain (S.I) ([[1, 2], [3, 4], [5, 6]]), [1, 2, 3, 4, 5, 6]);
13 | eq (S.chain (S.parseFloat) (S.Nothing), S.Nothing);
14 | eq (S.chain (S.parseFloat) (S.Just ('X')), S.Nothing);
15 | eq (S.chain (S.parseFloat) (S.Just ('0')), S.Just (0));
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/chainRec.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('chainRec', () => {
9 |
10 | eq (String (S.chainRec), 'chainRec :: ChainRec m => TypeRep (m b) -> (a -> m (Either a b)) -> a -> m b');
11 |
12 | eq (S.chainRec (Array)
13 | (s => s.length === 2 ? S.map (S.Right) ([s + '!', s + '?'])
14 | : S.map (S.Left) ([s + 'o', s + 'n']))
15 | (''),
16 | ['oo!', 'oo?', 'on!', 'on?', 'no!', 'no?', 'nn!', 'nn?']);
17 |
18 | // The following test case is concerned with stack usage rather than with
19 | // the correctness of the result. This test case is a slightly modified
20 | // version of one from sanctuary-type-classes. The "stop" value is lower
21 | // to prevent the execution time from exceeding the test runner's timeout.
22 | eq (S.chainRec (Function)
23 | (n => n === 3000 ? S.map (S.Right) (env => n + env.inc)
24 | : S.map (S.Left) (env => n + env.step))
25 | (0)
26 | ({step: 2, inc: 100}),
27 | 3100);
28 |
29 | });
30 |
--------------------------------------------------------------------------------
/test/clamp.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('clamp', () => {
9 |
10 | eq (String (S.clamp), 'clamp :: Ord a => a -> a -> a -> a');
11 |
12 | eq (S.clamp (0) (100) (-1), 0);
13 | eq (S.clamp (0) (100) (0), 0);
14 | eq (S.clamp (0) (100) (50), 50);
15 | eq (S.clamp (0) (100) (100), 100);
16 | eq (S.clamp (0) (100) (101), 100);
17 |
18 | eq (S.clamp ('A') ('Z') ('0'), 'A');
19 | eq (S.clamp ('A') ('Z') ('A'), 'A');
20 | eq (S.clamp ('A') ('Z') ('X'), 'X');
21 | eq (S.clamp ('A') ('Z') ('Z'), 'Z');
22 | eq (S.clamp ('A') ('Z') ('~'), 'Z');
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/test/complement.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('complement', () => {
9 |
10 | eq (String (S.complement), 'complement :: (a -> Boolean) -> a -> Boolean');
11 |
12 | eq (S.complement (S.odd) (1), false);
13 | eq (S.complement (S.odd) (2), true);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/compose.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('compose', () => {
9 |
10 | eq (String (S.compose), 'compose :: Semigroupoid s => s b c -> s a b -> s a c');
11 |
12 | eq (S.compose (S.mult (2)) (S.add (1)) (20), 42);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/concat.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('concat', () => {
9 |
10 | eq (String (S.concat), 'concat :: Semigroup a => a -> a -> a');
11 |
12 | eq (S.concat ([]) ([]), []);
13 | eq (S.concat ([1, 2, 3]) ([]), [1, 2, 3]);
14 | eq (S.concat ([]) ([4, 5, 6]), [4, 5, 6]);
15 | eq (S.concat ([1, 2, 3]) ([4, 5, 6]), [1, 2, 3, 4, 5, 6]);
16 |
17 | eq (S.concat ('') (''), '');
18 | eq (S.concat ('foo') (''), 'foo');
19 | eq (S.concat ('') ('bar'), 'bar');
20 | eq (S.concat ('foo') ('bar'), 'foobar');
21 |
22 | eq (S.concat (S.Nothing) (S.Nothing), S.Nothing);
23 | eq (S.concat (S.Just ('foo')) (S.Nothing), S.Just ('foo'));
24 | eq (S.concat (S.Nothing) (S.Just ('bar')), S.Just ('bar'));
25 | eq (S.concat (S.Just ('foo')) (S.Just ('bar')), S.Just ('foobar'));
26 |
27 | eq (S.concat (S.Left ('abc')) (S.Left ('def')), S.Left ('abcdef'));
28 | eq (S.concat (S.Right ([1, 2, 3])) (S.Left ('def')), S.Right ([1, 2, 3]));
29 | eq (S.concat (S.Left ('abc')) (S.Right ([4, 5, 6])), S.Right ([4, 5, 6]));
30 | eq (S.concat (S.Right ([1, 2, 3])) (S.Right ([4, 5, 6])), S.Right ([1, 2, 3, 4, 5, 6]));
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/test/contramap.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('contramap', () => {
9 |
10 | eq (String (S.contramap), 'contramap :: Contravariant f => (b -> a) -> f a -> f b');
11 |
12 | eq (S.contramap (S.prop ('length')) (Math.sqrt) ('Sanctuary'), 3);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/create.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq, throws} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import $ from 'sanctuary-def';
5 |
6 | import S from '../index.js';
7 |
8 |
9 | // FooTrue42 :: Type
10 | const FooTrue42 = $.EnumType ('my-package/FooTrue42') ('') (['foo', true, 42]);
11 |
12 | // customEnv :: Array Type
13 | const customEnv = S.env.concat ([FooTrue42]);
14 |
15 | const checkedDefaultEnv = S.create ({checkTypes: true, env: S.env});
16 | const checkedCustomEnv = S.create ({checkTypes: true, env: customEnv});
17 | const uncheckedDefaultEnv = S.create ({checkTypes: false, env: S.env});
18 | const uncheckedCustomEnv = S.create ({checkTypes: false, env: customEnv});
19 |
20 |
21 | test ('create', () => {
22 |
23 | eq (String (S.create), 'create :: { checkTypes :: Boolean, env :: Array Any } -> Object');
24 |
25 | const expected = S.sort (Object.keys (S));
26 | eq (S.sort (Object.keys (checkedDefaultEnv)), expected);
27 | eq (S.sort (Object.keys (checkedCustomEnv)), expected);
28 | eq (S.sort (Object.keys (uncheckedDefaultEnv)), expected);
29 | eq (S.sort (Object.keys (uncheckedCustomEnv)), expected);
30 |
31 | eq (checkedDefaultEnv.env, S.env);
32 | eq (checkedCustomEnv.env, customEnv);
33 | eq (uncheckedDefaultEnv.env, S.env);
34 | eq (uncheckedCustomEnv.env, customEnv);
35 |
36 | eq (checkedDefaultEnv.unchecked.env, S.env);
37 | eq (checkedCustomEnv.unchecked.env, customEnv);
38 | eq (uncheckedDefaultEnv.unchecked.env, S.env);
39 | eq (uncheckedCustomEnv.unchecked.env, customEnv);
40 |
41 | eq (uncheckedDefaultEnv.add (1) (42), S.add (1) (42));
42 | eq (uncheckedDefaultEnv.add (1) ('XXX'), '1XXX');
43 |
44 | throws (() => { S.I (['foo', 'foo', 42]); },
45 | new TypeError ('Type-variable constraint violation\n' +
46 | '\n' +
47 | 'I :: a -> a\n' +
48 | ' ^\n' +
49 | ' 1\n' +
50 | '\n' +
51 | '1) ["foo", "foo", 42] :: Array ???\n' +
52 | '\n' +
53 | 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n'));
54 |
55 | eq (checkedCustomEnv.I (['foo', 'foo', 42]), ['foo', 'foo', 42]);
56 |
57 | });
58 |
--------------------------------------------------------------------------------
/test/div.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('div', () => {
9 |
10 | eq (String (S.div), 'div :: NonZeroFiniteNumber -> FiniteNumber -> FiniteNumber');
11 |
12 | eq (S.map (S.div (2)) ([0, 1, 2, 3]), [0, 0.5, 1, 1.5]);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/drop.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('drop', () => {
11 |
12 | eq (String (S.drop), 'drop :: (Applicative f, Foldable f, Monoid f) => Integer -> f a -> Maybe (f a)');
13 |
14 | eq (S.drop (0) ([1, 2, 3, 4, 5]), S.Just ([1, 2, 3, 4, 5]));
15 | eq (S.drop (1) ([1, 2, 3, 4, 5]), S.Just ([2, 3, 4, 5]));
16 | eq (S.drop (2) ([1, 2, 3, 4, 5]), S.Just ([3, 4, 5]));
17 | eq (S.drop (3) ([1, 2, 3, 4, 5]), S.Just ([4, 5]));
18 | eq (S.drop (4) ([1, 2, 3, 4, 5]), S.Just ([5]));
19 | eq (S.drop (5) ([1, 2, 3, 4, 5]), S.Just ([]));
20 | eq (S.drop (6) ([1, 2, 3, 4, 5]), S.Nothing);
21 |
22 | eq (S.drop (-1) ([1, 2, 3, 4, 5]), S.Nothing);
23 |
24 | eq (S.drop (0) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (1) (Cons (2) (Cons (3) (Nil)))));
25 | eq (S.drop (1) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (2) (Cons (3) (Nil))));
26 | eq (S.drop (2) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (3) (Nil)));
27 | eq (S.drop (3) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Nil));
28 | eq (S.drop (4) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Nothing);
29 |
30 | eq (S.drop (-1) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Nothing);
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/test/dropLast.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('dropLast', () => {
11 |
12 | eq (String (S.dropLast), 'dropLast :: (Applicative f, Foldable f, Monoid f) => Integer -> f a -> Maybe (f a)');
13 |
14 | eq (S.dropLast (0) ([1, 2, 3, 4, 5]), S.Just ([1, 2, 3, 4, 5]));
15 | eq (S.dropLast (1) ([1, 2, 3, 4, 5]), S.Just ([1, 2, 3, 4]));
16 | eq (S.dropLast (2) ([1, 2, 3, 4, 5]), S.Just ([1, 2, 3]));
17 | eq (S.dropLast (3) ([1, 2, 3, 4, 5]), S.Just ([1, 2]));
18 | eq (S.dropLast (4) ([1, 2, 3, 4, 5]), S.Just ([1]));
19 | eq (S.dropLast (5) ([1, 2, 3, 4, 5]), S.Just ([]));
20 | eq (S.dropLast (6) ([1, 2, 3, 4, 5]), S.Nothing);
21 |
22 | eq (S.dropLast (-1) ([1, 2, 3, 4, 5]), S.Nothing);
23 |
24 | eq (S.dropLast (0) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (1) (Cons (2) (Cons (3) (Nil)))));
25 | eq (S.dropLast (1) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (1) (Cons (2) (Nil))));
26 | eq (S.dropLast (2) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (1) (Nil)));
27 | eq (S.dropLast (3) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Nil));
28 | eq (S.dropLast (4) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Nothing);
29 |
30 | eq (S.dropLast (-1) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Nothing);
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/test/dropWhile.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('dropWhile', () => {
9 |
10 | eq (String (S.dropWhile), 'dropWhile :: (a -> Boolean) -> Array a -> Array a');
11 |
12 | eq (S.dropWhile (S.odd) ([3, 3, 3, 7, 6, 3, 5, 4]), [6, 3, 5, 4]);
13 | eq (S.dropWhile (S.even) ([3, 3, 3, 7, 6, 3, 5, 4]), [3, 3, 3, 7, 6, 3, 5, 4]);
14 | eq (S.dropWhile (S.odd) ([]), []);
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/test/duplicate.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('duplicate', () => {
9 |
10 | eq (String (S.duplicate), 'duplicate :: Extend w => w a -> w (w a)');
11 |
12 | eq (S.duplicate ([]), []);
13 | eq (S.duplicate ([1]), [[1]]);
14 | eq (S.duplicate ([1, 2]), [[1, 2], [2]]);
15 | eq (S.duplicate ([1, 2, 3]), [[1, 2, 3], [2, 3], [3]]);
16 | eq (S.duplicate (S.reverse) ([1, 2]) ([3, 4]), [4, 3, 2, 1]);
17 | eq (S.duplicate (S.Just (1)), S.Just (S.Just (1)));
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/either.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('either', () => {
9 |
10 | eq (String (S.either), 'either :: (a -> c) -> (b -> c) -> Either a b -> c');
11 |
12 | eq (S.either (S.prop ('length')) (Math.sqrt) (S.Left ('abc')), 3);
13 | eq (S.either (S.prop ('length')) (Math.sqrt) (S.Right (256)), 16);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/elem.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('elem', () => {
9 |
10 | eq (String (S.elem), 'elem :: (Setoid a, Foldable f) => a -> f a -> Boolean');
11 |
12 | eq (S.elem ('c') (['a', 'b', 'c']), true);
13 | eq (S.elem ('x') (['a', 'b', 'c']), false);
14 | eq (S.elem (3) ({x: 1, y: 2, z: 3}), true);
15 | eq (S.elem (8) ({x: 1, y: 2, z: 3}), false);
16 | eq (S.elem (0) (S.Just (0)), true);
17 | eq (S.elem (0) (S.Just (1)), false);
18 | eq (S.elem (0) (S.Nothing), false);
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/elem_.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('elem_', () => {
9 |
10 | eq (String (S.elem_), 'elem_ :: (Setoid a, Foldable f) => f a -> a -> Boolean');
11 |
12 | eq (S.elem_ (['a', 'b', 'c']) ('c'), true);
13 | eq (S.elem_ (['a', 'b', 'c']) ('x'), false);
14 | eq (S.elem_ ({x: 1, y: 2, z: 3}) (3), true);
15 | eq (S.elem_ ({x: 1, y: 2, z: 3}) (8), false);
16 | eq (S.elem_ (S.Just (0)) (0), true);
17 | eq (S.elem_ (S.Just (1)) (0), false);
18 | eq (S.elem_ (S.Nothing) (0), false);
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/empty.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('empty', () => {
9 |
10 | eq (String (S.empty), 'empty :: Monoid a => TypeRep a -> a');
11 |
12 | eq (S.empty (String), '');
13 | eq (S.empty (Array), []);
14 | eq (S.empty (Object), {});
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/test/encase.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 | import area from './internal/area.js';
8 | import factorial from './internal/factorial.js';
9 | import rem from './internal/rem.js';
10 |
11 |
12 | test ('encase', () => {
13 |
14 | eq (String (S.encase), 'encase :: (Throwing e a b) -> a -> Either e b');
15 |
16 | // safeFactorial :: Number -> Maybe Number
17 | const safeFactorial = S.encase (factorial);
18 |
19 | eq (safeFactorial (5), S.Right (120));
20 | eq (safeFactorial (-1), S.Left ('Cannot determine factorial of negative number'));
21 |
22 | // safeRem :: Number -> Number -> Maybe Number
23 | const safeRem = S.compose (S.encase) (rem);
24 |
25 | eq (safeRem (42) (5), S.Right (2));
26 | eq (safeRem (42) (0), S.Left (new Error ('Cannot divide by zero')));
27 |
28 | // safeArea :: Number -> Number -> Number -> Maybe Number
29 | const safeArea = S.compose (S.compose (S.encase)) (area);
30 |
31 | eq (safeArea (3) (4) (5), S.Right (6));
32 | eq (safeArea (2) (2) (5), S.Left (new Error ('Impossible triangle')));
33 |
34 | });
35 |
--------------------------------------------------------------------------------
/test/env.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import $ from 'sanctuary-def';
5 |
6 | import S from '../index.js';
7 |
8 |
9 | test ('env', () => {
10 |
11 | eq (S.is ($.Array ($.Type)) (S.env), true);
12 |
13 | });
14 |
--------------------------------------------------------------------------------
/test/equals.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('equals', () => {
9 |
10 | eq (String (S.equals), 'equals :: Setoid a => a -> a -> Boolean');
11 |
12 | eq (S.equals (S.Nothing) (S.Nothing), true);
13 | eq (S.equals (S.Just (NaN)) (S.Just (NaN)), true);
14 | eq (S.equals (S.Just (0)) (S.Just (-0)), true);
15 | eq (S.equals (S.Nothing) (S.Just (0)), false);
16 | eq (S.equals (S.Just (0)) (S.Just (1)), false);
17 |
18 | eq (S.equals (S.Left (NaN)) (S.Left (NaN)), true);
19 | eq (S.equals (S.Left (0)) (S.Left (-0)), true);
20 | eq (S.equals (S.Right (NaN)) (S.Right (NaN)), true);
21 | eq (S.equals (S.Right (0)) (S.Right (-0)), true);
22 | eq (S.equals (S.Left (10)) (S.Left (20)), false);
23 | eq (S.equals (S.Left (10)) (S.Right (0)), false);
24 | eq (S.equals (S.Right (0)) (S.Right (1)), false);
25 |
26 | });
27 |
--------------------------------------------------------------------------------
/test/even.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('even', () => {
9 |
10 | eq (String (S.even), 'even :: Integer -> Boolean');
11 |
12 | eq (S.even (0), true);
13 | eq (S.even (2), true);
14 | eq (S.even (-2), true);
15 |
16 | eq (S.even (1), false);
17 | eq (S.even (-1), false);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/extend.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import Identity from 'sanctuary-identity';
5 |
6 | import S from './internal/sanctuary.js';
7 |
8 |
9 | test ('extend', () => {
10 |
11 | eq (String (S.extend), 'extend :: Extend w => (w a -> b) -> w a -> w b');
12 |
13 | eq (S.extend (S.joinWith ('')) ([]), []);
14 | eq (S.extend (S.joinWith ('')) (['x']), ['x']);
15 | eq (S.extend (S.joinWith ('')) (['x', 'y']), ['xy', 'y']);
16 | eq (S.extend (S.joinWith ('')) (['x', 'y', 'z']), ['xyz', 'yz', 'z']);
17 | eq (S.extend (S.reduce (S.add) (1)) (Identity (42)), Identity (43));
18 | eq (S.extend (S.T ([3, 4])) (S.reverse) ([1, 2]), [4, 3, 2, 1]);
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/extract.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import Identity from 'sanctuary-identity';
5 |
6 | import S from './internal/sanctuary.js';
7 |
8 |
9 | test ('extract', () => {
10 |
11 | eq (String (S.extract), 'extract :: Comonad w => w a -> a');
12 |
13 | eq (S.extract (Identity (42)), 42);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/filter.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('filter', () => {
11 |
12 | eq (String (S.filter), 'filter :: Filterable f => (a -> Boolean) -> f a -> f a');
13 |
14 | eq (S.filter (S.odd) ([]), []);
15 | eq (S.filter (S.odd) ([0, 2, 4, 6, 8]), []);
16 | eq (S.filter (S.odd) ([1, 3, 5, 7, 9]), [1, 3, 5, 7, 9]);
17 | eq (S.filter (S.odd) ([1, 2, 3, 4, 5]), [1, 3, 5]);
18 |
19 | eq (S.filter (S.odd) ({}), {});
20 | eq (S.filter (S.odd) ({x: 1}), {x: 1});
21 | eq (S.filter (S.odd) ({x: 1, y: 2}), {x: 1});
22 | eq (S.filter (S.odd) ({x: 1, y: 2, z: 3}), {x: 1, z: 3});
23 |
24 | eq (S.filter (S.odd) (S.Nothing), S.Nothing);
25 | eq (S.filter (S.odd) (S.Just (0)), S.Nothing);
26 | eq (S.filter (S.odd) (S.Just (1)), S.Just (1));
27 |
28 | eq (S.filter (S.odd) (Nil), Nil);
29 | eq (S.filter (S.odd) (Cons (1) (Nil)), Cons (1) (Nil));
30 | eq (S.filter (S.odd) (Cons (1) (Cons (2) (Nil))), Cons (1) (Nil));
31 | eq (S.filter (S.odd) (Cons (1) (Cons (2) (Cons (3) (Nil)))), Cons (1) (Cons (3) (Nil)));
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/test/find.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('find', () => {
9 |
10 | eq (String (S.find), 'find :: Foldable f => (a -> Boolean) -> f a -> Maybe a');
11 |
12 | eq (S.find (S.even) ([]), S.Nothing);
13 | eq (S.find (S.even) ([1, 3, 5, 7, 9]), S.Nothing);
14 | eq (S.find (S.even) ([1, 2, 3, 4, 5]), S.Just (2));
15 | eq (S.find (S.even) ({}), S.Nothing);
16 | eq (S.find (S.even) ({a: 1, b: 3, c: 5, d: 7, e: 9}), S.Nothing);
17 | eq (S.find (S.even) ({a: 1, b: 2, c: 3, d: 4, e: 5}), S.Just (2));
18 | eq (S.find (S.even) ({e: 5, d: 4, c: 3, b: 2, a: 1}), S.Just (2));
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/findMap.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('findMap', () => {
9 |
10 | eq (String (S.findMap), 'findMap :: Foldable f => (a -> Maybe b) -> f a -> Maybe b');
11 |
12 | eq (S.findMap (S.parseInt (16)) ([]), S.Nothing);
13 | eq (S.findMap (S.parseInt (16)) (['H', 'G']), S.Nothing);
14 | eq (S.findMap (S.parseInt (16)) (['H', 'G', 'F', 'E']), S.Just (15));
15 | eq (S.findMap (S.parseInt (16)) ({}), S.Nothing);
16 | eq (S.findMap (S.parseInt (16)) ({a: 'H', b: 'G'}), S.Nothing);
17 | eq (S.findMap (S.parseInt (16)) ({a: 'H', b: 'G', c: 'F', d: 'E'}), S.Just (15));
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/flip.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('flip', () => {
11 |
12 | eq (String (S.flip), 'flip :: Functor f => f (a -> b) -> a -> f b');
13 |
14 | eq (S.flip (S.concat) ('foo') ('bar'), 'barfoo');
15 | eq (S.map (S.flip (S.concat) ('!')) (['BAM', 'POW', 'KA-POW']), ['BAM!', 'POW!', 'KA-POW!']);
16 | eq (S.flip ([Math.floor, Math.ceil]) (1.5), [1, 2]);
17 | eq (S.flip ({floor: Math.floor, ceil: Math.ceil}) (1.5), {floor: 1, ceil: 2});
18 | eq (S.flip (Cons (Math.floor) (Cons (Math.ceil) (Nil))) (1.5), Cons (1) (Cons (2) (Nil)));
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/foldMap.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('foldMap', () => {
9 |
10 | eq (String (S.foldMap), 'foldMap :: (Monoid b, Foldable f) => TypeRep b -> (a -> b) -> f a -> b');
11 |
12 | const repeat = n => (new Array (n + 1)).join (String (n));
13 | eq (S.foldMap (String) (repeat) ([]), '');
14 | eq (S.foldMap (String) (repeat) ([1]), '1');
15 | eq (S.foldMap (String) (repeat) ([1, 2]), '122');
16 | eq (S.foldMap (String) (repeat) ([1, 2, 3]), '122333');
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/test/fromEither.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('fromEither', () => {
9 |
10 | eq (String (S.fromEither), 'fromEither :: Either a a -> a');
11 |
12 | eq (S.fromEither (S.Left (42)), 42);
13 | eq (S.fromEither (S.Right (42)), 42);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/fromLeft.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('fromLeft', () => {
9 |
10 | eq (String (S.fromLeft), 'fromLeft :: a -> Either a b -> a');
11 |
12 | eq (S.fromLeft ('abc') (S.Left ('xyz')), 'xyz');
13 | eq (S.fromLeft ('abc') (S.Right (123)), 'abc');
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/fromMaybe.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('fromMaybe', () => {
9 |
10 | eq (String (S.fromMaybe), 'fromMaybe :: a -> Maybe a -> a');
11 |
12 | eq (S.fromMaybe (0) (S.Nothing), 0);
13 | eq (S.fromMaybe (0) (S.Just (42)), 42);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/fromMaybe_.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('fromMaybe_', () => {
9 |
10 | eq (String (S.fromMaybe_), 'fromMaybe_ :: (() -> a) -> Maybe a -> a');
11 |
12 | eq (S.fromMaybe_ (() => 0) (S.Nothing), 0);
13 | eq (S.fromMaybe_ (() => 0) (S.Just (42)), 42);
14 |
15 | let count = 0;
16 | eq (S.fromMaybe_ (() => count += 1) (S.Just (42)), 42);
17 | eq (count, 0);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/fromPairs.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('fromPairs', () => {
9 |
10 | eq (String (S.fromPairs), 'fromPairs :: Foldable f => f (Pair String a) -> StrMap a');
11 |
12 | eq (S.fromPairs ([]),
13 | {});
14 | eq (S.fromPairs ([S.Pair ('a') (1), S.Pair ('b') (2), S.Pair ('c') (3)]),
15 | {a: 1, b: 2, c: 3});
16 | eq (S.fromPairs ({x: S.Pair ('a') (1), y: S.Pair ('b') (2), z: S.Pair ('c') (3)}),
17 | {a: 1, b: 2, c: 3});
18 | eq (S.fromPairs ([S.Pair ('x') (1), S.Pair ('x') (2)]),
19 | {x: 2});
20 |
21 | });
22 |
--------------------------------------------------------------------------------
/test/fromRight.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('fromRight', () => {
9 |
10 | eq (String (S.fromRight), 'fromRight :: b -> Either a b -> b');
11 |
12 | eq (S.fromRight (123) (S.Right (789)), 789);
13 | eq (S.fromRight (123) (S.Left ('abc')), 123);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/fst.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('fst', () => {
9 |
10 | eq (String (S.fst), 'fst :: Pair a b -> a');
11 |
12 | eq (S.fst (S.Pair ('foo') (42)), 'foo');
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/get.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 | import vm from 'node:vm';
3 |
4 | import test from 'oletus';
5 | import $ from 'sanctuary-def';
6 |
7 | import S from '../index.js';
8 |
9 |
10 | test ('get', () => {
11 |
12 | eq (String (S.get), 'get :: (Any -> Boolean) -> String -> a -> Maybe b');
13 |
14 | eq (S.get (S.is ($.Number)) ('x') ({x: 0, y: 42}), S.Just (0));
15 | eq (S.get (S.is ($.Number)) ('y') ({x: 0, y: 42}), S.Just (42));
16 | eq (S.get (S.is ($.Number)) ('z') ({x: 0, y: 42}), S.Nothing);
17 | eq (S.get (S.is ($.String)) ('z') ({x: 0, y: 42}), S.Nothing);
18 | eq (S.get (S.is ($.String)) ('x') ({x: 0, y: 42}), S.Nothing);
19 |
20 | //
21 | const pattern = vm.runInNewContext ('/.*/');
22 | eq (S.get (S.is ($.RegExp)) ('x') ({x: pattern}), S.Just (pattern));
23 |
24 | eq (S.get (S.K (true)) ('valueOf') (null), S.Nothing);
25 | eq (S.get (S.K (true)) ('valueOf') (undefined), S.Nothing);
26 |
27 | eq (S.get (S.is ($.Array ($.Number))) ('x') ({x: [1, 2]}), S.Just ([1, 2]));
28 | eq (S.get (S.is ($.Array ($.Number))) ('x') ({x: [1, 2, null]}), S.Nothing);
29 |
30 | });
31 |
--------------------------------------------------------------------------------
/test/gets.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 | import vm from 'node:vm';
3 |
4 | import test from 'oletus';
5 | import $ from 'sanctuary-def';
6 |
7 | import S from '../index.js';
8 |
9 |
10 | test ('gets', () => {
11 |
12 | eq (String (S.gets), 'gets :: (Any -> Boolean) -> Array String -> a -> Maybe b');
13 |
14 | eq (S.gets (S.is ($.Number)) (['x']) ({x: {z: 0}, y: 42}), S.Nothing);
15 | eq (S.gets (S.is ($.Number)) (['y']) ({x: {z: 0}, y: 42}), S.Just (42));
16 | eq (S.gets (S.is ($.Number)) (['z']) ({x: {z: 0}, y: 42}), S.Nothing);
17 | eq (S.gets (S.is ($.Number)) (['x', 'z']) ({x: {z: 0}, y: 42}), S.Just (0));
18 | eq (S.gets (S.is ($.Number)) (['a', 'b', 'c']) ({x: {z: 0}, y: 42}), S.Nothing);
19 | eq (S.gets (S.is ($.Number)) ([]) ({x: {z: 0}, y: 42}), S.Nothing);
20 | eq (S.gets (S.is ($.Object)) ([]) ({x: {z: 0}, y: 42}), S.Just ({x: {z: 0}, y: 42}));
21 |
22 | //
23 | const pattern = vm.runInNewContext ('/.*/');
24 | eq (S.gets (S.is ($.RegExp)) (['x']) ({x: pattern}), S.Just (pattern));
25 |
26 | eq (S.gets (S.K (true)) (['valueOf']) (null), S.Nothing);
27 | eq (S.gets (S.K (true)) (['valueOf']) (undefined), S.Nothing);
28 |
29 | eq (S.gets (S.is ($.Array ($.Number))) (['x']) ({x: [1, 2]}), S.Just ([1, 2]));
30 | eq (S.gets (S.is ($.Array ($.Number))) (['x']) ({x: [1, 2, null]}), S.Nothing);
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/test/groupBy.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import jsc from 'jsverify';
4 | import test from 'oletus';
5 | import Z from 'sanctuary-type-classes';
6 |
7 | import S from '../index.js';
8 |
9 |
10 | test ('groupBy', () => {
11 |
12 | eq (String (S.groupBy), 'groupBy :: (a -> a -> Boolean) -> Array a -> Array (Array a)');
13 |
14 | eq (S.groupBy (x => y => x * y % 3 === 0) ([]), []);
15 | eq (S.groupBy (x => y => x * y % 3 === 0) ([1, 2, 3, 4, 5, 6, 7, 8, 9]), [[1], [2, 3], [4], [5, 6], [7], [8, 9]]);
16 | eq (S.groupBy (S.equals) ([1, 1, 2, 1, 1]), [[1, 1], [2], [1, 1]]);
17 | eq (S.groupBy (x => y => x + y === 0) ([2, -3, 3, 3, 3, 4, -4, 4]), [[2], [-3, 3, 3, 3], [4, -4], [4]]);
18 |
19 | jsc.assert (jsc.forall ('nat -> nat -> bool', 'array nat', (f, xs) => {
20 | const lhs = S.join (S.groupBy (f) (xs));
21 | const rhs = xs;
22 | return Z.equals (lhs, rhs);
23 | }), {tests: 1000});
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/test/gt.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('gt', () => {
9 |
10 | eq (String (S.gt), 'gt :: Ord a => a -> a -> Boolean');
11 |
12 | eq (S.filter (S.gt (3)) ([1, 2, 3, 4, 5]), [4, 5]);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/gte.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('gte', () => {
9 |
10 | eq (String (S.gte), 'gte :: Ord a => a -> a -> Boolean');
11 |
12 | eq (S.filter (S.gte (3)) ([1, 2, 3, 4, 5]), [3, 4, 5]);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/head.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('head', () => {
11 |
12 | eq (String (S.head), 'head :: Foldable f => f a -> Maybe a');
13 |
14 | eq (S.head ([]), S.Nothing);
15 | eq (S.head (['foo']), S.Just ('foo'));
16 | eq (S.head (['foo', 'bar']), S.Just ('foo'));
17 | eq (S.head (['foo', 'bar', 'baz']), S.Just ('foo'));
18 |
19 | eq (S.head (Nil), S.Nothing);
20 | eq (S.head (Cons ('foo') (Nil)), S.Just ('foo'));
21 | eq (S.head (Cons ('foo') (Cons ('bar') (Nil))), S.Just ('foo'));
22 | eq (S.head (Cons ('foo') (Cons ('bar') (Cons ('baz') (Nil)))), S.Just ('foo'));
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/test/id.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('id', () => {
9 |
10 | eq (String (S.id), 'id :: Category c => TypeRep c -> c');
11 |
12 | eq (S.id (Function) (42), 42);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/ifElse.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('ifElse', () => {
9 |
10 | eq (String (S.ifElse), 'ifElse :: (a -> Boolean) -> (a -> b) -> (a -> b) -> a -> b');
11 |
12 | eq (S.ifElse (S.odd) (S.sub (1)) (S.add (1)) (9), 8);
13 | eq (S.ifElse (S.odd) (S.sub (1)) (S.add (1)) (0), 1);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/init.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('init', () => {
11 |
12 | eq (String (S.init), 'init :: (Applicative f, Foldable f, Monoid f) => f a -> Maybe (f a)');
13 |
14 | eq (S.init ([]), S.Nothing);
15 | eq (S.init (['foo']), S.Just ([]));
16 | eq (S.init (['foo', 'bar']), S.Just (['foo']));
17 | eq (S.init (['foo', 'bar', 'baz']), S.Just (['foo', 'bar']));
18 |
19 | eq (S.init (Nil), S.Nothing);
20 | eq (S.init (Cons ('foo') (Nil)), S.Just (Nil));
21 | eq (S.init (Cons ('foo') (Cons ('bar') (Nil))), S.Just (Cons ('foo') (Nil)));
22 | eq (S.init (Cons ('foo') (Cons ('bar') (Cons ('baz') (Nil)))), S.Just (Cons ('foo') (Cons ('bar') (Nil))));
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/test/insert.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import jsc from 'jsverify';
4 | import test from 'oletus';
5 | import Z from 'sanctuary-type-classes';
6 |
7 | import S from '../index.js';
8 |
9 |
10 | test ('insert', () => {
11 |
12 | eq (String (S.insert), 'insert :: String -> a -> StrMap a -> StrMap a');
13 |
14 | eq (S.insert ('a') (1) ({}), {a: 1});
15 | eq (S.insert ('b') (2) ({a: 1}), {a: 1, b: 2});
16 | eq (S.insert ('c') (3) ({a: 1, b: 2, c: 4}), {a: 1, b: 2, c: 3});
17 |
18 | jsc.assert (jsc.forall (jsc.string, jsc.number, jsc.dict (jsc.number), (key, val, map) => {
19 | const insert = S.insert (key) (val);
20 | const lhs = insert (insert (map));
21 | const rhs = insert (map);
22 | return Z.equals (lhs, rhs);
23 | }), {tests: 1000});
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/test/intercalate.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('intercalate', () => {
11 |
12 | eq (String (S.intercalate), 'intercalate :: (Monoid a, Foldable f) => a -> f a -> a');
13 |
14 | eq (S.intercalate (', ') ([]), '');
15 | eq (S.intercalate (', ') (['foo']), 'foo');
16 | eq (S.intercalate (', ') (['foo', 'bar']), 'foo, bar');
17 | eq (S.intercalate (', ') (['foo', 'bar', 'baz']), 'foo, bar, baz');
18 | eq (S.intercalate ([0, 0, 0]) ([]), []);
19 | eq (S.intercalate ([0, 0, 0]) ([[1]]), [1]);
20 | eq (S.intercalate ([0, 0, 0]) ([[1], [2]]), [1, 0, 0, 0, 2]);
21 | eq (S.intercalate ([0, 0, 0]) ([[1], [2], [3]]), [1, 0, 0, 0, 2, 0, 0, 0, 3]);
22 | eq (S.intercalate ('.') (Nil), '');
23 | eq (S.intercalate ('.') (Cons ('x') (Nil)), 'x');
24 | eq (S.intercalate ('.') (Cons ('x') (Cons ('y') (Nil))), 'x.y');
25 | eq (S.intercalate ('.') (Cons ('x') (Cons ('y') (Cons ('z') (Nil)))), 'x.y.z');
26 |
27 | });
28 |
--------------------------------------------------------------------------------
/test/internal/List.cjs:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const {deepStrictEqual: eq} = require ('node:assert');
4 |
5 | const FL = require ('fantasy-land');
6 | const $ = require ('sanctuary-def');
7 | const show = require ('sanctuary-show');
8 | const Z = require ('sanctuary-type-classes');
9 | const type = require ('sanctuary-type-identifiers');
10 |
11 |
12 | const List = {prototype: _List.prototype};
13 |
14 | List.prototype.constructor = List;
15 |
16 | function _List(tag, head, tail) {
17 | this.isCons = tag === 'Cons';
18 | this.isNil = tag === 'Nil';
19 | if (this.isCons) {
20 | this.head = head;
21 | this.tail = tail;
22 | }
23 | }
24 |
25 | // listTypeIdent :: String
26 | const listTypeIdent = List.prototype['@@type'] = 'sanctuary/List';
27 |
28 | // Type :: Type -> Type
29 | List.Type = $.UnaryType
30 | (listTypeIdent)
31 | ('')
32 | ([])
33 | (x => type (x) === listTypeIdent)
34 | (list => list);
35 |
36 | // Nil :: List a
37 | const Nil = List.Nil = new _List ('Nil');
38 |
39 | // Cons :: a -> List a -> List a
40 | const Cons = List.Cons = function Cons(head) {
41 | eq (arguments.length, Cons.length);
42 | return function Cons$1(tail) {
43 | eq (arguments.length, Cons$1.length);
44 | return new _List ('Cons', head, tail);
45 | };
46 | };
47 |
48 | List[FL.empty] = () => Nil;
49 |
50 | List[FL.of] = x => Cons (x) (Nil);
51 |
52 | List[FL.zero] = List[FL.empty];
53 |
54 | List.prototype[FL.equals] = function(other) {
55 | return this.isNil ?
56 | other.isNil :
57 | other.isCons &&
58 | Z.equals (other.head, this.head) &&
59 | Z.equals (other.tail, this.tail);
60 | };
61 |
62 | List.prototype[FL.concat] = function(other) {
63 | return this.isNil ?
64 | other :
65 | Cons (this.head) (Z.concat (this.tail, other));
66 | };
67 |
68 | List.prototype[FL.filter] = function(pred) {
69 | return this.isNil ?
70 | Nil :
71 | pred (this.head) ?
72 | Cons (this.head) (Z.filter (pred, this.tail)) :
73 | Z.filter (pred, this.tail);
74 | };
75 |
76 | List.prototype[FL.map] = function(f) {
77 | return this.isNil ?
78 | Nil :
79 | Cons (f (this.head)) (Z.map (f, this.tail));
80 | };
81 |
82 | List.prototype[FL.ap] = function(other) {
83 | return this.isNil || other.isNil ?
84 | Nil :
85 | Z.concat (Z.map (other.head, this), Z.ap (other.tail, this));
86 | };
87 |
88 | List.prototype[FL.chain] = function(f) {
89 | return this.isNil ?
90 | Nil :
91 | Z.concat (f (this.head), Z.chain (f, this.tail));
92 | };
93 |
94 | List.prototype[FL.alt] = List.prototype[FL.concat];
95 |
96 | List.prototype[FL.reduce] = function(f, x) {
97 | return this.isNil ?
98 | x :
99 | Z.reduce (f, f (x, this.head), this.tail);
100 | };
101 |
102 | List.prototype[FL.traverse] = function(typeRep, f) {
103 | return this.isNil ?
104 | Z.of (typeRep, Nil) :
105 | Z.ap (Z.map (Cons, f (this.head)), Z.traverse (typeRep, f, this.tail));
106 | };
107 |
108 | List.prototype.inspect =
109 | List.prototype['@@show'] = function() {
110 | return this.isNil ?
111 | 'Nil' :
112 | 'Cons (' + show (this.head) + ') (' + show (this.tail) + ')';
113 | };
114 |
115 | module.exports = List;
116 |
--------------------------------------------------------------------------------
/test/internal/List.mjs:
--------------------------------------------------------------------------------
1 | import List from './List.cjs';
2 |
3 | export {List, Nil, Cons};
4 |
5 | const {Nil, Cons} = List;
6 |
--------------------------------------------------------------------------------
/test/internal/Sum.cjs:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const FL = require ('fantasy-land');
4 | const $ = require ('sanctuary-def');
5 | const show = require ('sanctuary-show');
6 | const Z = require ('sanctuary-type-classes');
7 | const type = require ('sanctuary-type-identifiers');
8 |
9 |
10 | // Sum :: Number -> Sum
11 | function Sum(value) {
12 | if (!(this instanceof Sum)) return new Sum (value);
13 | this.value = value;
14 | }
15 |
16 | // sumTypeIdent :: String
17 | const sumTypeIdent = Sum.prototype['@@type'] = 'sanctuary/Sum';
18 |
19 | // Type :: Type
20 | Sum.Type = $.NullaryType
21 | (sumTypeIdent)
22 | ('')
23 | ([])
24 | (x => type (x) === sumTypeIdent);
25 |
26 | Sum[FL.empty] = () => Sum (0);
27 |
28 | Sum.prototype[FL.equals] = function(other) {
29 | return Z.equals (this.value, other.value);
30 | };
31 |
32 | Sum.prototype[FL.concat] = function(other) {
33 | return Sum (this.value + other.value);
34 | };
35 |
36 | Sum.prototype[FL.invert] = function() {
37 | return Sum (-this.value);
38 | };
39 |
40 | Sum.prototype.inspect =
41 | Sum.prototype['@@show'] = function() {
42 | return 'Sum (' + show (this.value) + ')';
43 | };
44 |
45 | module.exports = Sum;
46 |
--------------------------------------------------------------------------------
/test/internal/Sum.mjs:
--------------------------------------------------------------------------------
1 | import Sum from './Sum.cjs';
2 |
3 | export {Sum};
4 |
--------------------------------------------------------------------------------
/test/internal/area.js:
--------------------------------------------------------------------------------
1 | export default a => b => c => {
2 | if (Math.max (a, b, c) < (a + b + c) / 2) {
3 | const s = (a + b + c) / 2;
4 | return Math.sqrt (s * (s - a) * (s - b) * (s - c));
5 | } else {
6 | throw new Error ('Impossible triangle');
7 | }
8 | };
9 |
--------------------------------------------------------------------------------
/test/internal/factorial.js:
--------------------------------------------------------------------------------
1 | export default function factorial(n) {
2 | if (n < 0) {
3 | // eslint-disable-next-line no-throw-literal
4 | throw 'Cannot determine factorial of negative number';
5 | } else if (n === 0) {
6 | return 1;
7 | } else {
8 | return n * factorial (n - 1);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/test/internal/rem.js:
--------------------------------------------------------------------------------
1 | export default x => y => {
2 | if (y === 0) {
3 | throw new Error ('Cannot divide by zero');
4 | } else {
5 | return x % y;
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/test/internal/sanctuary.js:
--------------------------------------------------------------------------------
1 | import $ from 'sanctuary-def';
2 |
3 | import S from '../../index.js';
4 |
5 | import {List} from './List.mjs';
6 | import {Sum} from './Sum.mjs';
7 |
8 |
9 | // env :: Array Type
10 | const env = S.env.concat ([
11 | List.Type ($.Unknown),
12 | Sum.Type,
13 | ]);
14 |
15 | export default S.create ({checkTypes: true, env});
16 |
--------------------------------------------------------------------------------
/test/internal/strMap.js:
--------------------------------------------------------------------------------
1 | const proto = Object.create (null);
2 |
3 | Object.defineProperty (
4 | proto,
5 | 'non-enumerable inherited property',
6 | {enumerable: false, value: 'non-enumerable inherited property'}
7 | );
8 | Object.defineProperty (
9 | proto,
10 | 'enumerable inherited property',
11 | {enumerable: true, value: 'enumerable inherited property'}
12 | );
13 |
14 | const strMap = Object.create (proto);
15 |
16 | Object.defineProperty (
17 | strMap,
18 | 'non-enumerable own property',
19 | {enumerable: false, value: 'non-enumerable own property'}
20 | );
21 | Object.defineProperty (
22 | strMap,
23 | 'enumerable own property',
24 | {enumerable: true, value: 'enumerable own property'}
25 | );
26 |
27 | export default strMap;
28 |
--------------------------------------------------------------------------------
/test/invert.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Sum} from './internal/Sum.mjs';
8 |
9 |
10 | test ('invert', () => {
11 |
12 | eq (String (S.invert), 'invert :: Group g => g -> g');
13 |
14 | eq (S.invert (Sum (5)), Sum (-5));
15 | eq (S.invert (Sum (-5)), Sum (5));
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/is.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import $ from 'sanctuary-def';
5 |
6 | import S from '../index.js';
7 |
8 | import {Sum} from './internal/Sum.mjs';
9 |
10 |
11 | test ('is', () => {
12 |
13 | eq (String (S.is), 'is :: Type -> Any -> Boolean');
14 |
15 | eq (S.is ($.Boolean) (true), true);
16 | eq (S.is ($.Boolean) (false), true);
17 | eq (S.is ($.Boolean) (new Boolean (true)), false);
18 | eq (S.is ($.Boolean) (new Boolean (false)), false);
19 |
20 | eq (S.is ($.Array ($.Integer)) (null), false);
21 | eq (S.is ($.Array ($.Integer)) (undefined), false);
22 | eq (S.is ($.Array ($.Integer)) (['1', '2', '3']), false);
23 | eq (S.is ($.Array ($.Integer)) ([1, 2, 3.14]), false);
24 | eq (S.is ($.Array ($.Integer)) ([1, 2, 3]), true);
25 | eq (S.is ($.Array ($.Integer)) ([]), true);
26 |
27 | eq (S.is ($.Maybe ($.Integer)) (S.Nothing), true);
28 | eq (S.is ($.Maybe ($.Integer)) (S.Just (0)), true);
29 | eq (S.is ($.Maybe ($.Integer)) (S.Left (0)), false);
30 | eq (S.is ($.Maybe ($.Integer)) (S.Right (0)), false);
31 |
32 | eq (S.is ($.Either ($.String) ($.Integer)) (S.Nothing), false);
33 | eq (S.is ($.Either ($.String) ($.Integer)) (S.Just (0)), false);
34 | eq (S.is ($.Either ($.String) ($.Integer)) (S.Left (0)), false);
35 | eq (S.is ($.Either ($.String) ($.Integer)) (S.Right ('')), false);
36 | eq (S.is ($.Either ($.String) ($.Integer)) (S.Left ('')), true);
37 | eq (S.is ($.Either ($.String) ($.Integer)) (S.Right (0)), true);
38 |
39 | const a = $.TypeVariable ('a');
40 |
41 | eq (S.is ($.Array (a)) ([]), true);
42 | eq (S.is ($.Array (a)) ([1, 2, 3]), true);
43 | eq (S.is ($.Array (a)) (['foo', 'bar', 'baz']), true);
44 | eq (S.is ($.Array (a)) (['foo', true, 42]), false);
45 | eq (S.is ($.Array (a)) ([Sum (1), Sum (2), Sum (3)]), false);
46 |
47 | eq ((S.create ({checkTypes: true, env: []})).is ($.Array (a)) ([]), false);
48 | eq ((S.create ({checkTypes: true, env: [$.String]})).is ($.Array (a)) ([]), true);
49 | eq ((S.create ({checkTypes: true, env: [$.String]})).is ($.Array (a)) ([1, 2, 3]), false);
50 | eq ((S.create ({checkTypes: true, env: [$.Number]})).is ($.Array (a)) ([1, 2, 3]), true);
51 | eq ((S.create ({checkTypes: true, env: [Sum.Type]})).is ($.Array (a)) ([Sum (1), Sum (2), Sum (3)]), true);
52 |
53 | });
54 |
--------------------------------------------------------------------------------
/test/isJust.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('isJust', () => {
9 |
10 | eq (String (S.isJust), 'isJust :: Maybe a -> Boolean');
11 |
12 | eq (S.isJust (S.Nothing), false);
13 | eq (S.isJust (S.Just (42)), true);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/isLeft.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('isLeft', () => {
9 |
10 | eq (String (S.isLeft), 'isLeft :: Either a b -> Boolean');
11 |
12 | eq (S.isLeft (S.Left (42)), true);
13 | eq (S.isLeft (S.Right (42)), false);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/isNothing.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('isNothing', () => {
9 |
10 | eq (String (S.isNothing), 'isNothing :: Maybe a -> Boolean');
11 |
12 | eq (S.isNothing (S.Nothing), true);
13 | eq (S.isNothing (S.Just (42)), false);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/isRight.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('isRight', () => {
9 |
10 | eq (String (S.isRight), 'isRight :: Either a b -> Boolean');
11 |
12 | eq (S.isRight (S.Left (42)), false);
13 | eq (S.isRight (S.Right (42)), true);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/join.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('join', () => {
9 |
10 | eq (String (S.join), 'join :: Chain m => m (m a) -> m a');
11 |
12 | eq (S.join ([]), []);
13 | eq (S.join ([[]]), []);
14 | eq (S.join ([[[]]]), [[]]);
15 | eq (S.join ([[1], [2], [3]]), [1, 2, 3]);
16 | eq (S.join ([[[1, 2, 3]]]), [[1, 2, 3]]);
17 | eq (S.join (S.Nothing), S.Nothing);
18 | eq (S.join (S.Just (S.Nothing)), S.Nothing);
19 | eq (S.join (S.Just (S.Just (1))), S.Just (1));
20 | eq (S.join (S.Just (S.Just (S.Just (1)))), S.Just (S.Just (1)));
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/test/joinWith.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('joinWith', () => {
9 |
10 | eq (String (S.joinWith), 'joinWith :: String -> Array String -> String');
11 |
12 | eq (S.joinWith ('') (['a', 'b', 'c']), 'abc');
13 | eq (S.joinWith (':') ([]), '');
14 | eq (S.joinWith (':') (['']), '');
15 | eq (S.joinWith (':') (['', '']), ':');
16 | eq (S.joinWith (':') (['', 'foo', '']), ':foo:');
17 | eq (S.joinWith (':') (['foo', 'bar', 'baz']), 'foo:bar:baz');
18 | eq (S.joinWith ('::') (['foo', 'bar', 'baz']), 'foo::bar::baz');
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/justs.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('justs', () => {
11 |
12 | eq (String (S.justs), 'justs :: (Filterable f, Functor f) => f (Maybe a) -> f a');
13 |
14 | eq (S.justs ([]), []);
15 | eq (S.justs ([S.Nothing, S.Nothing]), []);
16 | eq (S.justs ([S.Nothing, S.Just ('b')]), ['b']);
17 | eq (S.justs ([S.Just ('a'), S.Nothing]), ['a']);
18 | eq (S.justs ([S.Just ('a'), S.Just ('b')]), ['a', 'b']);
19 |
20 | eq (S.justs ({}), {});
21 | eq (S.justs ({x: S.Nothing, y: S.Nothing}), {});
22 | eq (S.justs ({x: S.Nothing, y: S.Just (2)}), {y: 2});
23 | eq (S.justs ({x: S.Just (1), y: S.Nothing}), {x: 1});
24 | eq (S.justs ({x: S.Just (1), y: S.Just (2)}), {x: 1, y: 2});
25 |
26 | eq (S.justs (S.Nothing), S.Nothing);
27 | eq (S.justs (S.Just (S.Nothing)), S.Nothing);
28 | eq (S.justs (S.Just (S.Just (1))), S.Just (1));
29 |
30 | eq (S.justs (Nil), Nil);
31 | eq (S.justs (Cons (S.Nothing) (Cons (S.Nothing) (Nil))), Nil);
32 | eq (S.justs (Cons (S.Nothing) (Cons (S.Just (2)) (Nil))), Cons (2) (Nil));
33 | eq (S.justs (Cons (S.Just (1)) (Cons (S.Nothing) (Nil))), Cons (1) (Nil));
34 | eq (S.justs (Cons (S.Just (1)) (Cons (S.Just (2)) (Nil))), Cons (1) (Cons (2) (Nil)));
35 |
36 | });
37 |
--------------------------------------------------------------------------------
/test/keys.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 | import strMap from './internal/strMap.js';
8 |
9 |
10 | test ('keys', () => {
11 |
12 | eq (String (S.keys), 'keys :: StrMap a -> Array String');
13 |
14 | eq (S.sort (S.keys ({})), []);
15 | eq (S.sort (S.keys ({a: 1, b: 2, c: 3})), ['a', 'b', 'c']);
16 |
17 | eq (S.keys (strMap), ['enumerable own property']);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/last.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('last', () => {
11 |
12 | eq (String (S.last), 'last :: Foldable f => f a -> Maybe a');
13 |
14 | eq (S.last ([]), S.Nothing);
15 | eq (S.last (['foo']), S.Just ('foo'));
16 | eq (S.last (['foo', 'bar']), S.Just ('bar'));
17 | eq (S.last (['foo', 'bar', 'baz']), S.Just ('baz'));
18 |
19 | eq (S.last (Nil), S.Nothing);
20 | eq (S.last (Cons ('foo') (Nil)), S.Just ('foo'));
21 | eq (S.last (Cons ('foo') (Cons ('bar') (Nil))), S.Just ('bar'));
22 | eq (S.last (Cons ('foo') (Cons ('bar') (Cons ('baz') (Nil)))), S.Just ('baz'));
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/test/lefts.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('lefts', () => {
11 |
12 | eq (String (S.lefts), 'lefts :: (Filterable f, Functor f) => f (Either a b) -> f a');
13 |
14 | eq (S.lefts ([]), []);
15 | eq (S.lefts ([S.Right (2), S.Right (1)]), []);
16 | eq (S.lefts ([S.Right (2), S.Left ('b')]), ['b']);
17 | eq (S.lefts ([S.Left ('a'), S.Right (1)]), ['a']);
18 | eq (S.lefts ([S.Left ('a'), S.Left ('b')]), ['a', 'b']);
19 |
20 | eq (S.lefts ({}), {});
21 | eq (S.lefts ({x: S.Right (2), y: S.Right (1)}), {});
22 | eq (S.lefts ({x: S.Right (2), y: S.Left ('b')}), {y: 'b'});
23 | eq (S.lefts ({x: S.Left ('a'), y: S.Right (1)}), {x: 'a'});
24 | eq (S.lefts ({x: S.Left ('a'), y: S.Left ('b')}), {x: 'a', y: 'b'});
25 |
26 | eq (S.lefts (S.Nothing), S.Nothing);
27 | eq (S.lefts (S.Just (S.Right (1))), S.Nothing);
28 | eq (S.lefts (S.Just (S.Left ('a'))), S.Just ('a'));
29 |
30 | eq (S.lefts (Nil), Nil);
31 | eq (S.lefts (Cons (S.Right (2)) (Cons (S.Right (1)) (Nil))), Nil);
32 | eq (S.lefts (Cons (S.Right (2)) (Cons (S.Left ('b')) (Nil))), Cons ('b') (Nil));
33 | eq (S.lefts (Cons (S.Left ('a')) (Cons (S.Right (1)) (Nil))), Cons ('a') (Nil));
34 | eq (S.lefts (Cons (S.Left ('a')) (Cons (S.Left ('b')) (Nil))), Cons ('a') (Cons ('b') (Nil)));
35 |
36 | });
37 |
--------------------------------------------------------------------------------
/test/lift2.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('lift2', () => {
9 |
10 | eq (String (S.lift2), 'lift2 :: Apply f => (a -> b -> c) -> f a -> f b -> f c');
11 |
12 | eq (S.lift2 (S.add) (S.Just (3)) (S.Just (3)), S.Just (6));
13 | eq (S.lift2 (S.add) (S.Nothing) (S.Just (3)), S.Nothing);
14 |
15 | eq (S.lift2 (S.add) (S.Right (3)) (S.Left (4)), S.Left (4));
16 | eq (S.lift2 (S.add) (S.Right (3)) (S.Right (4)), S.Right (7));
17 |
18 | eq (S.lift2 (S.add) ([1, 2]) ([10, 20]), [11, 21, 12, 22]);
19 | eq (S.lift2 (S.add) ([]) ([1, 2]), []);
20 |
21 | eq (S.lift2 (S.and) (S.even) (S.gt (0)) (42), true);
22 | eq (S.lift2 (S.and) (S.even) (S.gt (0)) (43), false);
23 | eq (S.lift2 (S.and) (S.even) (S.gt (0)) (-42), false);
24 | eq (S.lift2 (S.and) (S.even) (S.gt (0)) (-43), false);
25 |
26 | });
27 |
--------------------------------------------------------------------------------
/test/lift3.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 | import area from './internal/area.js';
8 |
9 |
10 | test ('lift3', () => {
11 |
12 | eq (String (S.lift3), 'lift3 :: Apply f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d');
13 |
14 | eq (S.lift3 (S.reduce) (S.Just (S.add)) (S.Just (0)) (S.Just ([1, 2, 3])), S.Just (6));
15 | eq (S.lift3 (S.reduce) (S.Just (S.add)) (S.Just (0)) (S.Nothing), S.Nothing);
16 |
17 | eq (S.lift3 (S.reduce) (S.Right (S.add)) (S.Right (0)) (S.Right ([1, 2, 3])), S.Right (6));
18 | eq (S.lift3 (S.reduce) (S.Right (S.add)) (S.Right (0)) (S.Left ('WHOOPS')), S.Left ('WHOOPS'));
19 |
20 | eq (S.lift3 (S.reduce) ([S.add]) ([0]) ([[1, 2, 3]]), [6]);
21 | eq (S.lift3 (S.reduce) ([S.add]) ([0]) ([]), []);
22 |
23 | eq (S.lift3 (area) (S.sub (1)) (S.I) (S.add (1)) (4), 6);
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/test/lines.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('lines', () => {
9 |
10 | eq (String (S.lines), 'lines :: String -> Array String');
11 |
12 | eq (S.lines (''), []);
13 | eq (S.lines ('\n'), ['']);
14 | eq (S.lines ('\n\n'), ['', '']);
15 | eq (S.lines ('foo\nbar\nbaz'), ['foo', 'bar', 'baz']);
16 | eq (S.lines ('foo\nbar\nbaz\n'), ['foo', 'bar', 'baz']);
17 | eq (S.lines ('\tfoo\r\n\tbar\r\n\tbaz\r\n'), ['\tfoo', '\tbar', '\tbaz']);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/lt.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('lt', () => {
9 |
10 | eq (String (S.lt), 'lt :: Ord a => a -> a -> Boolean');
11 |
12 | eq (S.filter (S.lt (3)) ([1, 2, 3, 4, 5]), [1, 2]);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/lte.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('lte', () => {
9 |
10 | eq (String (S.lte), 'lte :: Ord a => a -> a -> Boolean');
11 |
12 | eq (S.filter (S.lte (3)) ([1, 2, 3, 4, 5]), [1, 2, 3]);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/map.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('map', () => {
9 |
10 | eq (String (S.map), 'map :: Functor f => (a -> b) -> f a -> f b');
11 |
12 | eq (S.map (S.not) (S.odd) (2), true);
13 | eq (S.map (S.not) (S.odd) (3), false);
14 |
15 | eq (S.map (S.mult (4)) (S.Just (2)), S.Just (8));
16 | eq (S.map (S.mult (4)) (S.Nothing), S.Nothing);
17 |
18 | eq (S.map (S.mult (4)) (S.Left (3)), S.Left (3));
19 | eq (S.map (S.mult (4)) (S.Right (2)), S.Right (8));
20 |
21 | eq (S.map (S.mult (2)) ([1, 2, 3]), [2, 4, 6]);
22 | eq (S.map (S.mult (2)) ([]), []);
23 |
24 | eq (S.map (S.mult (2)) ({a: 1, b: 2, c: 3}), {a: 2, b: 4, c: 6});
25 | eq (S.map (S.mult (2)) ({}), {});
26 |
27 | });
28 |
--------------------------------------------------------------------------------
/test/mapLeft.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('mapLeft', () => {
9 |
10 | eq (String (S.mapLeft), 'mapLeft :: Bifunctor p => (a -> b) -> p a c -> p b c');
11 |
12 | eq (S.mapLeft (S.toUpper) (S.Left ('xxx')), S.Left ('XXX'));
13 | eq (S.mapLeft (S.toUpper) (S.Right (1000)), S.Right (1000));
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/mapMaybe.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('mapMaybe', () => {
11 |
12 | eq (String (S.mapMaybe), 'mapMaybe :: (Filterable f, Functor f) => (a -> Maybe b) -> f a -> f b');
13 |
14 | eq (S.mapMaybe (S.head) ([]), []);
15 | eq (S.mapMaybe (S.head) ([[], [], []]), []);
16 | eq (S.mapMaybe (S.head) ([[1, 2], [3, 4], [5, 6]]), [1, 3, 5]);
17 | eq (S.mapMaybe (S.head) ([[1], [], [3], [], [5], []]), [1, 3, 5]);
18 |
19 | eq (S.mapMaybe (S.head) ({}), {});
20 | eq (S.mapMaybe (S.head) ({a: [], b: [], c: []}), {});
21 | eq (S.mapMaybe (S.head) ({a: [1, 2], b: [3, 4], c: [5, 6]}), {a: 1, b: 3, c: 5});
22 | eq (S.mapMaybe (S.head) ({a: [1], b: [], c: [3], d: [], e: [5], f: []}), {a: 1, c: 3, e: 5});
23 |
24 | eq (S.mapMaybe (S.head) (S.Nothing), S.Nothing);
25 | eq (S.mapMaybe (S.head) (S.Just ([])), S.Nothing);
26 | eq (S.mapMaybe (S.head) (S.Just ([1, 2])), S.Just (1));
27 |
28 | eq (S.mapMaybe (S.head) (Nil),
29 | Nil);
30 | eq (S.mapMaybe (S.head) (Cons ([]) (Cons ([]) (Cons ([]) (Nil)))),
31 | Nil);
32 | eq (S.mapMaybe (S.head) (Cons ([1, 2]) (Cons ([3, 4]) (Cons ([5, 6]) (Nil)))),
33 | Cons (1) (Cons (3) (Cons (5) (Nil))));
34 | eq (S.mapMaybe (S.head) (Cons ([1]) (Cons ([]) (Cons ([3]) (Cons ([]) (Cons ([5]) (Cons ([]) (Nil))))))),
35 | Cons (1) (Cons (3) (Cons (5) (Nil))));
36 |
37 | });
38 |
--------------------------------------------------------------------------------
/test/match.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import jsc from 'jsverify';
4 | import test from 'oletus';
5 | import Z from 'sanctuary-type-classes';
6 |
7 | import S from '../index.js';
8 |
9 |
10 | test ('match', () => {
11 |
12 | eq (String (S.match), 'match :: NonGlobalRegExp -> String -> Maybe (Array (Maybe String))');
13 |
14 | const scheme = '([a-z][a-z0-9+.-]*)';
15 | const authentication = '(.*?):(.*?)@';
16 | const hostname = '(.*?)';
17 | const port = ':([0-9]*)';
18 | const pattern = S.regex ('') (scheme + '://(?:' + authentication + ')?' + hostname + '(?:' + port + ')?(?!\\S)');
19 |
20 | eq (S.match (pattern) ('URL: N/A'),
21 | S.Nothing);
22 |
23 | eq (S.match (pattern) ('URL: http://example.com'),
24 | S.Just ([S.Just ('http'), S.Nothing, S.Nothing, S.Just ('example.com'), S.Nothing]));
25 |
26 | eq (S.match (pattern) ('URL: http://user:pass@example.com:80'),
27 | S.Just ([S.Just ('http'), S.Just ('user'), S.Just ('pass'), S.Just ('example.com'), S.Just ('80')]));
28 |
29 | jsc.assert (jsc.forall (jsc.string, s => {
30 | const p = '([A-Za-z]+)';
31 | const lhs = S.head (S.matchAll (S.regex ('g') (p)) (s));
32 | const rhs = S.match (S.regex ('') (p)) (s);
33 | return Z.equals (lhs, rhs);
34 | }), {tests: 1000});
35 |
36 | });
37 |
--------------------------------------------------------------------------------
/test/matchAll.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('matchAll', () => {
9 |
10 | eq (String (S.matchAll), 'matchAll :: GlobalRegExp -> String -> Array (Array (Maybe String))');
11 |
12 | const pattern = S.regex ('g') ('<(h[1-6])(?: id="([^"]*)")?>([^<]*)\\1>');
13 |
14 | eq (S.matchAll (pattern) (''), []);
15 |
16 | eq (S.matchAll (pattern) ('Foo
\nBar
\nBaz
\n'),
17 | [[S.Just ('h1'), S.Nothing, S.Just ('Foo')],
18 | [S.Just ('h2'), S.Just ('bar'), S.Just ('Bar')],
19 | [S.Just ('h2'), S.Just ('baz'), S.Just ('Baz')]]);
20 |
21 | eq (pattern.lastIndex, 0);
22 |
23 | {
24 | // `lastIndex` property is respected and preserved
25 | const pattern = /([0-9])/g;
26 | eq (pattern.lastIndex, 0);
27 | pattern.exec ('123');
28 | eq (pattern.lastIndex, 1);
29 | eq (S.matchAll (pattern) ('123'), [[S.Just ('2')], [S.Just ('3')]]);
30 | eq (pattern.lastIndex, 1);
31 | }
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/test/max.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('max', () => {
9 |
10 | eq (String (S.max), 'max :: Ord a => a -> a -> a');
11 |
12 | eq (S.max (10) (2), 10);
13 | eq (S.max (2) (10), 10);
14 | eq (S.max (0.1) (0.01), 0.1);
15 | eq (S.max (0.01) (0.1), 0.1);
16 | eq (S.max (Infinity) (-Infinity), Infinity);
17 | eq (S.max (-Infinity) (Infinity), Infinity);
18 |
19 | eq (S.max (new Date (10)) (new Date (2)), new Date (10));
20 | eq (S.max (new Date (2)) (new Date (10)), new Date (10));
21 |
22 | eq (S.max ('abc') ('xyz'), 'xyz');
23 | eq (S.max ('xyz') ('abc'), 'xyz');
24 | eq (S.max ('10') ('2'), '2');
25 | eq (S.max ('2') ('10'), '2');
26 | eq (S.max ('A') ('a'), 'a');
27 | eq (S.max ('a') ('A'), 'a');
28 |
29 | });
30 |
--------------------------------------------------------------------------------
/test/maybe.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('maybe', () => {
9 |
10 | eq (String (S.maybe), 'maybe :: b -> (a -> b) -> Maybe a -> b');
11 |
12 | eq (S.maybe (0) (Math.sqrt) (S.Nothing), 0);
13 | eq (S.maybe (0) (Math.sqrt) (S.Just (9)), 3);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/maybeToNullable.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('maybeToNullable', () => {
9 |
10 | eq (String (S.maybeToNullable), 'maybeToNullable :: Maybe a -> Nullable a');
11 |
12 | eq (S.maybeToNullable (S.Nothing), null);
13 | eq (S.maybeToNullable (S.Just (42)), 42);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/maybe_.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 | import factorial from './internal/factorial.js';
8 |
9 |
10 | test ('maybe_', () => {
11 |
12 | eq (String (S.maybe_), 'maybe_ :: (() -> b) -> (a -> b) -> Maybe a -> b');
13 |
14 | eq (S.maybe_ (() => factorial (10)) (Math.sqrt) (S.Nothing), 3628800);
15 | eq (S.maybe_ (() => factorial (10)) (Math.sqrt) (S.Just (9)), 3);
16 |
17 | let count = 0;
18 | eq (S.maybe_ (() => count += 1) (Math.sqrt) (S.Just (9)), 3);
19 | eq (count, 0);
20 |
21 | });
22 |
--------------------------------------------------------------------------------
/test/min.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('min', () => {
9 |
10 | eq (String (S.min), 'min :: Ord a => a -> a -> a');
11 |
12 | eq (S.min (10) (2), 2);
13 | eq (S.min (2) (10), 2);
14 | eq (S.min (0.1) (0.01), 0.01);
15 | eq (S.min (0.01) (0.1), 0.01);
16 | eq (S.min (Infinity) (-Infinity), -Infinity);
17 | eq (S.min (-Infinity) (Infinity), -Infinity);
18 |
19 | eq (S.min (new Date (10)) (new Date (2)), new Date (2));
20 | eq (S.min (new Date (2)) (new Date (10)), new Date (2));
21 |
22 | eq (S.min ('abc') ('xyz'), 'abc');
23 | eq (S.min ('xyz') ('abc'), 'abc');
24 | eq (S.min ('10') ('2'), '10');
25 | eq (S.min ('2') ('10'), '10');
26 | eq (S.min ('A') ('a'), 'A');
27 | eq (S.min ('a') ('A'), 'A');
28 |
29 | });
30 |
--------------------------------------------------------------------------------
/test/mult.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('mult', () => {
9 |
10 | eq (String (S.mult), 'mult :: FiniteNumber -> FiniteNumber -> FiniteNumber');
11 |
12 | eq (S.mult (4) (2), 8);
13 | eq (S.mult (4) (-2), -8);
14 | eq (S.mult (-4) (-2), 8);
15 | eq (S.mult (1.5) (3), 4.5);
16 | eq (S.mult (-1.5) (3), -4.5);
17 | eq (S.mult (-1.5) (-3), 4.5);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/negate.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('negate', () => {
9 |
10 | eq (String (S.negate), 'negate :: ValidNumber -> ValidNumber');
11 |
12 | eq (S.negate (0.5), -0.5);
13 | eq (S.negate (-0.5), 0.5);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/none.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import jsc from 'jsverify';
4 | import test from 'oletus';
5 | import Z from 'sanctuary-type-classes';
6 |
7 | import S from './internal/sanctuary.js';
8 |
9 | import {Nil, Cons} from './internal/List.mjs';
10 |
11 |
12 | test ('none', () => {
13 |
14 | eq (String (S.none), 'none :: Foldable f => (a -> Boolean) -> f a -> Boolean');
15 |
16 | eq (S.none (S.gt (0)) ([]), true);
17 | eq (S.none (S.gt (0)) ([0]), true);
18 | eq (S.none (S.gt (0)) ([1]), false);
19 | eq (S.none (S.gt (0)) ([0, 0]), true);
20 | eq (S.none (S.gt (0)) ([0, 1]), false);
21 | eq (S.none (S.gt (0)) ([1, 0]), false);
22 | eq (S.none (S.gt (0)) ([1, 1]), false);
23 |
24 | eq (S.none (S.gt (0)) (Nil), true);
25 | eq (S.none (S.gt (0)) (Cons (0) (Nil)), true);
26 | eq (S.none (S.gt (0)) (Cons (1) (Nil)), false);
27 | eq (S.none (S.gt (0)) (Cons (0) (Cons (0) (Nil))), true);
28 | eq (S.none (S.gt (0)) (Cons (0) (Cons (1) (Nil))), false);
29 | eq (S.none (S.gt (0)) (Cons (1) (Cons (0) (Nil))), false);
30 | eq (S.none (S.gt (0)) (Cons (1) (Cons (1) (Nil))), false);
31 |
32 | eq (S.none (S.gt (0)) (S.Nothing), true);
33 | eq (S.none (S.gt (0)) (S.Just (0)), true);
34 | eq (S.none (S.gt (0)) (S.Just (1)), false);
35 |
36 | jsc.assert (jsc.forall (jsc.array (jsc.integer), xs => {
37 | const p = S.odd;
38 | const lhs = S.none (p) (xs);
39 | const rhs = S.not (S.any (p) (xs));
40 | return Z.equals (lhs, rhs);
41 | }), {tests: 1000});
42 |
43 | jsc.assert (jsc.forall (jsc.array (jsc.integer), xs => {
44 | const p = S.odd;
45 | const lhs = S.none (p) (xs);
46 | const rhs = S.all (S.complement (p)) (xs);
47 | return Z.equals (lhs, rhs);
48 | }), {tests: 1000});
49 |
50 | });
51 |
--------------------------------------------------------------------------------
/test/not.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('not', () => {
9 |
10 | eq (String (S.not), 'not :: Boolean -> Boolean');
11 |
12 | eq (S.not (false), true);
13 | eq (S.not (true), false);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/odd.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('odd', () => {
9 |
10 | eq (String (S.odd), 'odd :: Integer -> Boolean');
11 |
12 | eq (S.odd (1), true);
13 | eq (S.odd (-1), true);
14 |
15 | eq (S.odd (0), false);
16 | eq (S.odd (2), false);
17 | eq (S.odd (-2), false);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/of.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import Identity from 'sanctuary-identity';
5 |
6 | import S from './internal/sanctuary.js';
7 |
8 |
9 | test ('of', () => {
10 |
11 | eq (String (S.of), 'of :: Applicative f => TypeRep (f a) -> a -> f a');
12 |
13 | eq (S.of (Array) (42), [42]);
14 | eq (S.of (Function) (42) (null), 42);
15 | eq (S.of (S.Maybe) (42), S.Just (42));
16 | eq (S.of (S.Either) (42), S.Right (42));
17 | eq (S.of (Identity) (42), Identity (42));
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/on.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 | import rem from './internal/rem.js';
8 |
9 |
10 | test ('on', () => {
11 |
12 | eq (String (S.on), 'on :: (b -> b -> c) -> (a -> b) -> a -> a -> c');
13 |
14 | eq (S.on (rem) (S.prop ('x')) ({x: 5, y: 5}) ({x: 3, y: 3}), 2);
15 | eq (S.on (S.concat) (S.reverse) ([1, 2, 3]) ([4, 5, 6]), [3, 2, 1, 6, 5, 4]);
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/or.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('or', () => {
9 |
10 | eq (String (S.or), 'or :: Boolean -> Boolean -> Boolean');
11 |
12 | eq (S.or (false) (false), false);
13 | eq (S.or (false) (true), true);
14 | eq (S.or (true) (false), true);
15 | eq (S.or (true) (true), true);
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module"
3 | }
4 |
--------------------------------------------------------------------------------
/test/pairs.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 | import strMap from './internal/strMap.js';
8 |
9 |
10 | test ('pairs', () => {
11 |
12 | eq (String (S.pairs), 'pairs :: StrMap a -> Array (Pair String a)');
13 |
14 | eq (S.sort (S.pairs ({})), []);
15 | eq (S.sort (S.pairs ({a: 1, b: 2, c: 3})), [S.Pair ('a') (1), S.Pair ('b') (2), S.Pair ('c') (3)]);
16 |
17 | eq (S.pairs (strMap), [S.Pair ('enumerable own property') ('enumerable own property')]);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/pair~.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('pair', () => {
9 |
10 | eq (String (S.pair), 'pair :: (a -> b -> c) -> Pair a b -> c');
11 |
12 | eq (S.pair (S.concat) (S.Pair ('foo') ('bar')), 'foobar');
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/parseDate.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('parseDate', () => {
9 |
10 | eq (String (S.parseDate), 'parseDate :: String -> Maybe ValidDate');
11 |
12 | eq (S.parseDate ('2001-02-03T04:05:06Z'), S.Just (new Date ('2001-02-03T04:05:06Z')));
13 | eq (S.parseDate ('today'), S.Nothing);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/parseFloat.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('parseFloat', () => {
9 |
10 | eq (String (S.parseFloat), 'parseFloat :: String -> Maybe Number');
11 |
12 | eq (S.parseFloat ('12.34'), S.Just (12.34));
13 | eq (S.parseFloat ('Infinity'), S.Just (Infinity));
14 | eq (S.parseFloat ('-Infinity'), S.Just (-Infinity));
15 | eq (S.parseFloat ('NaN'), S.Just (NaN));
16 | eq (S.parseFloat ('-NaN'), S.Just (NaN)); // Haskell accepts "-NaN"
17 | eq (S.parseFloat ('0'), S.Just (0));
18 | eq (S.parseFloat ('-0'), S.Just (-0));
19 | eq (S.parseFloat ('42'), S.Just (42));
20 | eq (S.parseFloat ('42.'), S.Just (42));
21 | eq (S.parseFloat ('0.5'), S.Just (0.5));
22 | eq (S.parseFloat ('.25'), S.Just (0.25));
23 | eq (S.parseFloat ('+42'), S.Just (42));
24 | eq (S.parseFloat ('+42.'), S.Just (42));
25 | eq (S.parseFloat ('+0.5'), S.Just (0.5));
26 | eq (S.parseFloat ('+.25'), S.Just (0.25));
27 | eq (S.parseFloat ('-42'), S.Just (-42));
28 | eq (S.parseFloat ('-42.'), S.Just (-42));
29 | eq (S.parseFloat ('-0.5'), S.Just (-0.5));
30 | eq (S.parseFloat ('-.25'), S.Just (-0.25));
31 | eq (S.parseFloat ('0.5 '), S.Just (0.5));
32 | eq (S.parseFloat (' 0.5'), S.Just (0.5));
33 | eq (S.parseFloat ('0.5x'), S.Nothing); // parseFloat ('0.5x') == 0.5
34 | eq (S.parseFloat ('x0.5'), S.Nothing);
35 | eq (S.parseFloat ('-1e3'), S.Just (-1000));
36 | eq (S.parseFloat ('-1e03'), S.Just (-1000));
37 | eq (S.parseFloat ('-1e+3'), S.Just (-1000));
38 | eq (S.parseFloat ('-1e+03'), S.Just (-1000));
39 | eq (S.parseFloat ('-1e-3'), S.Just (-0.001));
40 | eq (S.parseFloat ('-1e-03'), S.Just (-0.001));
41 | eq (S.parseFloat ('xxx'), S.Nothing);
42 |
43 | });
44 |
--------------------------------------------------------------------------------
/test/parseInt.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq, throws} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('parseInt', () => {
9 |
10 | eq (String (S.parseInt), 'parseInt :: Radix -> String -> Maybe Integer');
11 |
12 | eq (S.parseInt (10) ('42'), S.Just (42));
13 | eq (S.parseInt (16) ('2A'), S.Just (42));
14 | eq (S.parseInt (10) ('NaN'), S.Nothing);
15 | eq (S.parseInt (10) ('xxx'), S.Nothing);
16 |
17 | // Accepts radix in [2 .. 36]
18 | eq (S.parseInt (2) ('1'), S.Just (1));
19 | eq (S.parseInt (2) ('2'), S.Nothing);
20 | eq (S.parseInt (3) ('2'), S.Just (2));
21 | eq (S.parseInt (3) ('3'), S.Nothing);
22 | eq (S.parseInt (4) ('3'), S.Just (3));
23 | eq (S.parseInt (4) ('4'), S.Nothing);
24 | eq (S.parseInt (5) ('4'), S.Just (4));
25 | eq (S.parseInt (5) ('5'), S.Nothing);
26 | eq (S.parseInt (6) ('5'), S.Just (5));
27 | eq (S.parseInt (6) ('6'), S.Nothing);
28 | eq (S.parseInt (7) ('6'), S.Just (6));
29 | eq (S.parseInt (7) ('7'), S.Nothing);
30 | eq (S.parseInt (8) ('7'), S.Just (7));
31 | eq (S.parseInt (8) ('8'), S.Nothing);
32 | eq (S.parseInt (9) ('8'), S.Just (8));
33 | eq (S.parseInt (9) ('9'), S.Nothing);
34 | eq (S.parseInt (10) ('9'), S.Just (9));
35 | eq (S.parseInt (10) ('A'), S.Nothing);
36 | eq (S.parseInt (11) ('A'), S.Just (10));
37 | eq (S.parseInt (11) ('B'), S.Nothing);
38 | eq (S.parseInt (12) ('B'), S.Just (11));
39 | eq (S.parseInt (12) ('C'), S.Nothing);
40 | eq (S.parseInt (13) ('C'), S.Just (12));
41 | eq (S.parseInt (13) ('D'), S.Nothing);
42 | eq (S.parseInt (14) ('D'), S.Just (13));
43 | eq (S.parseInt (14) ('E'), S.Nothing);
44 | eq (S.parseInt (15) ('E'), S.Just (14));
45 | eq (S.parseInt (15) ('F'), S.Nothing);
46 | eq (S.parseInt (16) ('F'), S.Just (15));
47 | eq (S.parseInt (16) ('G'), S.Nothing);
48 | eq (S.parseInt (17) ('G'), S.Just (16));
49 | eq (S.parseInt (17) ('H'), S.Nothing);
50 | eq (S.parseInt (18) ('H'), S.Just (17));
51 | eq (S.parseInt (18) ('I'), S.Nothing);
52 | eq (S.parseInt (19) ('I'), S.Just (18));
53 | eq (S.parseInt (19) ('J'), S.Nothing);
54 | eq (S.parseInt (20) ('J'), S.Just (19));
55 | eq (S.parseInt (20) ('K'), S.Nothing);
56 | eq (S.parseInt (21) ('K'), S.Just (20));
57 | eq (S.parseInt (21) ('L'), S.Nothing);
58 | eq (S.parseInt (22) ('L'), S.Just (21));
59 | eq (S.parseInt (22) ('M'), S.Nothing);
60 | eq (S.parseInt (23) ('M'), S.Just (22));
61 | eq (S.parseInt (23) ('N'), S.Nothing);
62 | eq (S.parseInt (24) ('N'), S.Just (23));
63 | eq (S.parseInt (24) ('O'), S.Nothing);
64 | eq (S.parseInt (25) ('O'), S.Just (24));
65 | eq (S.parseInt (25) ('P'), S.Nothing);
66 | eq (S.parseInt (26) ('P'), S.Just (25));
67 | eq (S.parseInt (26) ('Q'), S.Nothing);
68 | eq (S.parseInt (27) ('Q'), S.Just (26));
69 | eq (S.parseInt (27) ('R'), S.Nothing);
70 | eq (S.parseInt (28) ('R'), S.Just (27));
71 | eq (S.parseInt (28) ('S'), S.Nothing);
72 | eq (S.parseInt (29) ('S'), S.Just (28));
73 | eq (S.parseInt (29) ('T'), S.Nothing);
74 | eq (S.parseInt (30) ('T'), S.Just (29));
75 | eq (S.parseInt (30) ('U'), S.Nothing);
76 | eq (S.parseInt (31) ('U'), S.Just (30));
77 | eq (S.parseInt (31) ('V'), S.Nothing);
78 | eq (S.parseInt (32) ('V'), S.Just (31));
79 | eq (S.parseInt (32) ('W'), S.Nothing);
80 | eq (S.parseInt (33) ('W'), S.Just (32));
81 | eq (S.parseInt (33) ('X'), S.Nothing);
82 | eq (S.parseInt (34) ('X'), S.Just (33));
83 | eq (S.parseInt (34) ('Y'), S.Nothing);
84 | eq (S.parseInt (35) ('Y'), S.Just (34));
85 | eq (S.parseInt (35) ('Z'), S.Nothing);
86 | eq (S.parseInt (36) ('Z'), S.Just (35));
87 | eq (S.parseInt (36) ('['), S.Nothing);
88 |
89 | // Throws if radix is not in [2 .. 36]
90 | throws (() => { S.parseInt (1); },
91 | new TypeError ('Invalid value\n' +
92 | '\n' +
93 | 'parseInt :: Radix -> String -> Maybe Integer\n' +
94 | ' ^^^^^\n' +
95 | ' 1\n' +
96 | '\n' +
97 | '1) 1 :: Number\n' +
98 | '\n' +
99 | 'The value at position 1 is not a member of ‘Radix’.\n'));
100 |
101 | throws (() => { S.parseInt (37); },
102 | new TypeError ('Invalid value\n' +
103 | '\n' +
104 | 'parseInt :: Radix -> String -> Maybe Integer\n' +
105 | ' ^^^^^\n' +
106 | ' 1\n' +
107 | '\n' +
108 | '1) 37 :: Number\n' +
109 | '\n' +
110 | 'The value at position 1 is not a member of ‘Radix’.\n'));
111 |
112 | // Is not case-sensitive
113 | eq (S.parseInt (16) ('FF'), S.Just (255));
114 | eq (S.parseInt (16) ('Ff'), S.Just (255));
115 | eq (S.parseInt (16) ('fF'), S.Just (255));
116 | eq (S.parseInt (16) ('ff'), S.Just (255));
117 |
118 | // Accepts optional "+" or "-" prefix
119 | eq (S.parseInt (10) ('+42'), S.Just (42));
120 | eq (S.parseInt (16) ('+2A'), S.Just (42));
121 | eq (S.parseInt (10) ('-42'), S.Just (-42));
122 | eq (S.parseInt (16) ('-2A'), S.Just (-42));
123 |
124 | // Accepts optional "0x" or "0X" prefix when radix is 16
125 | eq (S.parseInt (16) ('0xFF'), S.Just (255));
126 | eq (S.parseInt (16) ('0XFF'), S.Just (255));
127 | eq (S.parseInt (17) ('0xFF'), S.Nothing);
128 | eq (S.parseInt (17) ('0XFF'), S.Nothing);
129 | eq (S.parseInt (16) ('+0xFF'), S.Just (255));
130 | eq (S.parseInt (16) ('+0XFF'), S.Just (255));
131 | eq (S.parseInt (16) ('-0xFF'), S.Just (-255));
132 | eq (S.parseInt (16) ('-0XFF'), S.Just (-255));
133 |
134 | // Returns Nothing if one or more characters are invalid
135 | eq (S.parseInt (10) ('12.34'), S.Nothing); // parseInt ('12.34', 10) == 12
136 | eq (S.parseInt (16) ('alice'), S.Nothing); // parseInt ('alice', 16) == 10
137 |
138 | // Restricts to exactly representable range (-2^53 .. 2^53)
139 | eq (S.parseInt (10) ('9007199254740991'), S.Just (9007199254740991));
140 | eq (S.parseInt (10) ('-9007199254740991'), S.Just (-9007199254740991));
141 | eq (S.parseInt (10) ('9007199254740992'), S.Nothing);
142 | eq (S.parseInt (10) ('-9007199254740992'), S.Nothing);
143 | eq (S.parseInt (10) ('Infinity'), S.Nothing);
144 | eq (S.parseInt (10) ('-Infinity'), S.Nothing);
145 |
146 | });
147 |
--------------------------------------------------------------------------------
/test/parseJson.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import $ from 'sanctuary-def';
5 |
6 | import S from '../index.js';
7 |
8 |
9 | test ('parseJson', () => {
10 |
11 | eq (String (S.parseJson), 'parseJson :: (Any -> Boolean) -> String -> Maybe a');
12 |
13 | eq (S.parseJson (S.is ($.Any)) ('[Invalid JSON]'), S.Nothing);
14 | eq (S.parseJson (S.is ($.Array ($.Any))) ('{"foo":"bar"}'), S.Nothing);
15 | eq (S.parseJson (S.is ($.Array ($.Any))) ('["foo","bar"]'), S.Just (['foo', 'bar']));
16 | eq (S.parseJson (S.is ($.Array ($.Number))) ('[1,2]'), S.Just ([1, 2]));
17 | eq (S.parseJson (S.is ($.Array ($.Number))) ('[1,2,null]'), S.Nothing);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/pipe.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('pipe', () => {
11 |
12 | eq (String (S.pipe), 'pipe :: Foldable f => f (Any -> Any) -> a -> b');
13 |
14 | eq (S.pipe ([]) ('99'), '99');
15 | eq (S.pipe ([parseInt]) ('99'), 99);
16 | eq (S.pipe ([parseInt, S.add (1)]) ('99'), 100);
17 | eq (S.pipe ([parseInt, S.add (1), Math.sqrt]) ('99'), 10);
18 | eq (S.pipe ([parseInt, S.add (1), Math.sqrt, S.sub (1)]) ('99'), 9);
19 |
20 | eq (S.pipe (Nil) ('99'), '99');
21 | eq (S.pipe (Cons (parseInt) (Nil)) ('99'), 99);
22 | eq (S.pipe (Cons (parseInt) (Cons (S.add (1)) (Nil))) ('99'), 100);
23 | eq (S.pipe (Cons (parseInt) (Cons (S.add (1)) (Cons (Math.sqrt) (Nil)))) ('99'), 10);
24 | eq (S.pipe (Cons (parseInt) (Cons (S.add (1)) (Cons (Math.sqrt) (Cons (S.sub (1)) (Nil))))) ('99'), 9);
25 |
26 | });
27 |
--------------------------------------------------------------------------------
/test/pipeK.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('pipeK', () => {
11 |
12 | eq (String (S.pipeK), 'pipeK :: (Foldable f, Chain m) => f (Any -> m Any) -> m a -> m b');
13 |
14 | eq (S.pipeK ([]) (S.Just ([1, 2, 3])), S.Just ([1, 2, 3]));
15 | eq (S.pipeK ([S.tail]) (S.Just ([1, 2, 3])), S.Just ([2, 3]));
16 | eq (S.pipeK ([S.tail, S.tail]) (S.Just ([1, 2, 3])), S.Just ([3]));
17 | eq (S.pipeK ([S.tail, S.tail, S.head]) (S.Just ([1, 2, 3])), S.Just (3));
18 |
19 | eq (S.pipeK (Nil) (S.Just ([1, 2, 3])), S.Just ([1, 2, 3]));
20 | eq (S.pipeK (Cons (S.tail) (Nil)) (S.Just ([1, 2, 3])), S.Just ([2, 3]));
21 | eq (S.pipeK (Cons (S.tail) (Cons (S.tail) (Nil))) (S.Just ([1, 2, 3])), S.Just ([3]));
22 | eq (S.pipeK (Cons (S.tail) (Cons (S.tail) (Cons (S.head) (Nil)))) (S.Just ([1, 2, 3])), S.Just (3));
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/test/pow.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('pow', () => {
9 |
10 | eq (String (S.pow), 'pow :: FiniteNumber -> FiniteNumber -> FiniteNumber');
11 |
12 | eq (S.pow (2) (8), 64);
13 | eq (S.map (S.pow (2)) ([-3, -2, -1, 0, 1, 2, 3]), [9, 4, 1, 0, 1, 4, 9]);
14 | eq (S.map (S.pow (0.5)) ([1, 4, 9, 16, 25]), [1, 2, 3, 4, 5]);
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/test/prepend.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('prepend', () => {
9 |
10 | eq (String (S.prepend), 'prepend :: (Applicative f, Semigroup f) => a -> f a -> f a');
11 |
12 | eq (S.prepend (1) ([]), [1]);
13 | eq (S.prepend (1) ([2, 3]), [1, 2, 3]);
14 | eq (S.prepend ([1, 2]) ([[3, 4], [5, 6]]), [[1, 2], [3, 4], [5, 6]]);
15 |
16 | eq (S.prepend ([1]) (S.Nothing), S.Just ([1]));
17 | eq (S.prepend ([1]) (S.Just ([2])), S.Just ([1, 2]));
18 |
19 | eq (S.prepend ([1]) (S.Left ('error')), S.Right ([1]));
20 | eq (S.prepend ([1]) (S.Right ([2])), S.Right ([1, 2]));
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/test/product.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('product', () => {
9 |
10 | eq (String (S.product), 'product :: Foldable f => f FiniteNumber -> FiniteNumber');
11 |
12 | eq (S.product ([]), 1);
13 | eq (S.product ([0, 1, 2, 3]), 0);
14 | eq (S.product ([1, 2, 3, 4, 5]), 120);
15 | eq (S.product ([1, 2, 3, 4, -5]), -120);
16 |
17 | eq (S.product (S.Nothing), 1);
18 | eq (S.product (S.Just (42)), 42);
19 |
20 | eq (S.product (S.Left ('xxx')), 1);
21 | eq (S.product (S.Right (42)), 42);
22 |
23 | });
24 |
--------------------------------------------------------------------------------
/test/promap.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('promap', () => {
9 |
10 | eq (String (S.promap), 'promap :: Profunctor p => (a -> b) -> (c -> d) -> p b c -> p a d');
11 |
12 | const before = S.map (S.prop ('length'));
13 | const after = S.join (S.mult);
14 | eq (S.promap (before) (after) (S.sum) (['foo', 'bar', 'baz', 'quux']), 169);
15 |
16 | eq (S.promap (Math.abs) (S.add (1)) (Math.sqrt) (-100), 11);
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/test/prop.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq, throws} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('prop', () => {
9 |
10 | eq (String (S.prop), 'prop :: String -> a -> b');
11 |
12 | throws (() => { S.prop ('xxx') ([1, 2, 3]); },
13 | new TypeError ('‘prop’ expected object to have a property named ‘xxx’; [1, 2, 3] does not'));
14 |
15 | eq (S.prop ('a') ({a: 0, b: 1}), 0);
16 | eq (S.prop ('0') ([1, 2, 3]), 1);
17 | eq (S.prop ('length') ('abc'), 3);
18 | eq (S.prop ('x') (Object.create ({x: 1, y: 2})), 1);
19 | eq (S.prop ('global') (/x/g), true);
20 |
21 | throws (() => { S.prop ('valueOf') (null); },
22 | new TypeError ('‘prop’ expected object to have a property named ‘valueOf’; null does not'));
23 |
24 | throws (() => { S.prop ('valueOf') (undefined); },
25 | new TypeError ('‘prop’ expected object to have a property named ‘valueOf’; undefined does not'));
26 |
27 | });
28 |
--------------------------------------------------------------------------------
/test/props.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq, throws} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('props', () => {
9 |
10 | eq (String (S.props), 'props :: Array String -> a -> b');
11 |
12 | throws (() => { S.props (['a', 'b', 'c']) ([1, 2, 3]); },
13 | new TypeError ('‘props’ expected object to have a property at ["a", "b", "c"]; [1, 2, 3] does not'));
14 |
15 | eq (S.props (['a', 'b', 'c']) ({a: {b: {c: 1}}}), 1);
16 | eq (S.props (['a', 'b', 'c', '0']) ({a: {b: {c: [2, 4, 6]}}}), 2);
17 | eq (S.props (['a', 'b', 'c']) (Object.create ({a: {b: {c: 1}}})), 1);
18 |
19 | throws (() => { S.props (['valueOf']) (null); },
20 | new TypeError ('‘props’ expected object to have a property at ["valueOf"]; null does not'));
21 |
22 | throws (() => { S.props (['valueOf']) (undefined); },
23 | new TypeError ('‘props’ expected object to have a property at ["valueOf"]; undefined does not'));
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/test/range.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('range', () => {
9 |
10 | eq (String (S.range), 'range :: Integer -> Integer -> Array Integer');
11 |
12 | eq (S.range (0) (0), []);
13 | eq (S.range (0) (10), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
14 | eq (S.range (0) (-10), []);
15 | eq (S.range (-2) (-1), [-2]);
16 | eq (S.range (-2) (3), [-2, -1, 0, 1, 2]);
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/test/reduce.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('reduce', () => {
9 |
10 | eq (String (S.reduce), 'reduce :: Foldable f => (b -> a -> b) -> b -> f a -> b');
11 |
12 | eq (S.reduce (S.concat) ('x') ([]), 'x');
13 | eq (S.reduce (S.concat) ('x') (['A', 'B', 'C']), 'xABC');
14 | eq (S.reduce (S.concat) ('x') ({}), 'x');
15 | eq (S.reduce (S.concat) ('x') ({a: 'A', b: 'B', c: 'C'}), 'xABC');
16 | eq (S.reduce (S.concat) ('x') ({c: 'C', b: 'B', a: 'A'}), 'xABC');
17 | eq (S.reduce (S.concat) ('x') (S.Just ('A')), 'xA');
18 | eq (S.reduce (S.lift2 (S.concat)) (S.Just ('x')) ([S.Just ('A'), S.Just ('B'), S.Just ('C')]), S.Just ('xABC'));
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/reduce_.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('reduce_', () => {
9 |
10 | eq (String (S.reduce_), 'reduce_ :: Foldable f => (a -> b -> b) -> b -> f a -> b');
11 |
12 | eq (S.reduce_ (S.append) ([]) ([]), []);
13 | eq (S.reduce_ (S.append) ([]) ([1, 2, 3]), [1, 2, 3]);
14 | eq (S.reduce_ (S.prepend) ([]) ([]), []);
15 | eq (S.reduce_ (S.prepend) ([]) ([1, 2, 3]), [3, 2, 1]);
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/regex.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('regex', () => {
9 |
10 | eq (String (S.regex), 'regex :: RegexFlags -> String -> RegExp');
11 |
12 | eq (S.regex ('') ('\\d'), /\d/);
13 | eq (S.regex ('g') ('\\d'), /\d/g);
14 | eq (S.regex ('i') ('\\d'), /\d/i);
15 | eq (S.regex ('m') ('\\d'), /\d/m);
16 | eq (S.regex ('gi') ('\\d'), /\d/gi);
17 | eq (S.regex ('gm') ('\\d'), /\d/gm);
18 | eq (S.regex ('im') ('\\d'), /\d/im);
19 | eq (S.regex ('gim') ('\\d'), /\d/gim);
20 |
21 | });
22 |
--------------------------------------------------------------------------------
/test/regexEscape.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import jsc from 'jsverify';
4 | import test from 'oletus';
5 |
6 | import S from '../index.js';
7 |
8 |
9 | test ('regexEscape', () => {
10 |
11 | eq (String (S.regexEscape), 'regexEscape :: String -> String');
12 |
13 | eq (S.regexEscape ('-=*{XYZ}*=-'), '\\-=\\*\\{XYZ\\}\\*=\\-');
14 |
15 | jsc.assert (
16 | jsc.forall (
17 | jsc.string,
18 | s => S.test (S.regex ('') (S.regexEscape (s))) (s)
19 | ),
20 | {tests: 1000}
21 | );
22 |
23 | jsc.assert (
24 | jsc.forall (
25 | jsc.string,
26 | s => S.test (S.regex ('') ('^' + S.regexEscape (s) + '$')) (s)
27 | ),
28 | {tests: 1000}
29 | );
30 |
31 | });
32 |
--------------------------------------------------------------------------------
/test/reject.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('reject', () => {
11 |
12 | eq (String (S.reject), 'reject :: Filterable f => (a -> Boolean) -> f a -> f a');
13 |
14 | eq (S.reject (S.odd) ([]), []);
15 | eq (S.reject (S.odd) ([0, 2, 4, 6, 8]), [0, 2, 4, 6, 8]);
16 | eq (S.reject (S.odd) ([1, 3, 5, 7, 9]), []);
17 | eq (S.reject (S.odd) ([1, 2, 3, 4, 5]), [2, 4]);
18 |
19 | eq (S.reject (S.odd) ({}), {});
20 | eq (S.reject (S.odd) ({x: 1}), {});
21 | eq (S.reject (S.odd) ({x: 1, y: 2}), {y: 2});
22 | eq (S.reject (S.odd) ({x: 1, y: 2, z: 3}), {y: 2});
23 |
24 | eq (S.reject (S.odd) (S.Nothing), S.Nothing);
25 | eq (S.reject (S.odd) (S.Just (0)), S.Just (0));
26 | eq (S.reject (S.odd) (S.Just (1)), S.Nothing);
27 |
28 | eq (S.reject (S.odd) (Nil), Nil);
29 | eq (S.reject (S.odd) (Cons (1) (Nil)), Nil);
30 | eq (S.reject (S.odd) (Cons (1) (Cons (2) (Nil))), Cons (2) (Nil));
31 | eq (S.reject (S.odd) (Cons (1) (Cons (2) (Cons (3) (Nil)))), Cons (2) (Nil));
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/test/remove.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import jsc from 'jsverify';
4 | import test from 'oletus';
5 | import Z from 'sanctuary-type-classes';
6 |
7 | import S from '../index.js';
8 |
9 |
10 | test ('remove', () => {
11 |
12 | eq (String (S.remove), 'remove :: String -> StrMap a -> StrMap a');
13 |
14 | eq (S.remove ('a') ({}), {});
15 | eq (S.remove ('b') ({a: 1}), {a: 1});
16 | eq (S.remove ('c') ({a: 1, b: 2, c: 3}), {a: 1, b: 2});
17 |
18 | jsc.assert (jsc.forall (jsc.string, jsc.dict (jsc.number), (key, map) => {
19 | const remove = S.remove (key);
20 | const lhs = remove (remove (map));
21 | const rhs = remove (map);
22 | return Z.equals (lhs, rhs);
23 | }), {tests: 1000});
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/test/replace.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('replace', () => {
9 |
10 | eq (String (S.replace), 'replace :: (Array (Maybe String) -> String) -> RegExp -> String -> String');
11 |
12 | eq (S.replace (([$1]) => S.maybe ('') (S.toUpper) ($1)) (/(\w)/) ('foo'), 'Foo');
13 | eq (S.replace (([$1]) => S.maybe ('') (S.toUpper) ($1)) (/(\w)/g) ('foo'), 'FOO');
14 | eq (S.replace (S.show) (/(foo)(bar)?/) ('<>'), '<>');
15 | eq (S.replace (S.show) (/(foo)(bar)?/) (''), '<[Just ("foo"), Nothing]>');
16 | eq (S.replace (S.show) (/(foo)(bar)?/) (''), '<[Just ("foo"), Just ("bar")]>');
17 | eq (S.replace (S.show) (/@(?[-\w]+)/) ('@sanctuary-js'), '[Just ("sanctuary-js")]');
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/reverse.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('reverse', () => {
11 |
12 | eq (String (S.reverse), 'reverse :: (Applicative f, Foldable f, Monoid f) => f a -> f a');
13 |
14 | eq (S.reverse ([]), []);
15 | eq (S.reverse ([1]), [1]);
16 | eq (S.reverse ([1, 2]), [2, 1]);
17 | eq (S.reverse ([1, 2, 3]), [3, 2, 1]);
18 |
19 | eq (S.reverse (Nil), Nil);
20 | eq (S.reverse (Cons (1) (Nil)), Cons (1) (Nil));
21 | eq (S.reverse (Cons (1) (Cons (2) (Nil))), Cons (2) (Cons (1) (Nil)));
22 | eq (S.reverse (Cons (1) (Cons (2) (Cons (3) (Nil)))), Cons (3) (Cons (2) (Cons (1) (Nil))));
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/test/rights.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('rights', () => {
11 |
12 | eq (String (S.rights), 'rights :: (Filterable f, Functor f) => f (Either a b) -> f b');
13 |
14 | eq (S.rights ([]), []);
15 | eq (S.rights ([S.Left ('a'), S.Left ('b')]), []);
16 | eq (S.rights ([S.Left ('a'), S.Right (1)]), [1]);
17 | eq (S.rights ([S.Right (2), S.Left ('b')]), [2]);
18 | eq (S.rights ([S.Right (2), S.Right (1)]), [2, 1]);
19 |
20 | eq (S.rights ({}), {});
21 | eq (S.rights ({x: S.Left ('a'), y: S.Left ('b')}), {});
22 | eq (S.rights ({x: S.Left ('a'), y: S.Right (1)}), {y: 1});
23 | eq (S.rights ({x: S.Right (2), y: S.Left ('b')}), {x: 2});
24 | eq (S.rights ({x: S.Right (2), y: S.Right (1)}), {x: 2, y: 1});
25 |
26 | eq (S.rights (S.Nothing), S.Nothing);
27 | eq (S.rights (S.Just (S.Left ('a'))), S.Nothing);
28 | eq (S.rights (S.Just (S.Right (1))), S.Just (1));
29 |
30 | eq (S.rights (Nil), Nil);
31 | eq (S.rights (Cons (S.Left ('a')) (Cons (S.Left ('b')) (Nil))), Nil);
32 | eq (S.rights (Cons (S.Left ('a')) (Cons (S.Right (1)) (Nil))), Cons (1) (Nil));
33 | eq (S.rights (Cons (S.Right (2)) (Cons (S.Left ('b')) (Nil))), Cons (2) (Nil));
34 | eq (S.rights (Cons (S.Right (2)) (Cons (S.Right (1)) (Nil))), Cons (2) (Cons (1) (Nil)));
35 |
36 | });
37 |
--------------------------------------------------------------------------------
/test/sequence.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import Identity from 'sanctuary-identity';
5 |
6 | import S from './internal/sanctuary.js';
7 |
8 |
9 | test ('sequence', () => {
10 |
11 | eq (String (S.sequence), 'sequence :: (Applicative f, Traversable t) => TypeRep (f a) -> t (f a) -> f (t a)');
12 |
13 | eq (S.sequence (Identity) ([]), Identity ([]));
14 | eq (S.sequence (Identity) ([Identity (1), Identity (2), Identity (3)]), Identity ([1, 2, 3]));
15 | eq (S.sequence (Identity) ({}), Identity ({}));
16 | eq (S.sequence (Identity) ({a: Identity (1), b: Identity (2), c: Identity (3)}), Identity ({a: 1, b: 2, c: 3}));
17 | eq (S.sequence (Identity) (S.Nothing), Identity (S.Nothing));
18 | eq (S.sequence (Identity) (S.Just (Identity (0))), Identity (S.Just (0)));
19 | eq (S.sequence (Identity) (S.Left ('A')), Identity (S.Left ('A')));
20 | eq (S.sequence (Identity) (S.Right (Identity (-1))), Identity (S.Right (-1)));
21 |
22 | eq (S.sequence (Array) (Identity ([])), []);
23 | eq (S.sequence (Array) (Identity ([1, 2, 3])), [Identity (1), Identity (2), Identity (3)]);
24 | eq (S.sequence (S.Maybe) (Identity (S.Nothing)), S.Nothing);
25 | eq (S.sequence (S.Maybe) (Identity (S.Just (0))), S.Just (Identity (0)));
26 | eq (S.sequence (S.Either) (Identity (S.Left ('A'))), S.Left ('A'));
27 | eq (S.sequence (S.Either) (Identity (S.Right (-1))), S.Right (Identity (-1)));
28 |
29 | eq (S.sequence (Array) ({a: [1, 2], b: [3, 4]}), [{a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 3}, {a: 2, b: 4}]);
30 |
31 | });
32 |
--------------------------------------------------------------------------------
/test/show.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('show', () => {
9 |
10 | eq (String (S.show), 'show :: Any -> String');
11 |
12 | eq (S.show (null), 'null');
13 | eq (S.show (undefined), 'undefined');
14 | eq (S.show (false), 'false');
15 | eq (S.show (true), 'true');
16 | eq (S.show (new Boolean (false)), 'new Boolean (false)');
17 | eq (S.show (new Boolean (true)), 'new Boolean (true)');
18 | eq (S.show (0), '0');
19 | eq (S.show (-0), '-0');
20 | eq (S.show (NaN), 'NaN');
21 | eq (S.show (Math.PI), '3.141592653589793');
22 | eq (S.show (-Math.PI), '-3.141592653589793');
23 | eq (S.show (Infinity), 'Infinity');
24 | eq (S.show (-Infinity), '-Infinity');
25 | eq (S.show (new Number (0)), 'new Number (0)');
26 | eq (S.show (new Number (-0)), 'new Number (-0)');
27 | eq (S.show (new Number (NaN)), 'new Number (NaN)');
28 | eq (S.show (new Number (Math.PI)), 'new Number (3.141592653589793)');
29 | eq (S.show (new Number (-Math.PI)), 'new Number (-3.141592653589793)');
30 | eq (S.show (new Number (Infinity)), 'new Number (Infinity)');
31 | eq (S.show (new Number (-Infinity)), 'new Number (-Infinity)');
32 | eq (S.show (''), '""');
33 | eq (S.show ('foo'), '"foo"');
34 | eq (S.show ('foo "bar" baz'), '"foo \\"bar\\" baz"');
35 | eq (S.show (new String ('')), 'new String ("")');
36 | eq (S.show (new String ('foo')), 'new String ("foo")');
37 | eq (S.show (new String ('foo "bar" baz')), 'new String ("foo \\"bar\\" baz")');
38 | eq (S.show (new Date (0)), 'new Date ("1970-01-01T00:00:00.000Z")');
39 | eq (S.show (new Date (42)), 'new Date ("1970-01-01T00:00:00.042Z")');
40 | eq (S.show (new Date (NaN)), 'new Date (NaN)');
41 | eq (S.show (new Date ('2001-02-03')), 'new Date ("2001-02-03T00:00:00.000Z")');
42 | eq (S.show ([]), '[]');
43 | eq (S.show (['foo']), '["foo"]');
44 | eq (S.show (['foo', 'bar', 'baz']), '["foo", "bar", "baz"]');
45 | eq (S.show (['foo "bar" baz']), '["foo \\"bar\\" baz"]');
46 | eq (S.show ({}), '{}');
47 | eq (S.show ({x: 1}), '{"x": 1}');
48 | eq (S.show ({x: 1, y: 2, z: 3}), '{"x": 1, "y": 2, "z": 3}');
49 | eq (S.show ({'foo "bar" baz': '"quux"'}), '{"foo \\"bar\\" baz": "\\"quux\\""}');
50 | eq (S.show (S.Nothing), 'Nothing');
51 | eq (S.show (S.Just (9)), 'Just (9)');
52 | eq (S.show (S.Left (false)), 'Left (false)');
53 | eq (S.show (S.Right (true)), 'Right (true)');
54 |
55 | });
56 |
--------------------------------------------------------------------------------
/test/singleton.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('singleton', () => {
9 |
10 | eq (String (S.singleton), 'singleton :: String -> a -> StrMap a');
11 |
12 | eq (S.singleton ('foo') (42), {foo: 42});
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/size.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('size', () => {
11 |
12 | eq (String (S.size), 'size :: Foldable f => f a -> NonNegativeInteger');
13 |
14 | eq (S.size ([]), 0);
15 | eq (S.size (['foo']), 1);
16 | eq (S.size (['foo', 'bar']), 2);
17 | eq (S.size (['foo', 'bar', 'baz']), 3);
18 |
19 | eq (S.size (Nil), 0);
20 | eq (S.size (Cons ('foo') (Nil)), 1);
21 | eq (S.size (Cons ('foo') (Cons ('bar') (Nil))), 2);
22 | eq (S.size (Cons ('foo') (Cons ('bar') (Cons ('baz') (Nil)))), 3);
23 |
24 | eq (S.size (S.Nothing), 0);
25 | eq (S.size (S.Just (0)), 1);
26 |
27 | });
28 |
--------------------------------------------------------------------------------
/test/snd.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('snd', () => {
9 |
10 | eq (String (S.snd), 'snd :: Pair a b -> b');
11 |
12 | eq (S.snd (S.Pair ('foo') (42)), 42);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/sort.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('sort', () => {
9 |
10 | eq (String (S.sort), 'sort :: (Ord a, Applicative m, Foldable m, Monoid m) => m a -> m a');
11 |
12 | eq (S.sort ([]), []);
13 | eq (S.sort (['foo', 'bar', 'baz']), ['bar', 'baz', 'foo']);
14 | eq (S.sort ([S.Left (4), S.Right (3), S.Left (2), S.Right (1)]), [S.Left (2), S.Left (4), S.Right (1), S.Right (3)]);
15 |
16 | eq (S.sort (S.range (0) (100)), S.range (0) (100));
17 | eq (S.sort (S.reverse (S.range (0) (100))), S.range (0) (100));
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/sortBy.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('sortBy', () => {
9 |
10 | eq (String (S.sortBy), 'sortBy :: (Ord b, Applicative m, Foldable m, Monoid m) => (a -> b) -> m a -> m a');
11 |
12 | eq (S.sortBy (S.I) ([]), []);
13 | eq (S.sortBy (S.I) (['five']), ['five']);
14 | eq (S.sortBy (S.I) (['five', 'six']), ['five', 'six']);
15 | eq (S.sortBy (S.I) (['five', 'six', 'seven']), ['five', 'seven', 'six']);
16 | eq (S.sortBy (S.prop ('length')) (['five', 'six', 'seven']), ['six', 'five', 'seven']);
17 |
18 | const _7s = {rank: 7, suit: 's'};
19 | const _5h = {rank: 5, suit: 'h'};
20 | const _2h = {rank: 2, suit: 'h'};
21 | const _5s = {rank: 5, suit: 's'};
22 | eq (S.sortBy (S.prop ('rank')) ([_7s, _5h, _2h, _5s]), [_2h, _5h, _5s, _7s]);
23 | eq (S.sortBy (S.prop ('rank')) ([_7s, _5s, _2h, _5h]), [_2h, _5s, _5h, _7s]);
24 | eq (S.sortBy (S.prop ('suit')) ([_7s, _5h, _2h, _5s]), [_5h, _2h, _7s, _5s]);
25 | eq (S.sortBy (S.prop ('suit')) ([_5s, _2h, _5h, _7s]), [_2h, _5h, _5s, _7s]);
26 |
27 | });
28 |
--------------------------------------------------------------------------------
/test/splitOn.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import jsc from 'jsverify';
4 | import test from 'oletus';
5 | import Z from 'sanctuary-type-classes';
6 |
7 | import S from '../index.js';
8 |
9 |
10 | test ('splitOn', () => {
11 |
12 | eq (String (S.splitOn), 'splitOn :: String -> String -> Array String');
13 |
14 | eq (S.splitOn ('') ('abc'), ['a', 'b', 'c']);
15 | eq (S.splitOn (':') (''), ['']);
16 | eq (S.splitOn (':') (':'), ['', '']);
17 | eq (S.splitOn (':') (':foo:'), ['', 'foo', '']);
18 | eq (S.splitOn (':') ('foo:bar:baz'), ['foo', 'bar', 'baz']);
19 | eq (S.splitOn ('::') ('foo::bar::baz'), ['foo', 'bar', 'baz']);
20 |
21 | jsc.assert (jsc.forall (jsc.asciistring, t => {
22 | const min = 0;
23 | const max = t.length;
24 | const i = jsc.random (min, max);
25 | const j = jsc.random (min, max);
26 | const s = t.slice (Math.min (i, j), Math.max (i, j));
27 | const lhs = S.joinWith (s) (S.splitOn (s) (t));
28 | const rhs = t;
29 | return Z.equals (lhs, rhs);
30 | }), {tests: 1000});
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/test/splitOnRegex.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import jsc from 'jsverify';
4 | import test from 'oletus';
5 | import Z from 'sanctuary-type-classes';
6 |
7 | import S from '../index.js';
8 |
9 |
10 | test ('splitOnRegex', () => {
11 |
12 | eq (String (S.splitOnRegex), 'splitOnRegex :: GlobalRegExp -> String -> Array String');
13 |
14 | eq (S.splitOnRegex (/b/g) ('abc'), ['a', 'c']);
15 | eq (S.splitOnRegex (/d/g) ('abc'), ['abc']);
16 | eq (S.splitOnRegex (/b(?=c)/g) ('abc abd'), ['a', 'c abd']);
17 | eq (S.splitOnRegex (/b(?!c)/g) ('abc abd'), ['abc a', 'd']);
18 |
19 | eq (S.splitOnRegex (/\s+/g) ('foo bar baz qux'), ['foo', 'bar', 'baz', 'qux']);
20 | eq (S.splitOnRegex (/\s+/g) ('foo bar baz\tqux\nquux'), ['foo', 'bar', 'baz', 'qux', 'quux']);
21 | eq (S.splitOnRegex (/\s+/g) ('foobar'), ['foobar']);
22 | eq (S.splitOnRegex (/([:;])\1/g) ('foo::bar:;baz;;quux'), ['foo', 'bar:;baz', 'quux']);
23 |
24 | eq (S.splitOnRegex (/./g) ('a\rb\nc'), ['', '\r', '\n', '']);
25 | eq (S.splitOnRegex (/[^]/g) ('a\nb'), ['', '', '', '']);
26 |
27 | eq (S.splitOnRegex (/^/g) ('foo\nbar\nbaz\n'), ['foo\nbar\nbaz\n']);
28 | eq (S.splitOnRegex (/^/gm) ('foo\nbar\nbaz\n'), ['foo\n', 'bar\n', 'baz\n']);
29 |
30 | eq (S.splitOnRegex (/foo/g) ('FOObar'), ['FOObar']);
31 | eq (S.splitOnRegex (/foo/gi) ('FOObar'), ['', 'bar']);
32 |
33 | eq (S.splitOnRegex (/(?:)/g) (''), []);
34 | eq (S.splitOnRegex (/(?:)/g) ('a'), ['a']);
35 | eq (S.splitOnRegex (/(?:)/g) ('ab'), ['a', 'b']);
36 | eq (S.splitOnRegex (/(?:)/g) ('abc'), ['a', 'b', 'c']);
37 |
38 | eq (S.splitOnRegex (/[^]/g) (''), ['']);
39 | eq (S.splitOnRegex (/[^]/g) ('a'), ['', '']);
40 | eq (S.splitOnRegex (/[^]/g) ('ab'), ['', '', '']);
41 | eq (S.splitOnRegex (/[^]/g) ('abc'), ['', '', '', '']);
42 |
43 | eq (S.splitOnRegex (/.*/g) (''), []);
44 | eq (S.splitOnRegex (/.*/g) ('hello'), ['']);
45 | eq (S.splitOnRegex (/./g) (''), ['']);
46 | eq (S.splitOnRegex (/./g) ('hello'), ['', '', '', '', '', '']);
47 |
48 | {
49 | // `lastIndex` property is respected and preserved
50 | const pattern = /:/g;
51 | eq (pattern.lastIndex, 0);
52 | pattern.exec ('x:y:z');
53 | eq (pattern.lastIndex, 2);
54 | eq (S.splitOnRegex (pattern) ('x:y:z'), ['x:y', 'z']);
55 | eq (pattern.lastIndex, 2);
56 | }
57 |
58 | jsc.assert (jsc.forall (jsc.asciistring, t => {
59 | const min = 0;
60 | const max = t.length;
61 | const i = jsc.random (min, max);
62 | const j = jsc.random (min, max);
63 | const s = t.slice (Math.min (i, j), Math.max (i, j));
64 | const lhs = S.joinWith (s) (S.splitOnRegex (S.regex ('g') (S.regexEscape (s))) (t));
65 | const rhs = t;
66 | return Z.equals (lhs, rhs);
67 | }), {tests: 1000});
68 |
69 | });
70 |
--------------------------------------------------------------------------------
/test/stripPrefix.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('stripPrefix', () => {
9 |
10 | eq (String (S.stripPrefix), 'stripPrefix :: String -> String -> Maybe String');
11 |
12 | eq (S.stripPrefix ('') (''), S.Just (''));
13 | eq (S.stripPrefix ('') ('abc'), S.Just ('abc'));
14 | eq (S.stripPrefix ('a') (''), S.Nothing);
15 | eq (S.stripPrefix ('a') ('abc'), S.Just ('bc'));
16 | eq (S.stripPrefix ('a') ('[abc]'), S.Nothing);
17 | eq (S.stripPrefix ('aaa') ('a'), S.Nothing);
18 | eq (S.stripPrefix ('https://') ('https://sanctuary.js.org'), S.Just ('sanctuary.js.org'));
19 | eq (S.stripPrefix ('https://') ('http://sanctuary.js.org'), S.Nothing);
20 |
21 | });
22 |
--------------------------------------------------------------------------------
/test/stripSuffix.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('stripSuffix', () => {
9 |
10 | eq (String (S.stripSuffix), 'stripSuffix :: String -> String -> Maybe String');
11 |
12 | eq (S.stripSuffix ('') (''), S.Just (''));
13 | eq (S.stripSuffix ('') ('xyz'), S.Just ('xyz'));
14 | eq (S.stripSuffix ('z') (''), S.Nothing);
15 | eq (S.stripSuffix ('z') ('xyz'), S.Just ('xy'));
16 | eq (S.stripSuffix ('z') ('[xyz]'), S.Nothing);
17 | eq (S.stripSuffix ('zzz') ('z'), S.Nothing);
18 | eq (S.stripSuffix ('.md') ('README.md'), S.Just ('README'));
19 | eq (S.stripSuffix ('.md') ('README'), S.Nothing);
20 |
21 | });
22 |
--------------------------------------------------------------------------------
/test/sub.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('sub', () => {
9 |
10 | eq (String (S.sub), 'sub :: FiniteNumber -> FiniteNumber -> FiniteNumber');
11 |
12 | eq (S.map (S.sub (1)) ([1, 2, 3]), [0, 1, 2]);
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/sum.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('sum', () => {
9 |
10 | eq (String (S.sum), 'sum :: Foldable f => f FiniteNumber -> FiniteNumber');
11 |
12 | eq (S.sum ([]), 0);
13 | eq (S.sum ([0, 1, 2, 3]), 6);
14 | eq (S.sum ([1, 2, 3, 4, 5]), 15);
15 | eq (S.sum ([1, 2, 3, 4, -5]), 5);
16 |
17 | eq (S.sum (S.Nothing), 0);
18 | eq (S.sum (S.Just (42)), 42);
19 |
20 | eq (S.sum (S.Left ('xxx')), 0);
21 | eq (S.sum (S.Right (42)), 42);
22 |
23 | });
24 |
--------------------------------------------------------------------------------
/test/swap.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('swap', () => {
9 |
10 | eq (String (S.swap), 'swap :: Pair a b -> Pair b a');
11 |
12 | eq (S.swap (S.Pair ('foo') (42)), S.Pair (42) ('foo'));
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/test/tagBy.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('tagBy', () => {
9 |
10 | eq (String (S.tagBy), 'tagBy :: (a -> Boolean) -> a -> Either a a');
11 |
12 | eq (S.tagBy (S.odd) (5), S.Right (5));
13 | eq (S.tagBy (S.odd) (6), S.Left (6));
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/tail.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('tail', () => {
11 |
12 | eq (String (S.tail), 'tail :: (Applicative f, Foldable f, Monoid f) => f a -> Maybe (f a)');
13 |
14 | eq (S.tail ([]), S.Nothing);
15 | eq (S.tail (['foo']), S.Just ([]));
16 | eq (S.tail (['foo', 'bar']), S.Just (['bar']));
17 | eq (S.tail (['foo', 'bar', 'baz']), S.Just (['bar', 'baz']));
18 |
19 | eq (S.tail (Nil), S.Nothing);
20 | eq (S.tail (Cons ('foo') (Nil)), S.Just (Nil));
21 | eq (S.tail (Cons ('foo') (Cons ('bar') (Nil))), S.Just (Cons ('bar') (Nil)));
22 | eq (S.tail (Cons ('foo') (Cons ('bar') (Cons ('baz') (Nil)))), S.Just (Cons ('bar') (Cons ('baz') (Nil))));
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/test/take.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('take', () => {
11 |
12 | eq (String (S.take), 'take :: (Applicative f, Foldable f, Monoid f) => Integer -> f a -> Maybe (f a)');
13 |
14 | eq (S.take (0) ([1, 2, 3, 4, 5]), S.Just ([]));
15 | eq (S.take (1) ([1, 2, 3, 4, 5]), S.Just ([1]));
16 | eq (S.take (2) ([1, 2, 3, 4, 5]), S.Just ([1, 2]));
17 | eq (S.take (3) ([1, 2, 3, 4, 5]), S.Just ([1, 2, 3]));
18 | eq (S.take (4) ([1, 2, 3, 4, 5]), S.Just ([1, 2, 3, 4]));
19 | eq (S.take (5) ([1, 2, 3, 4, 5]), S.Just ([1, 2, 3, 4, 5]));
20 | eq (S.take (6) ([1, 2, 3, 4, 5]), S.Nothing);
21 |
22 | eq (S.take (-1) ([1, 2, 3, 4, 5]), S.Nothing);
23 |
24 | eq (S.take (0) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Nil));
25 | eq (S.take (1) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (1) (Nil)));
26 | eq (S.take (2) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (1) (Cons (2) (Nil))));
27 | eq (S.take (3) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (1) (Cons (2) (Cons (3) (Nil)))));
28 | eq (S.take (4) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Nothing);
29 |
30 | eq (S.take (-1) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Nothing);
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/test/takeLast.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from './internal/sanctuary.js';
6 |
7 | import {Nil, Cons} from './internal/List.mjs';
8 |
9 |
10 | test ('takeLast', () => {
11 |
12 | eq (String (S.takeLast), 'takeLast :: (Applicative f, Foldable f, Monoid f) => Integer -> f a -> Maybe (f a)');
13 |
14 | eq (S.takeLast (0) ([1, 2, 3, 4, 5]), S.Just ([]));
15 | eq (S.takeLast (1) ([1, 2, 3, 4, 5]), S.Just ([5]));
16 | eq (S.takeLast (2) ([1, 2, 3, 4, 5]), S.Just ([4, 5]));
17 | eq (S.takeLast (3) ([1, 2, 3, 4, 5]), S.Just ([3, 4, 5]));
18 | eq (S.takeLast (4) ([1, 2, 3, 4, 5]), S.Just ([2, 3, 4, 5]));
19 | eq (S.takeLast (5) ([1, 2, 3, 4, 5]), S.Just ([1, 2, 3, 4, 5]));
20 | eq (S.takeLast (6) ([1, 2, 3, 4, 5]), S.Nothing);
21 |
22 | eq (S.takeLast (-1) ([1, 2, 3, 4, 5]), S.Nothing);
23 |
24 | eq (S.takeLast (0) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Nil));
25 | eq (S.takeLast (1) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (3) (Nil)));
26 | eq (S.takeLast (2) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (2) (Cons (3) (Nil))));
27 | eq (S.takeLast (3) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Just (Cons (1) (Cons (2) (Cons (3) (Nil)))));
28 | eq (S.takeLast (4) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Nothing);
29 |
30 | eq (S.takeLast (-1) (Cons (1) (Cons (2) (Cons (3) (Nil)))), S.Nothing);
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/test/takeWhile.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('takeWhile', () => {
9 |
10 | eq (String (S.takeWhile), 'takeWhile :: (a -> Boolean) -> Array a -> Array a');
11 |
12 | eq (S.takeWhile (S.odd) ([3, 3, 3, 7, 6, 3, 5, 4]), [3, 3, 3, 7]);
13 | eq (S.takeWhile (S.even) ([3, 3, 3, 7, 6, 3, 5, 4]), []);
14 | eq (S.takeWhile (S.odd) ([]), []);
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('test', () => {
9 |
10 | eq (String (S.test), 'test :: RegExp -> String -> Boolean');
11 |
12 | eq (S.test (/^a/) ('abacus'), true);
13 | eq (S.test (/^a/) ('banana'), false);
14 |
15 | const pattern = /x/g;
16 | eq (pattern.lastIndex, 0);
17 | eq (S.test (pattern) ('xyz'), true);
18 | eq (pattern.lastIndex, 0);
19 | eq (S.test (pattern) ('xyz'), true);
20 |
21 | {
22 | // `lastIndex` property is respected and preserved
23 | const pattern = /x/g;
24 | eq (pattern.lastIndex, 0);
25 | pattern.exec ('xyz');
26 | eq (pattern.lastIndex, 1);
27 | eq (S.test (pattern) ('xyz'), false);
28 | eq (pattern.lastIndex, 1);
29 | }
30 |
31 | });
32 |
--------------------------------------------------------------------------------
/test/toLower.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('toLower', () => {
9 |
10 | eq (String (S.toLower), 'toLower :: String -> String');
11 |
12 | eq (S.toLower (''), '');
13 | eq (S.toLower ('ABC def 123'), 'abc def 123');
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/toUpper.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('toUpper', () => {
9 |
10 | eq (String (S.toUpper), 'toUpper :: String -> String');
11 |
12 | eq (S.toUpper (''), '');
13 | eq (S.toUpper ('ABC def 123'), 'ABC DEF 123');
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/traverse.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 | import Identity from 'sanctuary-identity';
5 |
6 | import S from './internal/sanctuary.js';
7 |
8 |
9 | test ('traverse', () => {
10 |
11 | eq (String (S.traverse), 'traverse :: (Applicative f, Traversable t) => TypeRep (f b) -> (a -> f b) -> t a -> f (t b)');
12 |
13 | eq (S.traverse (S.Maybe) (S.parseInt (16)) (['A', 'B', 'C']), S.Just ([10, 11, 12]));
14 | eq (S.traverse (S.Maybe) (S.parseInt (16)) (['A', 'B', 'C', 'X']), S.Nothing);
15 | eq (S.traverse (S.Maybe) (S.parseInt (16)) ({a: 'A', b: 'B', c: 'C'}), S.Just ({a: 10, b: 11, c: 12}));
16 | eq (S.traverse (S.Maybe) (S.parseInt (16)) ({a: 'A', b: 'B', c: 'C', x: 'X'}), S.Nothing);
17 |
18 | eq (S.traverse (Array) (S.I) ([]), [[]]);
19 | eq (S.traverse (Array) (S.I) ([['A', 'a']]), [['A'], ['a']]);
20 | eq (S.traverse (Array) (S.I) ([['A', 'a'], ['B']]), [['A', 'B'], ['a', 'B']]);
21 | eq (S.traverse (Array) (S.I) ([['A', 'a'], ['B', 'b']]), [['A', 'B'], ['A', 'b'], ['a', 'B'], ['a', 'b']]);
22 |
23 | eq (S.traverse (Array) (S.words) (Identity ('')), []);
24 | eq (S.traverse (Array) (S.words) (Identity ('foo')), [Identity ('foo')]);
25 | eq (S.traverse (Array) (S.words) (Identity ('foo bar')), [Identity ('foo'), Identity ('bar')]);
26 | eq (S.traverse (Array) (S.words) (Identity ('foo bar baz')), [Identity ('foo'), Identity ('bar'), Identity ('baz')]);
27 |
28 | eq (S.traverse (Identity) (S.I) ([]), Identity ([]));
29 | eq (S.traverse (Identity) (S.I) ([Identity (1)]), Identity ([1]));
30 | eq (S.traverse (Identity) (S.I) ([Identity (1), Identity (2)]), Identity ([1, 2]));
31 | eq (S.traverse (Identity) (S.I) ([Identity (1), Identity (2), Identity (3)]), Identity ([1, 2, 3]));
32 |
33 | eq (S.traverse (Array) (S.I) ({a: [1, 2], b: [3, 4]}), [{a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 3}, {a: 2, b: 4}]);
34 |
35 | });
36 |
--------------------------------------------------------------------------------
/test/trim.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('trim', () => {
9 |
10 | eq (String (S.trim), 'trim :: String -> String');
11 |
12 | eq (S.trim (''), '');
13 | eq (S.trim (' '), '');
14 | eq (S.trim ('x'), 'x');
15 | eq (S.trim (' x'), 'x');
16 | eq (S.trim ('x '), 'x');
17 | eq (S.trim (' x '), 'x');
18 | eq (S.trim ('\n\r\t x \n\r\t x \n\r\t'), 'x \n\r\t x');
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/type.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 | import vm from 'node:vm';
3 |
4 | import test from 'oletus';
5 |
6 | import S from '../index.js';
7 |
8 |
9 | test ('type', () => {
10 |
11 | eq (String (S.type), 'type :: Any -> { name :: String, namespace :: Maybe String, version :: NonNegativeInteger }');
12 |
13 | // eslint-disable-next-line prefer-rest-params
14 | eq (S.type (function() { return arguments; } ()),
15 | {namespace: S.Nothing, name: 'Arguments', version: 0});
16 | eq (S.type ([]),
17 | {namespace: S.Nothing, name: 'Array', version: 0});
18 | eq (S.type (false),
19 | {namespace: S.Nothing, name: 'Boolean', version: 0});
20 | eq (S.type (new Date (0)),
21 | {namespace: S.Nothing, name: 'Date', version: 0});
22 | eq (S.type (new TypeError ()),
23 | {namespace: S.Nothing, name: 'Error', version: 0});
24 | eq (S.type (() => {}),
25 | {namespace: S.Nothing, name: 'Function', version: 0});
26 | eq (S.type (null),
27 | {namespace: S.Nothing, name: 'Null', version: 0});
28 | eq (S.type (0),
29 | {namespace: S.Nothing, name: 'Number', version: 0});
30 | eq (S.type (/(?:)/),
31 | {namespace: S.Nothing, name: 'RegExp', version: 0});
32 | eq (S.type (''),
33 | {namespace: S.Nothing, name: 'String', version: 0});
34 | eq (S.type (undefined),
35 | {namespace: S.Nothing, name: 'Undefined', version: 0});
36 | eq (S.type (new Boolean (false)),
37 | {namespace: S.Nothing, name: 'Boolean', version: 0});
38 | eq (S.type (new Number (0)),
39 | {namespace: S.Nothing, name: 'Number', version: 0});
40 | eq (S.type (new String ('')),
41 | {namespace: S.Nothing, name: 'String', version: 0});
42 |
43 | eq (S.type (S.Left (42)),
44 | {namespace: S.Just ('sanctuary-either'), name: 'Either', version: 1});
45 | eq (S.type (S.Right (42)),
46 | {namespace: S.Just ('sanctuary-either'), name: 'Either', version: 1});
47 | eq (S.type (S.Nothing),
48 | {namespace: S.Just ('sanctuary-maybe'), name: 'Maybe', version: 1});
49 | eq (S.type (S.Just (42)),
50 | {namespace: S.Just ('sanctuary-maybe'), name: 'Maybe', version: 1});
51 |
52 | function Gizmo() {}
53 | Gizmo.prototype['@@type'] = 'gadgets/Gizmo@42';
54 |
55 | eq (S.type (new Gizmo ()),
56 | {namespace: S.Just ('gadgets'), name: 'Gizmo', version: 42});
57 | eq (S.type (Gizmo),
58 | {namespace: S.Nothing, name: 'Function', version: 0});
59 | eq (S.type (Gizmo.prototype),
60 | {namespace: S.Nothing, name: 'Object', version: 0});
61 |
62 | eq (S.type (vm.runInNewContext ('[1, 2, 3]')),
63 | {namespace: S.Nothing, name: 'Array', version: 0});
64 |
65 | });
66 |
--------------------------------------------------------------------------------
/test/unchecked.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('unchecked', () => {
9 |
10 | eq (S.unchecked.add (2) (2), 4);
11 | eq (S.unchecked.add (2) ('2'), '22');
12 | eq (S.unchecked.add ('2') (2), '22');
13 | eq (S.unchecked.add ('2') ('2'), '22');
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/unfold.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('unfold', () => {
9 |
10 | eq (String (S.unfold), 'unfold :: (b -> Maybe (Pair a b)) -> b -> Array a');
11 |
12 | const f = n => n >= 5 ? S.Nothing : S.Just (S.Pair (n) (n + 1));
13 | eq (S.unfold (f) (5), []);
14 | eq (S.unfold (f) (4), [4]);
15 | eq (S.unfold (f) (1), [1, 2, 3, 4]);
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/unless.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('unless', () => {
9 |
10 | eq (String (S.unless), 'unless :: (a -> Boolean) -> (a -> a) -> a -> a');
11 |
12 | eq (S.unless (S.lt (0)) (Math.sqrt) (16), 4);
13 | eq (S.unless (S.lt (0)) (Math.sqrt) (-1), -1);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/unlines.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('unlines', () => {
9 |
10 | eq (String (S.unlines), 'unlines :: Array String -> String');
11 |
12 | eq (S.unlines ([]), '');
13 | eq (S.unlines (['']), '\n');
14 | eq (S.unlines (['', '']), '\n\n');
15 | eq (S.unlines (['\n']), '\n\n');
16 | eq (S.unlines (['\n', '\n']), '\n\n\n\n');
17 | eq (S.unlines (['foo', 'bar', 'baz']), 'foo\nbar\nbaz\n');
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/unwords.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('unwords', () => {
9 |
10 | eq (String (S.unwords), 'unwords :: Array String -> String');
11 |
12 | eq (S.unwords ([]), '');
13 | eq (S.unwords (['']), '');
14 | eq (S.unwords (['', '']), ' ');
15 | eq (S.unwords ([' ']), ' ');
16 | eq (S.unwords ([' ', ' ']), ' ');
17 | eq (S.unwords (['foo', 'bar', 'baz']), 'foo bar baz');
18 | eq (S.unwords ([' foo ', ' bar ', ' baz ']), ' foo bar baz ');
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/test/value.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 | import strMap from './internal/strMap.js';
8 |
9 |
10 | test ('value', () => {
11 |
12 | eq (String (S.value), 'value :: String -> StrMap a -> Maybe a');
13 |
14 | eq (S.value ('foo') ({foo: 1, bar: 2}), S.Just (1));
15 | eq (S.value ('bar') ({foo: 1, bar: 2}), S.Just (2));
16 | eq (S.value ('baz') ({foo: 1, bar: 2}), S.Nothing);
17 |
18 | eq (S.value ('valueOf') ({}), S.Nothing);
19 |
20 | eq (S.value ('non-enumerable inherited property') (strMap), S.Nothing);
21 | eq (S.value ('enumerable inherited property') (strMap), S.Nothing);
22 | eq (S.value ('non-enumerable own property') (strMap), S.Nothing);
23 | eq (S.value ('enumerable own property') (strMap), S.Just ('enumerable own property'));
24 |
25 | });
26 |
--------------------------------------------------------------------------------
/test/values.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 | import strMap from './internal/strMap.js';
8 |
9 |
10 | test ('values', () => {
11 |
12 | eq (String (S.values), 'values :: StrMap a -> Array a');
13 |
14 | eq (S.sort (S.values ({})), []);
15 | eq (S.sort (S.values ({a: 1, b: 2, c: 3})), [1, 2, 3]);
16 |
17 | eq (S.values (strMap), ['enumerable own property']);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/when.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('when', () => {
9 |
10 | eq (String (S.when), 'when :: (a -> Boolean) -> (a -> a) -> a -> a');
11 |
12 | eq (S.when (S.gte (0)) (Math.sqrt) (16), 4);
13 | eq (S.when (S.gte (0)) (Math.sqrt) (-1), -1);
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/test/words.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('words', () => {
9 |
10 | eq (String (S.words), 'words :: String -> Array String');
11 |
12 | eq (S.words (''), []);
13 | eq (S.words (' '), []);
14 | eq (S.words (' \t\r\n'), []);
15 | eq (S.words ('foo bar baz'), ['foo', 'bar', 'baz']);
16 | eq (S.words (' foo bar baz '), ['foo', 'bar', 'baz']);
17 | eq (S.words ('\tfoo\r\n\tbar\r\n\tbaz\r\n'), ['foo', 'bar', 'baz']);
18 |
19 | });
20 |
--------------------------------------------------------------------------------
/test/zero.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('zero', () => {
9 |
10 | eq (String (S.zero), 'zero :: Plus f => TypeRep (f a) -> f a');
11 |
12 | eq (S.zero (Array), []);
13 | eq (S.zero (Object), {});
14 | eq (S.zero (S.Maybe), S.Nothing);
15 |
16 | });
17 |
--------------------------------------------------------------------------------
/test/zip.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('zip', () => {
9 |
10 | eq (String (S.zip), 'zip :: Array a -> Array b -> Array (Pair a b)');
11 |
12 | eq (S.zip (['a', 'b']) (['x', 'y', 'z']),
13 | [S.Pair ('a') ('x'), S.Pair ('b') ('y')]);
14 | eq (S.zip ([1, 3, 5]) ([2, 4]),
15 | [S.Pair (1) (2), S.Pair (3) (4)]);
16 |
17 | });
18 |
--------------------------------------------------------------------------------
/test/zipWith.js:
--------------------------------------------------------------------------------
1 | import {deepStrictEqual as eq} from 'node:assert';
2 |
3 | import test from 'oletus';
4 |
5 | import S from '../index.js';
6 |
7 |
8 | test ('zipWith', () => {
9 |
10 | eq (String (S.zipWith), 'zipWith :: (a -> b -> c) -> Array a -> Array b -> Array c');
11 |
12 | eq (S.zipWith (x => y => x + y) (['a', 'b']) (['x', 'y', 'z']), ['ax', 'by']);
13 | eq (S.zipWith (x => y => [x, y]) ([1, 3, 5]) ([2, 4]), [[1, 2], [3, 4]]);
14 |
15 | });
16 |
--------------------------------------------------------------------------------