Repository: fp-ts/core Branch: main Commit: 7a190bacb476 Files: 208 Total size: 1.1 MB Directory structure: gitextract_pgmrj7hm/ ├── .babel.cjs.json ├── .babel.mjs.json ├── .changeset/ │ ├── README.md │ ├── beige-numbers-exist.md │ ├── config.json │ ├── famous-spies-attend.md │ ├── flat-news-whisper.md │ ├── hungry-comics-kneel.md │ ├── mighty-meals-dream.md │ ├── odd-hornets-wave.md │ ├── sour-suits-press.md │ └── tough-planets-lick.md ├── .eslintrc.cjs ├── .github/ │ ├── CONTRIBUTING.md │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── Bug_report.md │ │ ├── Documentation.md │ │ └── Feature_request.md │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/ │ ├── main.yml │ └── pr.yml ├── .gitignore ├── .gitpod.yml ├── .vscode/ │ ├── settings.json │ └── tasks.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── benchmark/ │ ├── Number/ │ │ └── lessThan.ts │ ├── These/ │ │ └── product.ts │ ├── dual.ts │ ├── sumAll.ts │ └── tsconfig.json ├── docs/ │ ├── _config.yml │ ├── _sass/ │ │ └── custom/ │ │ └── custom.scss │ ├── index.md │ └── modules/ │ ├── Bigint.ts.md │ ├── Boolean.ts.md │ ├── Either.ts.md │ ├── Function.ts.md │ ├── HKT.ts.md │ ├── Identity.ts.md │ ├── Number.ts.md │ ├── Option.ts.md │ ├── Ordering.ts.md │ ├── Predicate.ts.md │ ├── ReadonlyArray.ts.md │ ├── ReadonlyRecord.ts.md │ ├── String.ts.md │ ├── Struct.ts.md │ ├── Symbol.ts.md │ ├── These.ts.md │ ├── Tuple.ts.md │ ├── index.md │ ├── index.ts.md │ └── typeclass/ │ ├── Alternative.ts.md │ ├── Applicative.ts.md │ ├── Bicovariant.ts.md │ ├── Bounded.ts.md │ ├── Chainable.ts.md │ ├── Contravariant.ts.md │ ├── Coproduct.ts.md │ ├── Covariant.ts.md │ ├── Equivalence.ts.md │ ├── Filterable.ts.md │ ├── FlatMap.ts.md │ ├── Foldable.ts.md │ ├── Invariant.ts.md │ ├── Monad.ts.md │ ├── Monoid.ts.md │ ├── Of.ts.md │ ├── Order.ts.md │ ├── Pointed.ts.md │ ├── Product.ts.md │ ├── SemiAlternative.ts.md │ ├── SemiApplicative.ts.md │ ├── SemiCoproduct.ts.md │ ├── SemiProduct.ts.md │ ├── Semigroup.ts.md │ ├── Traversable.ts.md │ └── TraversableFilterable.ts.md ├── docs-ts.json ├── dtslint/ │ ├── index.d.ts │ └── ts4.8/ │ ├── FlatMap.ts │ ├── Monoid.ts │ ├── Option.ts │ ├── Predicate.ts │ ├── Product.ts │ ├── ReadonlyArray.ts │ ├── ReadonlyRecord.ts │ ├── SemiAlternative.ts │ ├── SemiProduct.ts │ ├── Semigroup.ts │ ├── Tuple.ts │ ├── index.d.ts │ ├── index.ts │ ├── tsconfig.json │ └── tslint.json ├── guides/ │ ├── Either.md │ ├── FAQ.md │ ├── Option.md │ ├── These.md │ ├── ts-types.md │ └── typeclass.md ├── package.json ├── patches/ │ ├── @effect-ts__build-utils@0.40.3.patch │ └── docs-ts@0.6.10.patch ├── src/ │ ├── Bigint.ts │ ├── Boolean.ts │ ├── Either.ts │ ├── Function.ts │ ├── HKT.ts │ ├── Identity.ts │ ├── Number.ts │ ├── Option.ts │ ├── Ordering.ts │ ├── Predicate.ts │ ├── ReadonlyArray.ts │ ├── ReadonlyRecord.ts │ ├── String.ts │ ├── Struct.ts │ ├── Symbol.ts │ ├── These.ts │ ├── Tuple.ts │ ├── index.ts │ ├── internal/ │ │ ├── Either.ts │ │ ├── Option.ts │ │ ├── ReadonlyArray.ts │ │ └── effect.ts │ └── typeclass/ │ ├── Alternative.ts │ ├── Applicative.ts │ ├── Bicovariant.ts │ ├── Bounded.ts │ ├── Chainable.ts │ ├── Contravariant.ts │ ├── Coproduct.ts │ ├── Covariant.ts │ ├── Equivalence.ts │ ├── Filterable.ts │ ├── FlatMap.ts │ ├── Foldable.ts │ ├── Invariant.ts │ ├── Monad.ts │ ├── Monoid.ts │ ├── Of.ts │ ├── Order.ts │ ├── Pointed.ts │ ├── Product.ts │ ├── SemiAlternative.ts │ ├── SemiApplicative.ts │ ├── SemiCoproduct.ts │ ├── SemiProduct.ts │ ├── Semigroup.ts │ ├── Traversable.ts │ └── TraversableFilterable.ts ├── test/ │ ├── Bigint.ts │ ├── Boolean.ts │ ├── Either.ts │ ├── Function.ts │ ├── Identity.ts │ ├── Number.ts │ ├── Option.ts │ ├── Ordering.ts │ ├── Predicate.ts │ ├── ReadonlyArray.ts │ ├── ReadonlyRecord.ts │ ├── String.ts │ ├── Struct.ts │ ├── Symbol.ts │ ├── These.ts │ ├── Tuple.ts │ ├── index.ts │ ├── limbo/ │ │ ├── Category.ts │ │ ├── Comonad.ts │ │ ├── Composable.ts │ │ ├── Extendable.ts │ │ └── NonEmptyTraversable.ts │ ├── typeclass/ │ │ ├── Applicative.ts │ │ ├── Bicovariant.ts │ │ ├── Bounded.ts │ │ ├── Chainable.ts │ │ ├── Contravariant.ts │ │ ├── Coproduct.ts │ │ ├── Covariant.ts │ │ ├── Equivalence.ts │ │ ├── Filterable.ts │ │ ├── FlatMap.ts │ │ ├── Foldable.ts │ │ ├── Invariant.ts │ │ ├── Monoid.ts │ │ ├── NonEmptyTraversable.ts │ │ ├── Of.ts │ │ ├── Order.ts │ │ ├── Product.ts │ │ ├── SemiApplicative.ts │ │ ├── SemiCoproduct.ts │ │ ├── SemiProduct.ts │ │ ├── Semigroup.ts │ │ ├── Traversable.ts │ │ └── TraversableFilterable.ts │ └── util.ts ├── tsconfig.base.json ├── tsconfig.build-test.json ├── tsconfig.build.json ├── tsconfig.eslint.json ├── tsconfig.json ├── tsconfig.madge.json └── vitest.config.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babel.cjs.json ================================================ { "plugins": [["@babel/transform-modules-commonjs"], ["annotate-pure-calls"]] } ================================================ FILE: .babel.mjs.json ================================================ { "plugins": [["annotate-pure-calls"]] } ================================================ FILE: .changeset/README.md ================================================ # Changesets Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it [in our repository](https://github.com/changesets/changesets) We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) ================================================ FILE: .changeset/beige-numbers-exist.md ================================================ --- "@fp-ts/core": patch --- Tuple: add more APIs ================================================ FILE: .changeset/config.json ================================================ { "$schema": "https://unpkg.com/@changesets/config@1.6.4/schema.json", "changelog": ["@changesets/changelog-github", { "repo": "fp-ts/core" }], "commit": false, "linked": [], "access": "restricted", "baseBranch": "main", "updateInternalDependencies": "patch", "ignore": [] } ================================================ FILE: .changeset/famous-spies-attend.md ================================================ --- "@fp-ts/core": patch --- export productAll from Option, Either, Predicate ================================================ FILE: .changeset/flat-news-whisper.md ================================================ --- "@fp-ts/core": patch --- fix bounds flipping in reverse function ================================================ FILE: .changeset/hungry-comics-kneel.md ================================================ --- "@fp-ts/core": patch --- Function: swap apply arguments ================================================ FILE: .changeset/mighty-meals-dream.md ================================================ --- "@fp-ts/core": patch --- add missing boolean semigroups, monoids and combinators ================================================ FILE: .changeset/odd-hornets-wave.md ================================================ --- "@fp-ts/core": patch --- Bigint: feature parity with Number ================================================ FILE: .changeset/sour-suits-press.md ================================================ --- "@fp-ts/core": patch --- Number: add missing functions (derivable from Order) ================================================ FILE: .changeset/tough-planets-lick.md ================================================ --- "@fp-ts/core": patch --- ReadonlyRecord: map: add support for structs ================================================ FILE: .eslintrc.cjs ================================================ /* eslint-disable no-undef */ module.exports = { ignorePatterns: ["build", "dist", "dtslint", "benchmark", "*.mjs", "docs", "*.md"], parser: "@typescript-eslint/parser", parserOptions: { ecmaVersion: 2018, sourceType: "module", project: "./tsconfig.eslint.json" }, settings: { "import/parsers": { "@typescript-eslint/parser": [".ts", ".tsx"] }, "import/resolver": { typescript: { alwaysTryTypes: true } } }, extends: [ "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "plugin:@repo-tooling/dprint/recommended" ], plugins: ["deprecation", "import", "sort-destructure-keys", "simple-import-sort", "codegen"], rules: { "codegen/codegen": "error", "no-fallthrough": "off", "no-irregular-whitespace": "off", "object-shorthand": "error", "prefer-destructuring": "off", "sort-imports": "off", "no-unused-vars": "off", "prefer-rest-params": "off", "prefer-spread": "off", "import/first": "error", "import/no-cycle": "error", "import/newline-after-import": "error", "import/no-duplicates": "error", "import/no-unresolved": "off", "import/order": "off", "simple-import-sort/imports": "off", "sort-destructure-keys/sort-destructure-keys": "error", "deprecation/deprecation": "off", "@typescript-eslint/array-type": ["warn", { "default": "generic", "readonly": "generic" }], "@typescript-eslint/prefer-readonly": "warn", "@typescript-eslint/member-delimiter-style": 0, "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/ban-types": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/consistent-type-imports": "warn", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }], "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/camelcase": "off", "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/interface-name-prefix": "off", "@typescript-eslint/no-array-constructor": "off", "@typescript-eslint/no-use-before-define": "off", "@typescript-eslint/no-namespace": "off", "@repo-tooling/dprint/dprint": [ "error", { config: { "indentWidth": 2, "lineWidth": 100, "semiColons": "asi", "quoteStyle": "alwaysDouble", "trailingCommas": "never", "operatorPosition": "maintain", "useParentheses": "preferNone" } } ] } } ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Contributing to `@fp-ts/core` We welcome all contributions to the `@fp-ts/core` library. Your help makes the library better for everyone! ## Creating an Issue Before you begin working on a contribution, it's important to create an issue that describes what you would like to build or improve. This helps to ensure that someone else isn't already working on something similar, and also helps the maintainers understand your goals. ## Development Workflow 1. Fork the repository on GitHub. 2. Clone your forked repository using the following command: `git clone git@github.com:{your_username}/core.git` 3. Install dependencies with `pnpm install`. 4. Make your contributions and commit your changes. 5. If you have made changes to the code, run `pnpm changeset` and select the appropriate level of change (`patch`, `minor`, `major`) ### Available Commands - `pnpm build`: Deletes the `dist` folder and recompiles the `src` code into `dist`. - `pnpm test`: Runs all vitest tests in watch mode. - `pnpm coverage`: Runs all vitest tests and collects coverage information. - `pnpm dtslint`: Runs type-level tests. ### Writing Tests `@fp-ts/core` uses vitest for testing. After making your contributions, it's important to write tests to ensure that they work as intended. Before submitting your pull request, run `pnpm coverage` to make sure there are no unintended breaking changes and that your code has 100% coverage. ### Documentation API documentation for `@fp-ts/core` can be found in the source code as JSDoc comments. Be sure to include documentation for any changes you make to the API. ## Licensing By contributing your code to the `@fp-ts/core` GitHub repository, you agree to license your contribution under the MIT license. ================================================ FILE: .github/FUNDING.yml ================================================ github: [gcanti] ================================================ FILE: .github/ISSUE_TEMPLATE/Bug_report.md ================================================ # Bug Report Thank you for reporting a bug in `@fp-ts/core`. Your contribution to this project is greatly appreciated and will help make the library better for everyone. ## Describing the Bug Please provide a clear and concise description of the issue you are encountering, including any error messages or unexpected behavior you have observed. ## Steps to Reproduce In order to help us understand and resolve the issue, please provide the steps to reproduce the behavior, along with a minimal, self-contained code example that demonstrates the problem. ## Expected Behavior Please describe what you expected to happen, and how the current behavior differs from your expectations. ## Environment Please provide the following information to help us understand your setup: - Library version: [e.g. `0.8.1`] - TypeScript version: [e.g. `4.2.2`] ## Additional Context Any additional information or context that you think would be helpful in resolving the issue. ================================================ FILE: .github/ISSUE_TEMPLATE/Documentation.md ================================================ # Improving Documentation We welcome all suggestions and improvements to the documentation of `@fp-ts/core`. Your contributions help make the library easier to understand and use for everyone. ## How to Contribute To contribute to the documentation, follow these steps: 1. Make the desired changes to the documentation files. 2. Submit a pull request with a clear description of the changes and why they are beneficial. ## Content Guidelines When contributing to the documentation, please keep in mind the following guidelines: - Write clear and concise explanations of features and concepts. - Use examples and code snippets to help illustrate your explanations. - Follow the same formatting and style used in the existing documentation. Thank you for your contributions to the `@fp-ts/core` documentation! ================================================ FILE: .github/ISSUE_TEMPLATE/Feature_request.md ================================================ # Feature Request Thank you for submitting a feature request for `@fp-ts/core`. Your contributions help shape the future of this library. ## Describing the Feature Please provide a clear and concise description of the new feature you would like to see added to `@fp-ts/core`. ## Problem to Solve Please describe the problem that this new feature will solve, and why it's important. ## Use Case Please provide a use case or an example of how this feature will be used. ## Alternatives Considered Please describe any alternatives you have considered and why you believe this new feature is a better solution. ## Additional Context Please provide any additional information or context that might be relevant to this feature request. ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ # Pull Request Template ## Description Please describe the changes you have made and the purpose of the changes. If applicable, provide context or links to relevant issues or discussions. ## Types of Changes What types of changes does your code introduce to the library? - [ ] Bugfix - [ ] New feature - [ ] Documentation update ## Checklist - [ ] I have read the [contributing guidelines](https://github.com/fp-ts/core/blob/main/.github/CONTRIBUTING.md) for this repository - [ ] I have written tests for the changes I have made - [ ] I have run `pnpm coverage` and my code is 100% covered - [ ] I have updated the documentation (if applicable) - [ ] I agree to license my contribution under the MIT license ## Additional Information Is there anything else you would like to add? Are there any questions that need to be answered before merging this pull request? ================================================ FILE: .github/workflows/main.yml ================================================ name: Main Flow on: push: branches: [main] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [16.17.1] steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - uses: pnpm/action-setup@v2.0.1 name: Install pnpm id: pnpm-install with: version: 7 run_install: false - name: Get pnpm store directory id: pnpm-cache run: | echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" - uses: actions/cache@v3 name: Setup pnpm cache with: path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - run: pnpm install - run: pnpm build - run: pnpm test - run: pnpm dtslint - run: pnpm lint - run: pnpm run docs - name: Create Release Pull Request or Publish id: changesets uses: changesets/action@v1 with: version: pnpm run version publish: pnpm exec changeset publish env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} ================================================ FILE: .github/workflows/pr.yml ================================================ name: PR Flow on: pull_request: branches: - 'main' # Allows you to run this workflow manually from the Actions tab workflow_dispatch: jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [16.17.1] steps: - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - uses: pnpm/action-setup@v2.0.1 name: Install pnpm id: pnpm-install with: version: 7 run_install: false - name: Get pnpm store directory id: pnpm-cache run: | echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" - uses: actions/cache@v3 name: Setup pnpm cache with: path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - run: pnpm install - run: pnpm build - run: pnpm test - run: pnpm dtslint - run: pnpm lint - run: pnpm run docs ================================================ FILE: .gitignore ================================================ coverage/ *.tsbuildinfo node_modules/ yarn-error.log .ultra.cache.json .DS_Store tmp/ build/ dist/ .idea/ ================================================ FILE: .gitpod.yml ================================================ tasks: - init: npm install -g pnpm && pnpm && pnpm run build github: prebuilds: addCheck: true vscode: extensions: - dbaeumer.vscode-eslint ================================================ FILE: .vscode/settings.json ================================================ { "typescript.tsdk": "node_modules/typescript/lib", "typescript.preferences.importModuleSpecifier": "non-relative", "typescript.enablePromptUseWorkspaceTsdk": true, "editor.formatOnSave": true, "eslint.format.enable": true, "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[javascript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[javascriptreact]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[typescript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[typescriptreact]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "eslint.validate": ["markdown", "javascript", "typescript"], "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "editor.quickSuggestions": { "other": true, "comments": false, "strings": false }, "editor.acceptSuggestionOnCommitCharacter": true, "editor.acceptSuggestionOnEnter": "on", "editor.quickSuggestionsDelay": 10, "editor.suggestOnTriggerCharacters": true, "editor.tabCompletion": "off", "editor.suggest.localityBonus": true, "editor.suggestSelection": "recentlyUsed", "editor.wordBasedSuggestions": true, "editor.parameterHints.enabled": true, "files.watcherExclude": { "**/target": true }, "files.insertFinalNewline": true } ================================================ FILE: .vscode/tasks.json ================================================ { "version": "2.0.0", "tasks": [ { "label": "clean", "type": "shell", "command": "yarn clean", "isBackground": false, "problemMatcher": [] }, { "label": "build-watch", "type": "shell", "command": "yarn build-watch", "problemMatcher": ["$tsc-watch"], "isBackground": true, "presentation": { "focus": false, "panel": "shared", "group": "dev", "showReuseMessage": true, "clear": false } }, { "label": "build", "type": "shell", "command": "yarn build", "problemMatcher": [], "isBackground": false }, { "label": "test-watch", "dependsOn": ["build-watch"], "type": "shell", "command": "yarn test", "problemMatcher": [] } ] } ================================================ FILE: CHANGELOG.md ================================================ # @fp-ts/core ## 0.2.1 ### Patch Changes - [#59](https://github.com/fp-ts/core/pull/59) [`5efa9c03`](https://github.com/fp-ts/core/commit/5efa9c03572c9f39dd0e801dfe404e9e18d5fba2) Thanks [@gcanti](https://github.com/gcanti)! - Predicate: add more guards - [#60](https://github.com/fp-ts/core/pull/60) [`c48d2f56`](https://github.com/fp-ts/core/commit/c48d2f56063c31db5a42d426fa9a9ef270977843) Thanks [@gcanti](https://github.com/gcanti)! - add getOrThrowWith to Option, Either, These - [#57](https://github.com/fp-ts/core/pull/57) [`549509b8`](https://github.com/fp-ts/core/commit/549509b8a02a515becd514cfbb00044b313d5ede) Thanks [@gcanti](https://github.com/gcanti)! - Number: add remainder - [#56](https://github.com/fp-ts/core/pull/56) [`cf4918de`](https://github.com/fp-ts/core/commit/cf4918de74504ec59dd00df0ff251a549fb51284) Thanks [@gcanti](https://github.com/gcanti)! - ReadonlyArray: handle mutable arrays in isEmpty, isNonEmpty guards ## 0.2.0 ### Minor Changes - [#55](https://github.com/fp-ts/core/pull/55) [`b3e7ff34`](https://github.com/fp-ts/core/commit/b3e7ff34596b9cf90cc94c7349cf340fb0df82ef) Thanks [@gcanti](https://github.com/gcanti)! - Identity: remove exports except do notation ones - [#55](https://github.com/fp-ts/core/pull/55) [`a99a23a1`](https://github.com/fp-ts/core/commit/a99a23a15ccd1c9d1f623f39d4727cb3ff0be3f7) Thanks [@gcanti](https://github.com/gcanti)! - Either: make orElse, orElseEither lazy and remove catchAll - [#55](https://github.com/fp-ts/core/pull/55) [`31b5fffc`](https://github.com/fp-ts/core/commit/31b5fffc175f4740c8f31f05afba48b6b8cb9cd6) Thanks [@gcanti](https://github.com/gcanti)! - Option: remove fromThrowable - [#55](https://github.com/fp-ts/core/pull/55) [`14de6de2`](https://github.com/fp-ts/core/commit/14de6de207c63d460ecabcb6b13f5d9abb697f05) Thanks [@gcanti](https://github.com/gcanti)! - Option: remove coproductEither - [#55](https://github.com/fp-ts/core/pull/55) [`f3cc9d2c`](https://github.com/fp-ts/core/commit/f3cc9d2cf2440586f2681f447ae9056d94a631d7) Thanks [@gcanti](https://github.com/gcanti)! - rename `element` to `appendElement` - [#55](https://github.com/fp-ts/core/pull/55) [`2bb91d1e`](https://github.com/fp-ts/core/commit/2bb91d1e15ec62bfa762bb17aec6c97305b94692) Thanks [@gcanti](https://github.com/gcanti)! - Function: flip apply - [#55](https://github.com/fp-ts/core/pull/55) [`9569811e`](https://github.com/fp-ts/core/commit/9569811ea5506fb4206c1b9dbde7dbdbe7e9a8bc) Thanks [@gcanti](https://github.com/gcanti)! - Covariant: flip flap - [#55](https://github.com/fp-ts/core/pull/55) [`ae3338c0`](https://github.com/fp-ts/core/commit/ae3338c091284e0af7b24e1be818a96d59a77f09) Thanks [@gcanti](https://github.com/gcanti)! - Either: rename `firstSuccessOf` to `firstRightOf` - [#55](https://github.com/fp-ts/core/pull/55) [`a4a6ebbc`](https://github.com/fp-ts/core/commit/a4a6ebbcf73b453e526fbc42a76424732b8fdb23) Thanks [@gcanti](https://github.com/gcanti)! - remove `orElseSucceed` - [#55](https://github.com/fp-ts/core/pull/55) [`99088b21`](https://github.com/fp-ts/core/commit/99088b21a5945cb744a380947ee79378f19766f3) Thanks [@gcanti](https://github.com/gcanti)! - remove `imap` from exports - [#55](https://github.com/fp-ts/core/pull/55) [`d4fcf63e`](https://github.com/fp-ts/core/commit/d4fcf63e16f15ac86a96e89b0b47c7d2647a6fe6) Thanks [@gcanti](https://github.com/gcanti)! - Option: make orElse, orElseEither lazy and remove catchAll - [#55](https://github.com/fp-ts/core/pull/55) [`bfb22498`](https://github.com/fp-ts/core/commit/bfb22498cb9287d40e231b4992937e3313fae1fe) Thanks [@gcanti](https://github.com/gcanti)! - Option: remove `compact` - [#55](https://github.com/fp-ts/core/pull/55) [`4463f4f1`](https://github.com/fp-ts/core/commit/4463f4f1649ca2f984d715d0aa22055a3a8d6519) Thanks [@gcanti](https://github.com/gcanti)! - Option: change `firstSomeOf` signature - [#55](https://github.com/fp-ts/core/pull/55) [`18f70fcb`](https://github.com/fp-ts/core/commit/18f70fcb18c5e8f26980fd88c1192808df241631) Thanks [@gcanti](https://github.com/gcanti)! - Either: remove `fromThrowable` ### Patch Changes - [#55](https://github.com/fp-ts/core/pull/55) [`ce345a8d`](https://github.com/fp-ts/core/commit/ce345a8dd5bae7694cdbdd1bf5056b337175810d) Thanks [@gcanti](https://github.com/gcanti)! - add default handler to `getOrThrow` - [#55](https://github.com/fp-ts/core/pull/55) [`615d492e`](https://github.com/fp-ts/core/commit/615d492ea79b47472da256b4dea6f33835f24d23) Thanks [@gcanti](https://github.com/gcanti)! - algebraic operations: add support for bigint - [#55](https://github.com/fp-ts/core/pull/55) [`14f87fb3`](https://github.com/fp-ts/core/commit/14f87fb33061ef1e36a5695c0f28578c9f860cf1) Thanks [@gcanti](https://github.com/gcanti)! - Option: add `reduceAll` - [#51](https://github.com/fp-ts/core/pull/51) [`175d6b9e`](https://github.com/fp-ts/core/commit/175d6b9e93dbf6bfbea80b34a06f26ceb3d725aa) Thanks [@gcanti](https://github.com/gcanti)! - Option, Either, These: switch to interfaces - [#51](https://github.com/fp-ts/core/pull/51) [`3efb6d8a`](https://github.com/fp-ts/core/commit/3efb6d8a9a343ca177ec7bcc3e360974aec307cf) Thanks [@gcanti](https://github.com/gcanti)! - Function: add dual utility ## 0.1.1 ### Patch Changes - [#48](https://github.com/fp-ts/core/pull/48) [`da0bae84`](https://github.com/fp-ts/core/commit/da0bae8487d59d78c5ba6470d37727ccc66538bb) Thanks [@gcanti](https://github.com/gcanti)! - change structural tracking ## 0.1.0 ### Minor Changes - [#46](https://github.com/fp-ts/core/pull/46) [`0bd0d604`](https://github.com/fp-ts/core/commit/0bd0d60454642d7b1692d923c2d240b747ac797b) Thanks [@gcanti](https://github.com/gcanti)! - add modules from @fp-ts/data ### Patch Changes - [#46](https://github.com/fp-ts/core/pull/46) [`3c256fa8`](https://github.com/fp-ts/core/commit/3c256fa8b9bbb4379ad51c5e48781deaaac2990a) Thanks [@gcanti](https://github.com/gcanti)! - Add tracking code for Option ## next **Breaking changes** - remove `NonEmptyTraversable` module - `Semigroup` - make `combine` binary - make `combineMany` binary - `SemiCoproduct` - make `coproduct` binary - make `coproductMany` binary - `SemiProduct` - make `product` binary - make `productMany` binary - rename `productFlatten` to `element` - `Order` - make `compare` binary **New Features** - `Boolean` - add `not` combinator - `Order` - add `array` combinator - add `bigint` instance - `Monoid` - add `array`, `readonlyArray` combinators - `Semigroup` - add `array`, `readonlyArray` combinators - new modules - `typeclass/Equivalence` - `typeclass/Filterable` - `typeclass/TraversableFilterable` - `Bigint` - `Boolean` - `Either` - `Function` - `Identity` - `Number` - `Option` - `Ordering` - `Predicate` - `ReadonlyArray` - `ReadonyRecord` - `String` - `Struct` - `Symbol` - `These` - `Tuple` ## 0.0.11 ### Patch Changes - [#39](https://github.com/fp-ts/core/pull/39) [`c27db5e7`](https://github.com/fp-ts/core/commit/c27db5e796071966a64af1a860b56e417f99423e) Thanks [@gcanti](https://github.com/gcanti)! - revert 0.0.10 changes ## 0.0.10 ### Patch Changes - [#36](https://github.com/fp-ts/core/pull/36) [`51bb90bd`](https://github.com/fp-ts/core/commit/51bb90bd4f32bd878575a159a2bc0c8c3b3ff57b) Thanks [@gcanti](https://github.com/gcanti)! - remove readonly ## 0.0.9 ### Patch Changes - [#33](https://github.com/fp-ts/core/pull/33) [`c8246ea5`](https://github.com/fp-ts/core/commit/c8246ea56c07d44507b90be49bc529ddee2847d6) Thanks [@gcanti](https://github.com/gcanti)! - remove Compactable, Filterable, TraversableFilterable and /data folder ## 0.0.8 ### Patch Changes - [#29](https://github.com/fp-ts/core/pull/29) [`c2e0f09d`](https://github.com/fp-ts/core/commit/c2e0f09dc0d5aca2cc3c200adbe25991ff1a8c0c) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyAlternative: rename to SemiAlternative - [#29](https://github.com/fp-ts/core/pull/29) [`adbf4dbc`](https://github.com/fp-ts/core/commit/adbf4dbc1e6d8ea2d85e897de8048be7ac6dd88c) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyProduct: rename to SemiProduct - [#29](https://github.com/fp-ts/core/pull/29) [`07b7061b`](https://github.com/fp-ts/core/commit/07b7061bcef03d405a47777bc89e979c1b58e335) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyProduct: rename bindKind to andThenBind - [#29](https://github.com/fp-ts/core/pull/29) [`1f116d3d`](https://github.com/fp-ts/core/commit/1f116d3ddfbb26afd9e92b7001de7f1425774d3e) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyApplicative: rename to SemiApplicative - [#29](https://github.com/fp-ts/core/pull/29) [`d539285e`](https://github.com/fp-ts/core/commit/d539285e270d69bd995a3ebc4e98a84b74665f46) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyCoproduct: rename to SemiCoproduct ## 0.0.7 ### Patch Changes - [#26](https://github.com/fp-ts/core/pull/26) [`2aa35975`](https://github.com/fp-ts/core/commit/2aa35975d2803377c0a629603b308e3c2c6448b9) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyTraversable: rename nonEmptyTraverse to traverseNonEmpty, nonEmptySequence to sequenceNonEmpty - [#26](https://github.com/fp-ts/core/pull/26) [`9d4ac0bb`](https://github.com/fp-ts/core/commit/9d4ac0bb2dc82a33a9959565b6af8289af0f4403) Thanks [@gcanti](https://github.com/gcanti)! - Traversable: add sequence as member - [#26](https://github.com/fp-ts/core/pull/26) [`eb6020ca`](https://github.com/fp-ts/core/commit/eb6020ca6b8d1cbe3cb4ead58ab9b54cc9ce82a3) Thanks [@gcanti](https://github.com/gcanti)! - Foldable: remove reduceRight from typeclass - [#28](https://github.com/fp-ts/core/pull/28) [`9f6a193e`](https://github.com/fp-ts/core/commit/9f6a193e4580aadc18ccc172a9e3cf6ffde5c19d) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyCoproduct / Coproduct: fix getSemigroup / getMonoid type params - [#26](https://github.com/fp-ts/core/pull/26) [`29a94c17`](https://github.com/fp-ts/core/commit/29a94c17f0f018627892f1749acbdea07471374f) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyProduct: rename struct to nonEmptyStruct - [#26](https://github.com/fp-ts/core/pull/26) [`577f9597`](https://github.com/fp-ts/core/commit/577f9597db0a53728fca14e9a945e1e0d7164957) Thanks [@gcanti](https://github.com/gcanti)! - Foldable: add a default `reduceRight` implementation - [#26](https://github.com/fp-ts/core/pull/26) [`fc914c93`](https://github.com/fp-ts/core/commit/fc914c9319017abd3da4b11987342fbf56806eca) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyTraversable: add sequenceNonEmpty as member - [#26](https://github.com/fp-ts/core/pull/26) [`fc4d0aae`](https://github.com/fp-ts/core/commit/fc4d0aaef2aeca6b63f10432695c62e808c6310b) Thanks [@gcanti](https://github.com/gcanti)! - NonEmptyProduct: rename tuple to nonEmptyTuple ## 0.0.6 ### Patch Changes - [#22](https://github.com/fp-ts/core/pull/22) [`e71d3d57`](https://github.com/fp-ts/core/commit/e71d3d57b0869ab3283a7bb68e76452bc0a2ffba) Thanks [@gcanti](https://github.com/gcanti)! - rename HKT params ## 0.0.5 ### Patch Changes - [#18](https://github.com/fp-ts/core/pull/18) [`be638f44`](https://github.com/fp-ts/core/commit/be638f44764484c8d93943d916d3fc0285466cbd) Thanks [@gcanti](https://github.com/gcanti)! - Semigroup: fix reverse implementation - [#18](https://github.com/fp-ts/core/pull/18) [`ae9715f6`](https://github.com/fp-ts/core/commit/ae9715f6670fda76e25c955cdaab17c65af098ba) Thanks [@gcanti](https://github.com/gcanti)! - Foldable / FoldableWithIndex: add compositions - [#18](https://github.com/fp-ts/core/pull/18) [`ba899d76`](https://github.com/fp-ts/core/commit/ba899d76debfd15031d0fff9079332fd33394f9b) Thanks [@gcanti](https://github.com/gcanti)! - Foldable / FlodableWithIndex: curry toReadonlyArrayWith and add toReadonlyArray - [#18](https://github.com/fp-ts/core/pull/18) [`2d30a185`](https://github.com/fp-ts/core/commit/2d30a1852227ac4f5279ebafef46ac527f5048ee) Thanks [@gcanti](https://github.com/gcanti)! - add FunctorWithIndex module - [#18](https://github.com/fp-ts/core/pull/18) [`9c531794`](https://github.com/fp-ts/core/commit/9c531794ca69346f38740e002687e4bd55fcb6b9) Thanks [@gcanti](https://github.com/gcanti)! - Semigroupal: remove useless zipWith export - [#18](https://github.com/fp-ts/core/pull/18) [`9683f82d`](https://github.com/fp-ts/core/commit/9683f82d68e35bfa471a6b39d59830b078d868c9) Thanks [@gcanti](https://github.com/gcanti)! - Bounded: swap maximum, minimum arguments in fromSortable ## 0.0.4 ### Patch Changes - [#14](https://github.com/fp-ts/core/pull/14) [`1cac5547`](https://github.com/fp-ts/core/commit/1cac5547815673308916236780b94c6263825cde) Thanks [@gcanti](https://github.com/gcanti)! - rename Succeed typeclass to Pointed / of - [#14](https://github.com/fp-ts/core/pull/14) [`6c9be695`](https://github.com/fp-ts/core/commit/6c9be6950e8bb004802dce959f8d133f7e911aa7) Thanks [@gcanti](https://github.com/gcanti)! - make all typeclass operations pipeable - [#14](https://github.com/fp-ts/core/pull/14) [`8ae84df9`](https://github.com/fp-ts/core/commit/8ae84df993f63d1255a9b40a614fcc79fea8ad68) Thanks [@gcanti](https://github.com/gcanti)! - SemigroupKind: fix combineKind signature - [#14](https://github.com/fp-ts/core/pull/14) [`51d62040`](https://github.com/fp-ts/core/commit/51d62040bf25ddc8e7911171d48b60282a35fb26) Thanks [@gcanti](https://github.com/gcanti)! - Ordering: remove sign function - [#14](https://github.com/fp-ts/core/pull/14) [`89665e87`](https://github.com/fp-ts/core/commit/89665e8768e1c9fac1894c12b74e5941341a9473) Thanks [@gcanti](https://github.com/gcanti)! - remove Show typeclass ## 0.0.3 ### Patch Changes - [#12](https://github.com/fp-ts/core/pull/12) [`7c6fa2c4`](https://github.com/fp-ts/core/commit/7c6fa2c4992dd3aeffbd1e7a9aeb564a62c5f149) Thanks [@mikearnaldi](https://github.com/mikearnaldi)! - type class refactoring ## 0.0.2 ### Patch Changes - [#8](https://github.com/fp-ts/core/pull/8) [`79b1237c`](https://github.com/fp-ts/core/commit/79b1237c22a16f8354f8c5f086922585ce26b572) Thanks [@mikearnaldi](https://github.com/mikearnaldi)! - Fix package json repository urls ## 0.0.1 ### Patch Changes - [#1](https://github.com/fp-ts/core/pull/1) [`65983dd9`](https://github.com/fp-ts/core/commit/65983dd99a04cd2d1d6f503dabaa600df5c82d17) Thanks [@mikearnaldi](https://github.com/mikearnaldi)! - Dual ESM-CJS Support ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2017-present Giulio Canti Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ **Announcement**: following the [official decision](https://dev.to/effect-ts/a-bright-future-for-effect-455m) to merge the `fp-ts` project with the Effect-TS ecosystem, active development has been transferred to the repository https://github.com/Effect-TS/data. ================================================ FILE: benchmark/Number/lessThan.ts ================================================ import { dual } from "@fp-ts/core/Function"; import { lessThan } from "@fp-ts/core/Number" import * as Benchmark from "benchmark" /* */ const suite = new Benchmark.Suite() const lessThanBaseline: { (that: number): (self: number) => boolean; (self: number, that: number): boolean; } = dual(2, (self: number, that: number): boolean => self < that) suite .add("lessThanBaseline", function() { lessThanBaseline(2, 1) }) .add("lessThan", function() { lessThan(2, 1) }) .on("cycle", function(event: any) { console.log(String(event.target)) }) .on("complete", function(this: any) { console.log("Fastest is " + this.filter("fastest").map("name")) }) .run({ async: true }) ================================================ FILE: benchmark/These/product.ts ================================================ import { Product, right, fail } from "@fp-ts/core/These" import * as Benchmark from "benchmark" /* */ const suite = new Benchmark.Suite() suite .add("Product.product", function() { Product.product(right(1), fail('e')) }) .add("Product.productAll", function() { Product.productAll([right(1), fail('e')]) }) .on("cycle", function(event: any) { console.log(String(event.target)) }) .on("complete", function(this: any) { console.log("Fastest is " + this.filter("fastest").map("name")) }) .run({ async: true }) ================================================ FILE: benchmark/dual.ts ================================================ import { sum } from "@fp-ts/core/Number" import * as Benchmark from "benchmark" /* sum(a, b) x 39,807,035 ops/sec ±0.79% (87 runs sampled) binary(a, b) x 745,618,052 ops/sec ±0.53% (91 runs sampled) sum(b)(a) x 2,423,147 ops/sec ±1.50% (82 runs sampled) curried(b)(a) x 737,608,819 ops/sec ±0.60% (88 runs sampled) */ const suite = new Benchmark.Suite() const binary = (a: number, b: number): number => a + b const curried = (a: number) => (b: number): number => a + b suite .add("sum(a, b)", function() { sum(1, 2) }) .add("binary(a, b)", function() { binary(1, 2) }) .add("sum(b)(a)", function() { sum(2)(1) }) .add("curried(b)(a)", function() { curried(2)(1) }) .on("cycle", function(event: any) { console.log(String(event.target)) }) .on("complete", function(this: any) { console.log("Fastest is " + this.filter("fastest").map("name")) }) .run({ async: true }) ================================================ FILE: benchmark/sumAll.ts ================================================ import { fromIterable } from "@fp-ts/core/internal/ReadonlyArray" import { sumAll } from "@fp-ts/core/Number" import * as Benchmark from "benchmark" /* sumAll x 98,318,148 ops/sec ±0.46% (91 runs sampled) sum x 104,495,149 ops/sec ±0.76% (90 runs sampled) */ const suite = new Benchmark.Suite() const sum = (collection: Iterable): number => fromIterable(collection).reduce((a, b) => a + b, 0) suite .add("sumAll", function() { sumAll([1, 2, 3, 4, 5]) }) .add("sum", function() { sum([1, 2, 3, 4, 5]) }) .on("cycle", function(event: any) { console.log(String(event.target)) }) .on("complete", function(this: any) { console.log("Fastest is " + this.filter("fastest").map("name")) }) .run({ async: true }) ================================================ FILE: benchmark/tsconfig.json ================================================ { "compilerOptions": { "strict": true, "module": "commonjs", "paths": { "@fp-ts/core": ["../src/index.ts"], "@fp-ts/core/test/*": ["../test/*"], "@fp-ts/core/examples/*": ["../examples/*"], "@fp-ts/core/*": ["../src/*"] } } } ================================================ FILE: docs/_config.yml ================================================ remote_theme: mikearnaldi/just-the-docs # Enable or disable the site search search_enabled: true # Aux links for the upper right navigation aux_links: "Docs": - "//fp-ts.github.io/core" "API Reference": - "//fp-ts.github.io/core/docs/modules" "GitHub": - "//github.com/fp-ts/core" ================================================ FILE: docs/_sass/custom/custom.scss ================================================ $fp-ts-blue-000: #0088e6; $fp-ts-blue-100: #0075c5; $link-color: $fp-ts-blue-000; $btn-primary-color: $fp-ts-blue-100; ================================================ FILE: docs/index.md ================================================ --- title: Introduction permalink: / nav_order: 1 has_children: false has_toc: false --- fp-ts logo # Typed functional programming in TypeScript `@fp-ts/core` provides developers with popular patterns and reliable abstractions from typed functional languages in TypeScript. {: .fs-6 .fw-300 } **Disclaimer**. Teaching functional programming is out of scope of this project, so the documentation assumes you already know what FP is. ================================================ FILE: docs/modules/Bigint.ts.md ================================================ --- title: Bigint.ts nav_order: 1 parent: Modules --- ## Bigint overview This module provides utility functions and type class instances for working with the `bigint` type in TypeScript. It includes functions for basic arithmetic operations, as well as type class instances for `Equivalence`, `Order`, `Semigroup`, and `Monoid`. Added in v1.0.0 ---

Table of contents

- [guards](#guards) - [isBigint](#isbigint) - [instances](#instances) - [Equivalence](#equivalence) - [MonoidMultiply](#monoidmultiply) - [MonoidSum](#monoidsum) - [Order](#order) - [SemigroupMax](#semigroupmax) - [SemigroupMin](#semigroupmin) - [SemigroupMultiply](#semigroupmultiply) - [SemigroupSum](#semigroupsum) - [math](#math) - [decrement](#decrement) - [divide](#divide) - [increment](#increment) - [multiply](#multiply) - [multiplyAll](#multiplyall) - [sign](#sign) - [subtract](#subtract) - [sum](#sum) - [sumAll](#sumall) - [predicates](#predicates) - [between](#between) - [greaterThan](#greaterthan) - [greaterThanOrEqualTo](#greaterthanorequalto) - [lessThan](#lessthan) - [lessThanOrEqualTo](#lessthanorequalto) - [utils](#utils) - [clamp](#clamp) - [max](#max) - [min](#min) --- # guards ## isBigint Tests if a value is a `bigint`. **Signature** ```ts export declare const isBigint: (u: unknown) => u is bigint ``` **Example** ```ts import { isBigint } from '@fp-ts/core/Bigint' assert.deepStrictEqual(isBigint(1n), true) assert.deepStrictEqual(isBigint(1), false) ``` Added in v1.0.0 # instances ## Equivalence **Signature** ```ts export declare const Equivalence: equivalence.Equivalence ``` Added in v1.0.0 ## MonoidMultiply `bigint` monoid under multiplication. The `empty` value is `1n`. **Signature** ```ts export declare const MonoidMultiply: monoid.Monoid ``` **Example** ```ts import { MonoidMultiply } from '@fp-ts/core/Bigint' assert.deepStrictEqual(MonoidMultiply.combine(2n, 3n), 6n) assert.deepStrictEqual(MonoidMultiply.combine(2n, MonoidMultiply.empty), 2n) ``` Added in v1.0.0 ## MonoidSum `bigint` monoid under addition. The `empty` value is `0n`. **Signature** ```ts export declare const MonoidSum: monoid.Monoid ``` **Example** ```ts import { MonoidSum } from '@fp-ts/core/Bigint' assert.deepStrictEqual(MonoidSum.combine(2n, 3n), 5n) assert.deepStrictEqual(MonoidSum.combine(2n, MonoidSum.empty), 2n) ``` Added in v1.0.0 ## Order **Signature** ```ts export declare const Order: order.Order ``` Added in v1.0.0 ## SemigroupMax A `Semigroup` that uses the maximum between two values. **Signature** ```ts export declare const SemigroupMax: semigroup.Semigroup ``` **Example** ```ts import { SemigroupMax } from '@fp-ts/core/Bigint' assert.deepStrictEqual(SemigroupMax.combine(2n, 3n), 3n) ``` Added in v1.0.0 ## SemigroupMin A `Semigroup` that uses the minimum between two values. **Signature** ```ts export declare const SemigroupMin: semigroup.Semigroup ``` **Example** ```ts import { SemigroupMin } from '@fp-ts/core/Bigint' assert.deepStrictEqual(SemigroupMin.combine(2n, 3n), 2n) ``` Added in v1.0.0 ## SemigroupMultiply `bigint` semigroup under multiplication. **Signature** ```ts export declare const SemigroupMultiply: semigroup.Semigroup ``` Added in v1.0.0 ## SemigroupSum `bigint` semigroup under addition. **Signature** ```ts export declare const SemigroupSum: semigroup.Semigroup ``` **Example** ```ts import { SemigroupSum } from '@fp-ts/core/Bigint' assert.deepStrictEqual(SemigroupSum.combine(2n, 3n), 5n) ``` Added in v1.0.0 # math ## decrement Decrements a number by `1n`. **Signature** ```ts export declare const decrement: (n: bigint) => bigint ``` **Example** ```ts import { decrement } from '@fp-ts/core/Bigint' assert.deepStrictEqual(decrement(3n), 2n) ``` Added in v1.0.0 ## divide Provides a division operation on `bigint`s. If the dividend is not a multiple of the divisor the result will be a `bigint` value which represents the integer division rounded down to the nearest integer. **Signature** ```ts export declare const divide: { (that: bigint): (self: bigint) => bigint; (self: bigint, that: bigint): bigint } ``` **Example** ```ts import { divide } from '@fp-ts/core/Bigint' assert.deepStrictEqual(divide(6n, 3n), 2n) assert.deepStrictEqual(divide(6n, 4n), 1n) ``` Added in v1.0.0 ## increment Returns the result of adding `1n` to a given number. **Signature** ```ts export declare const increment: (n: bigint) => bigint ``` **Example** ```ts import { increment } from '@fp-ts/core/Bigint' assert.deepStrictEqual(increment(2n), 3n) ``` Added in v1.0.0 ## multiply Provides a multiplication operation on `bigint`s. **Signature** ```ts export declare const multiply: { (that: bigint): (self: bigint) => bigint; (self: bigint, that: bigint): bigint } ``` **Example** ```ts import { multiply } from '@fp-ts/core/Bigint' assert.deepStrictEqual(multiply(2n, 3n), 6n) ``` Added in v1.0.0 ## multiplyAll Takes an `Iterable` of `bigint`s and returns their multiplication as a single `number`. **Signature** ```ts export declare const multiplyAll: (collection: Iterable) => bigint ``` **Example** ```ts import { multiplyAll } from '@fp-ts/core/Bigint' assert.deepStrictEqual(multiplyAll([2n, 3n, 4n]), 24n) ``` Added in v1.0.0 ## sign Determines the sign of a given `bigint`. **Signature** ```ts export declare const sign: (n: bigint) => Ordering ``` **Example** ```ts import { sign } from '@fp-ts/core/Bigint' assert.deepStrictEqual(sign(-5n), -1) assert.deepStrictEqual(sign(0n), 0) assert.deepStrictEqual(sign(5n), 1) ``` Added in v1.0.0 ## subtract Provides a subtraction operation on `bigint`s. **Signature** ```ts export declare const subtract: { (that: bigint): (self: bigint) => bigint; (self: bigint, that: bigint): bigint } ``` **Example** ```ts import { subtract } from '@fp-ts/core/Bigint' assert.deepStrictEqual(subtract(2n, 3n), -1n) ``` Added in v1.0.0 ## sum Provides an addition operation on `bigint`s. **Signature** ```ts export declare const sum: { (that: bigint): (self: bigint) => bigint; (self: bigint, that: bigint): bigint } ``` **Example** ```ts import { sum } from '@fp-ts/core/Bigint' assert.deepStrictEqual(sum(2n, 3n), 5n) ``` Added in v1.0.0 ## sumAll Takes an `Iterable` of `bigint`s and returns their sum as a single `bigint **Signature** ```ts export declare const sumAll: (collection: Iterable) => bigint ``` **Example** ```ts import { sumAll } from '@fp-ts/core/Bigint' assert.deepStrictEqual(sumAll([2n, 3n, 4n]), 9n) ``` Added in v1.0.0 # predicates ## between Checks if a `bigint` is between a `minimum` and `maximum` value (inclusive). **Signature** ```ts export declare const between: { (minimum: bigint, maximum: bigint): (self: bigint) => boolean (self: bigint, minimum: bigint, maximum: bigint): boolean } ``` **Example** ```ts import { between } from '@fp-ts/core/Bigint' assert.deepStrictEqual(between(0n, 5n)(3n), true) assert.deepStrictEqual(between(0n, 5n)(-1n), false) assert.deepStrictEqual(between(0n, 5n)(6n), false) ``` Added in v1.0.0 ## greaterThan Returns `true` if the first argument is greater than the second, otherwise `false`. **Signature** ```ts export declare const greaterThan: { (that: bigint): (self: bigint) => boolean; (self: bigint, that: bigint): boolean } ``` **Example** ```ts import { greaterThan } from '@fp-ts/core/Bigint' assert.deepStrictEqual(greaterThan(2n, 3n), false) assert.deepStrictEqual(greaterThan(3n, 3n), false) assert.deepStrictEqual(greaterThan(4n, 3n), true) ``` Added in v1.0.0 ## greaterThanOrEqualTo Returns a function that checks if a given `bigint` is greater than or equal to the provided one. **Signature** ```ts export declare const greaterThanOrEqualTo: { (that: bigint): (self: bigint) => boolean (self: bigint, that: bigint): boolean } ``` **Example** ```ts import { greaterThanOrEqualTo } from '@fp-ts/core/Bigint' assert.deepStrictEqual(greaterThanOrEqualTo(2n, 3n), false) assert.deepStrictEqual(greaterThanOrEqualTo(3n, 3n), true) assert.deepStrictEqual(greaterThanOrEqualTo(4n, 3n), true) ``` Added in v1.0.0 ## lessThan Returns `true` if the first argument is less than the second, otherwise `false`. **Signature** ```ts export declare const lessThan: { (that: bigint): (self: bigint) => boolean; (self: bigint, that: bigint): boolean } ``` **Example** ```ts import { lessThan } from '@fp-ts/core/Bigint' assert.deepStrictEqual(lessThan(2n, 3n), true) assert.deepStrictEqual(lessThan(3n, 3n), false) assert.deepStrictEqual(lessThan(4n, 3n), false) ``` Added in v1.0.0 ## lessThanOrEqualTo Returns a function that checks if a given `bigint` is less than or equal to the provided one. **Signature** ```ts export declare const lessThanOrEqualTo: { (that: bigint): (self: bigint) => boolean (self: bigint, that: bigint): boolean } ``` **Example** ```ts import { lessThanOrEqualTo } from '@fp-ts/core/Bigint' assert.deepStrictEqual(lessThanOrEqualTo(2n, 3n), true) assert.deepStrictEqual(lessThanOrEqualTo(3n, 3n), true) assert.deepStrictEqual(lessThanOrEqualTo(4n, 3n), false) ``` Added in v1.0.0 # utils ## clamp Restricts the given `bigint` to be within the range specified by the `minimum` and `maximum` values. - If the `bigint` is less than the `minimum` value, the function returns the `minimum` value. - If the `bigint` is greater than the `maximum` value, the function returns the `maximum` value. - Otherwise, it returns the original `bigint`. **Signature** ```ts export declare const clamp: { (minimum: bigint, maximum: bigint): (self: bigint) => bigint (self: bigint, minimum: bigint, maximum: bigint): bigint } ``` **Example** ```ts import { clamp } from '@fp-ts/core/Bigint' assert.deepStrictEqual(clamp(0n, 5n)(3n), 3n) assert.deepStrictEqual(clamp(0n, 5n)(-1n), 0n) assert.deepStrictEqual(clamp(0n, 5n)(6n), 5n) ``` Added in v1.0.0 ## max Returns the maximum between two `bigint`s. **Signature** ```ts export declare const max: { (that: bigint): (self: bigint) => bigint; (self: bigint, that: bigint): bigint } ``` **Example** ```ts import { max } from '@fp-ts/core/Bigint' assert.deepStrictEqual(max(2n, 3n), 3n) ``` Added in v1.0.0 ## min Returns the minimum between two `bigint`s. **Signature** ```ts export declare const min: { (that: bigint): (self: bigint) => bigint; (self: bigint, that: bigint): bigint } ``` **Example** ```ts import { min } from '@fp-ts/core/Bigint' assert.deepStrictEqual(min(2n, 3n), 2n) ``` Added in v1.0.0 ================================================ FILE: docs/modules/Boolean.ts.md ================================================ --- title: Boolean.ts nav_order: 2 parent: Modules --- ## Boolean overview This module provides utility functions and type class instances for working with the `boolean` type in TypeScript. It includes functions for basic boolean operations, as well as type class instances for `Equivalence`, `Order`, `Semigroup`, and `Monoid`. Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [and](#and) - [eqv](#eqv) - [implies](#implies) - [nand](#nand) - [nor](#nor) - [not](#not) - [or](#or) - [xor](#xor) - [guards](#guards) - [isBoolean](#isboolean) - [instances](#instances) - [Equivalence](#equivalence) - [MonoidAll](#monoidall) - [MonoidAny](#monoidany) - [MonoidEqv](#monoideqv) - [MonoidXor](#monoidxor) - [Order](#order) - [SemigroupAll](#semigroupall) - [SemigroupAny](#semigroupany) - [SemigroupEqv](#semigroupeqv) - [SemigroupXor](#semigroupxor) - [pattern matching](#pattern-matching) - [match](#match) - [utils](#utils) - [all](#all) - [any](#any) --- # combinators ## and Combines two boolean using AND: `self && that`. **Signature** ```ts export declare const and: { (that: boolean): (self: boolean) => boolean; (self: boolean, that: boolean): boolean } ``` **Example** ```ts import { and } from '@fp-ts/core/Boolean' assert.deepStrictEqual(and(true, true), true) assert.deepStrictEqual(and(true, false), false) assert.deepStrictEqual(and(false, true), false) assert.deepStrictEqual(and(false, false), false) ``` Added in v1.0.0 ## eqv Combines two booleans using EQV (aka XNOR): `!xor(self, that)`. **Signature** ```ts export declare const eqv: { (that: boolean): (self: boolean) => boolean; (self: boolean, that: boolean): boolean } ``` **Example** ```ts import { eqv } from '@fp-ts/core/Boolean' assert.deepStrictEqual(eqv(true, true), true) assert.deepStrictEqual(eqv(true, false), false) assert.deepStrictEqual(eqv(false, true), false) assert.deepStrictEqual(eqv(false, false), true) ``` Added in v1.0.0 ## implies Combines two booleans using an implication: `(!self || that)`. **Signature** ```ts export declare const implies: { (that: boolean): (self: boolean) => boolean; (self: boolean, that: boolean): boolean } ``` **Example** ```ts import { implies } from '@fp-ts/core/Boolean' assert.deepStrictEqual(implies(true, true), true) assert.deepStrictEqual(implies(true, false), false) assert.deepStrictEqual(implies(false, true), true) assert.deepStrictEqual(implies(false, false), true) ``` Added in v1.0.0 ## nand Combines two boolean using NAND: `!(self && that)`. **Signature** ```ts export declare const nand: { (that: boolean): (self: boolean) => boolean; (self: boolean, that: boolean): boolean } ``` **Example** ```ts import { nand } from '@fp-ts/core/Boolean' assert.deepStrictEqual(nand(true, true), false) assert.deepStrictEqual(nand(true, false), true) assert.deepStrictEqual(nand(false, true), true) assert.deepStrictEqual(nand(false, false), true) ``` Added in v1.0.0 ## nor Combines two booleans using NOR: `!(self || that)`. **Signature** ```ts export declare const nor: { (that: boolean): (self: boolean) => boolean; (self: boolean, that: boolean): boolean } ``` **Example** ```ts import { nor } from '@fp-ts/core/Boolean' assert.deepStrictEqual(nor(true, true), false) assert.deepStrictEqual(nor(true, false), false) assert.deepStrictEqual(nor(false, true), false) assert.deepStrictEqual(nor(false, false), true) ``` Added in v1.0.0 ## not Negates the given boolean: `!self` **Signature** ```ts export declare const not: (self: boolean) => boolean ``` **Example** ```ts import { not } from '@fp-ts/core/Boolean' assert.deepStrictEqual(not(true), false) assert.deepStrictEqual(not(false), true) ``` Added in v1.0.0 ## or Combines two boolean using OR: `self || that`. **Signature** ```ts export declare const or: { (that: boolean): (self: boolean) => boolean; (self: boolean, that: boolean): boolean } ``` **Example** ```ts import { or } from '@fp-ts/core/Boolean' assert.deepStrictEqual(or(true, true), true) assert.deepStrictEqual(or(true, false), true) assert.deepStrictEqual(or(false, true), true) assert.deepStrictEqual(or(false, false), false) ``` Added in v1.0.0 ## xor Combines two booleans using XOR: `(!self && that) || (self && !that)`. **Signature** ```ts export declare const xor: { (that: boolean): (self: boolean) => boolean; (self: boolean, that: boolean): boolean } ``` **Example** ```ts import { xor } from '@fp-ts/core/Boolean' assert.deepStrictEqual(xor(true, true), false) assert.deepStrictEqual(xor(true, false), true) assert.deepStrictEqual(xor(false, true), true) assert.deepStrictEqual(xor(false, false), false) ``` Added in v1.0.0 # guards ## isBoolean Tests if a value is a `boolean`. **Signature** ```ts export declare const isBoolean: (input: unknown) => input is boolean ``` **Example** ```ts import { isBoolean } from '@fp-ts/core/Boolean' assert.deepStrictEqual(isBoolean(true), true) assert.deepStrictEqual(isBoolean('true'), false) ``` Added in v1.0.0 # instances ## Equivalence **Signature** ```ts export declare const Equivalence: equivalence.Equivalence ``` Added in v1.0.0 ## MonoidAll `boolean` monoid under conjunction, see also {@link SemigroupAll}. The `empty` value is `true`. **Signature** ```ts export declare const MonoidAll: monoid.Monoid ``` Added in v1.0.0 ## MonoidAny `boolean` monoid under disjunction, see also {@link SemigroupAny}. The `empty` value is `false`. **Signature** ```ts export declare const MonoidAny: monoid.Monoid ``` Added in v1.0.0 ## MonoidEqv `boolean` monoid under equivalence. The `empty` value is `true`. **Signature** ```ts export declare const MonoidEqv: monoid.Monoid ``` Added in v1.0.0 ## MonoidXor `boolean` monoid under exclusive disjunction, see also {@link SemigroupXor}. The `empty` value is `false`. **Signature** ```ts export declare const MonoidXor: monoid.Monoid ``` Added in v1.0.0 ## Order **Signature** ```ts export declare const Order: order.Order ``` Added in v1.0.0 ## SemigroupAll `boolean` semigroup under conjunction. **Signature** ```ts export declare const SemigroupAll: semigroup.Semigroup ``` **Example** ```ts import { SemigroupAll } from '@fp-ts/core/Boolean' assert.deepStrictEqual(SemigroupAll.combine(true, true), true) assert.deepStrictEqual(SemigroupAll.combine(true, false), false) assert.deepStrictEqual(SemigroupAll.combine(false, true), false) assert.deepStrictEqual(SemigroupAll.combine(false, false), false) ``` Added in v1.0.0 ## SemigroupAny `boolean` semigroup under disjunction. **Signature** ```ts export declare const SemigroupAny: semigroup.Semigroup ``` **Example** ```ts import { SemigroupAny } from '@fp-ts/core/Boolean' assert.deepStrictEqual(SemigroupAny.combine(true, true), true) assert.deepStrictEqual(SemigroupAny.combine(true, false), true) assert.deepStrictEqual(SemigroupAny.combine(false, true), true) assert.deepStrictEqual(SemigroupAny.combine(false, false), false) ``` Added in v1.0.0 ## SemigroupEqv `boolean` semigroup under equivalence. **Signature** ```ts export declare const SemigroupEqv: semigroup.Semigroup ``` **Example** ```ts import { SemigroupEqv } from '@fp-ts/core/Boolean' assert.deepStrictEqual(SemigroupEqv.combine(true, true), true) assert.deepStrictEqual(SemigroupEqv.combine(true, false), false) assert.deepStrictEqual(SemigroupEqv.combine(false, true), false) assert.deepStrictEqual(SemigroupEqv.combine(false, false), true) ``` Added in v1.0.0 ## SemigroupXor `boolean` semigroup under exclusive disjunction. **Signature** ```ts export declare const SemigroupXor: semigroup.Semigroup ``` **Example** ```ts import { SemigroupXor } from '@fp-ts/core/Boolean' assert.deepStrictEqual(SemigroupXor.combine(true, true), false) assert.deepStrictEqual(SemigroupXor.combine(true, false), true) assert.deepStrictEqual(SemigroupXor.combine(false, true), true) assert.deepStrictEqual(SemigroupXor.combine(false, false), false) ``` Added in v1.0.0 # pattern matching ## match This function returns the result of either of the given functions depending on the value of the boolean parameter. It is useful when you have to run one of two functions depending on the boolean value. **Signature** ```ts export declare const match: { (onFalse: LazyArg, onTrue: LazyArg): (value: boolean) => A | B (value: boolean, onFalse: LazyArg, onTrue: LazyArg): A | B } ``` **Example** ```ts import * as B from '@fp-ts/core/Boolean' assert.deepStrictEqual( B.match( true, () => "It's false!", () => "It's true!" ), "It's true!" ) ``` Added in v1.0.0 # utils ## all This utility function is used to check if all the elements in a collection of boolean values are `true`. **Signature** ```ts export declare const all: (collection: Iterable) => boolean ``` **Example** ```ts import { all } from '@fp-ts/core/Boolean' assert.deepStrictEqual(all([true, true, true]), true) assert.deepStrictEqual(all([true, false, true]), false) ``` Added in v1.0.0 ## any This utility function is used to check if at least one of the elements in a collection of boolean values is `true`. **Signature** ```ts export declare const any: (collection: Iterable) => boolean ``` **Example** ```ts import { any } from '@fp-ts/core/Boolean' assert.deepStrictEqual(any([true, false, true]), true) assert.deepStrictEqual(any([false, false, false]), false) ``` Added in v1.0.0 ================================================ FILE: docs/modules/Either.ts.md ================================================ --- title: Either.ts nav_order: 3 parent: Modules --- ## Either overview Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [tap](#tap) - [combining](#combining) - [all](#all) - [andThenDiscard](#andthendiscard) - [flatMap](#flatmap) - [flatMapNullable](#flatmapnullable) - [flatMapOption](#flatmapoption) - [getFirstLeftMonoid](#getfirstleftmonoid) - [getFirstLeftSemigroup](#getfirstleftsemigroup) - [getFirstRightSemigroup](#getfirstrightsemigroup) - [zipWith](#zipwith) - [constructors](#constructors) - [left](#left) - [of](#of) - [right](#right) - [conversions](#conversions) - [fromIterable](#fromiterable) - [fromOption](#fromoption) - [getLeft](#getleft) - [getRight](#getright) - [toArray](#toarray) - [toOption](#tooption) - [toRefinement](#torefinement) - [debugging](#debugging) - [inspectLeft](#inspectleft) - [inspectRight](#inspectright) - [do notation](#do-notation) - [Do](#do) - [andThenBind](#andthenbind) - [appendElement](#appendelement) - [bind](#bind) - [bindTo](#bindto) - [let](#let) - [tupled](#tupled) - [equivalence](#equivalence) - [getEquivalence](#getequivalence) - [error handling](#error-handling) - [firstRightOf](#firstrightof) - [mapLeft](#mapleft) - [orElse](#orelse) - [orElseEither](#orelseeither) - [orElseFail](#orelsefail) - [tapError](#taperror) - [filtering](#filtering) - [compact](#compact) - [filter](#filter) - [filterMap](#filtermap) - [getters](#getters) - [getOrElse](#getorelse) - [getOrNull](#getornull) - [getOrUndefined](#getorundefined) - [lefts](#lefts) - [rights](#rights) - [guards](#guards) - [isEither](#iseither) - [isLeft](#isleft) - [isRight](#isright) - [instances](#instances) - [Applicative](#applicative) - [Bicovariant](#bicovariant) - [Chainable](#chainable) - [Covariant](#covariant) - [FlatMap](#flatmap) - [Foldable](#foldable) - [Invariant](#invariant) - [Monad](#monad) - [Of](#of) - [Pointed](#pointed) - [Product](#product) - [SemiAlternative](#semialternative) - [SemiApplicative](#semiapplicative) - [SemiCoproduct](#semicoproduct) - [SemiProduct](#semiproduct) - [Traversable](#traversable) - [getOptionalSemigroup](#getoptionalsemigroup) - [interop](#interop) - [fromNullable](#fromnullable) - [getOrThrow](#getorthrow) - [getOrThrowWith](#getorthrowwith) - [liftNullable](#liftnullable) - [liftThrowable](#liftthrowable) - [merge](#merge) - [lifting](#lifting) - [lift2](#lift2) - [liftOption](#liftoption) - [liftPredicate](#liftpredicate) - [mapping](#mapping) - [as](#as) - [asUnit](#asunit) - [bimap](#bimap) - [flap](#flap) - [map](#map) - [math](#math) - [divide](#divide) - [multiply](#multiply) - [subtract](#subtract) - [sum](#sum) - [models](#models) - [Either (type alias)](#either-type-alias) - [Left (interface)](#left-interface) - [Right (interface)](#right-interface) - [pattern matching](#pattern-matching) - [match](#match) - [traversing](#traversing) - [sequence](#sequence) - [traverse](#traverse) - [traverseTap](#traversetap) - [type lambdas](#type-lambdas) - [EitherTypeLambda (interface)](#eithertypelambda-interface) - [utils](#utils) - [andThen](#andthen) - [ap](#ap) - [composeKleisliArrow](#composekleisliarrow) - [contains](#contains) - [exists](#exists) - [flatten](#flatten) - [reverse](#reverse) - [struct](#struct) - [tuple](#tuple) - [unit](#unit) --- # combinators ## tap Returns an effect that effectfully "peeks" at the success of this effect. **Signature** ```ts export declare const tap: { (self: Either, f: (a: A) => Either): Either (f: (a: A) => Either): (self: Either) => Either } ``` Added in v1.0.0 # combining ## all Similar to `Promise.all` but operates on `Either`s. ``` Iterable> -> Either ``` Flattens a collection of `Either`s into a single `Either` that contains a list of all the `Right` values. If there is a `Left` value in the collection, it returns the first `Left` found as the result. **Signature** ```ts export declare const all: (collection: Iterable>) => Either ``` **Example** ```ts import * as E from '@fp-ts/core/Either' assert.deepStrictEqual(E.all([E.right(1), E.right(2), E.right(3)]), E.right([1, 2, 3])) assert.deepStrictEqual(E.all([E.right(1), E.left('error'), E.right(3)]), E.left('error')) ``` Added in v1.0.0 ## andThenDiscard Sequences the specified effect after this effect, but ignores the value produced by the effect. **Signature** ```ts export declare const andThenDiscard: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } ``` Added in v1.0.0 ## flatMap **Signature** ```ts export declare const flatMap: { (f: (a: A) => Either): (self: Either) => Either (self: Either, f: (a: A) => Either): Either } ``` Added in v1.0.0 ## flatMapNullable **Signature** ```ts export declare const flatMapNullable: { (f: (a: A) => B | null | undefined, onNullable: (a: A) => E2): ( self: Either ) => Either> (self: Either, f: (a: A) => B | null | undefined, onNullable: (a: A) => E2): Either< E1 | E2, NonNullable > } ``` Added in v1.0.0 ## flatMapOption **Signature** ```ts export declare const flatMapOption: { (f: (a: A) => Option, onNone: (a: A) => E2): (self: Either) => Either (self: Either, f: (a: A) => Option, onNone: (a: A) => E2): Either } ``` Added in v1.0.0 ## getFirstLeftMonoid `Monoid` returning the left-most `Left` value. If both operands are `Right`s then the inner values are combined using the provided `Monoid`. - `combine` is provided by {@link getFirstLeftSemigroup}. - `empty` is `right(M.empty)` **Signature** ```ts export declare const getFirstLeftMonoid: (M: Monoid
) => Monoid> ``` Added in v1.0.0 ## getFirstLeftSemigroup `Semigroup` returning the left-most `Left` value. If both operands are `Right`s then the inner values are combined using the provided `Semigroup`. ``` | self | that | combine(self, that) | | ---------- | ---------- | ----------------------- | | left(e1) | left(e2) | left(e1) | | left(e1) | right(a2) | left(e1) | | right(a1) | left(e2) | left(e2) | | right(a1) | right(a2) | right(combine(a1, a2)) | ``` **Signature** ```ts export declare const getFirstLeftSemigroup: (S: Semigroup) => Semigroup> ``` Added in v1.0.0 ## getFirstRightSemigroup Semigroup returning the left-most `Right` value. ``` | self | that | combine(self, that) | | ---------- | ---------- | ------------------- | | left(e1) | left(e2) | left(e2) | | left(e1) | right(a2) | right(a2) | | right(a1) | left(e2) | right(a1) | | right(a1) | right(a2) | right(a1) | ``` **Signature** ```ts export declare const getFirstRightSemigroup: () => Semigroup> ``` Added in v1.0.0 ## zipWith **Signature** ```ts export declare const zipWith: { (self: Either, that: Either, f: (a: A, b: B) => C): Either (that: Either, f: (a: A, b: B) => C): (self: Either) => Either } ``` Added in v1.0.0 # constructors ## left Constructs a new `Either` holding a `Left` value. This usually represents a failure, due to the right-bias of this structure. **Signature** ```ts export declare const left: (e: E) => Either ``` Added in v1.0.0 ## of Alias of {@link right}. **Signature** ```ts export declare const of: (a: A) => Either ``` Added in v1.0.0 ## right Constructs a new `Either` holding a `Right` value. This usually represents a successful value due to the right bias of this structure. **Signature** ```ts export declare const right: (a: A) => Either ``` Added in v1.0.0 # conversions ## fromIterable **Signature** ```ts export declare const fromIterable: { (onEmpty: LazyArg): (collection: Iterable) => Either (collection: Iterable, onEmpty: LazyArg): Either } ``` Added in v1.0.0 ## fromOption **Signature** ```ts export declare const fromOption: { (fa: Option, onNone: () => E): Either (onNone: () => E): (fa: Option) => Either } ``` **Example** ```ts import * as E from '@fp-ts/core/Either' import * as O from '@fp-ts/core/Option' assert.deepStrictEqual( E.fromOption(O.some(1), () => 'error'), E.right(1) ) assert.deepStrictEqual( E.fromOption(O.none(), () => 'error'), E.left('error') ) ``` Added in v1.0.0 ## getLeft Converts a `Either` to an `Option` discarding the value. **Signature** ```ts export declare const getLeft: (self: Either) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' assert.deepStrictEqual(E.getLeft(E.right('ok')), O.none()) assert.deepStrictEqual(E.getLeft(E.left('err')), O.some('err')) ``` Added in v1.0.0 ## getRight Converts a `Either` to an `Option` discarding the error. Alias of {@link toOption}. **Signature** ```ts export declare const getRight: (self: Either) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' assert.deepStrictEqual(E.getRight(E.right('ok')), O.some('ok')) assert.deepStrictEqual(E.getRight(E.left('err')), O.none()) ``` Added in v1.0.0 ## toArray Transforms an `Either` into an `Array`. If the input is `Left`, an empty array is returned. If the input is `Right`, the value is wrapped in an array. **Signature** ```ts export declare const toArray: (self: Either) => A[] ``` **Example** ```ts import { right, left, toArray } from '@fp-ts/core/Either' assert.deepStrictEqual(toArray(right(1)), [1]) assert.deepStrictEqual(toArray(left('error')), []) ``` Added in v1.0.0 ## toOption Converts a `Either` to an `Option` discarding the error. **Signature** ```ts export declare const toOption: (self: Either) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' assert.deepStrictEqual(E.toOption(E.right(1)), O.some(1)) assert.deepStrictEqual(E.toOption(E.left('a')), O.none()) ``` Added in v1.0.0 ## toRefinement Returns a `Refinement` from a `Either` returning function. This function ensures that a `Refinement` definition is type-safe. **Signature** ```ts export declare const toRefinement: (f: (a: A) => Either) => Refinement ``` Added in v1.0.0 # debugging ## inspectLeft **Signature** ```ts export declare const inspectLeft: { (onLeft: (e: E) => void): (self: Either) => Either (self: Either, onLeft: (e: E) => void): Either } ``` Added in v1.0.0 ## inspectRight **Signature** ```ts export declare const inspectRight: { (onRight: (a: A) => void): (self: Either) => Either (self: Either, onRight: (a: A) => void): Either } ``` Added in v1.0.0 # do notation ## Do **Signature** ```ts export declare const Do: Either ``` Added in v1.0.0 ## andThenBind Extends the `Either` value with the value of another `Either` type. If both `Either` instances are `Left`, then the result will be the first `Left`. **Signature** ```ts export declare const andThenBind: { (name: Exclude, that: Either): ( self: Either ) => Either ( self: Either, name: Exclude, that: Either ): Either } ``` **Example** ```ts import * as E from '@fp-ts/core/Either' import { pipe } from '@fp-ts/core/Function' const result = pipe( E.Do, E.bind('a', () => E.left('e1')), E.andThenBind('b', E.left('e2')) ) assert.deepStrictEqual(result, E.left('e1')) ``` Added in v1.0.0 ## appendElement Appends an element to the end of a tuple. **Signature** ```ts export declare const appendElement: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } ``` Added in v1.0.0 ## bind **Signature** ```ts export declare const bind: { (name: Exclude, f: (a: A) => Either): ( self: Either ) => Either ( self: Either, name: Exclude, f: (a: A) => Either ): Either } ``` Added in v1.0.0 ## bindTo **Signature** ```ts export declare const bindTo: { (name: N): (self: Either) => Either (self: Either, name: N): Either } ``` Added in v1.0.0 ## let **Signature** ```ts export declare const let: { (name: Exclude, f: (a: A) => B): ( self: Either ) => Either (self: Either, name: Exclude, f: (a: A) => B): Either< E, { [K in N | keyof A]: K extends keyof A ? A[K] : B } > } ``` Added in v1.0.0 ## tupled **Signature** ```ts export declare const tupled: (self: Either) => Either ``` Added in v1.0.0 # equivalence ## getEquivalence **Signature** ```ts export declare const getEquivalence: (EE: Equivalence, EA: Equivalence) => Equivalence> ``` Added in v1.0.0 # error handling ## firstRightOf **Signature** ```ts export declare const firstRightOf: { (collection: Iterable>): (self: Either) => Either (self: Either, collection: Iterable>): Either } ``` Added in v1.0.0 ## mapLeft Maps the `Left` side of an `Either` value to a new `Either` value. **Signature** ```ts export declare const mapLeft: { (f: (e: E) => G): (self: Either) => Either (self: Either, f: (e: E) => G): Either } ``` Added in v1.0.0 ## orElse Executes this effect and returns its value, if it succeeds, but otherwise executes the specified effect. **Signature** ```ts export declare const orElse: { (that: (e1: E1) => Either): (self: Either) => Either (self: Either, that: (e1: E1) => Either): Either } ``` Added in v1.0.0 ## orElseEither Returns an effect that will produce the value of this effect, unless it fails, in which case, it will produce the value of the specified effect. **Signature** ```ts export declare const orElseEither: { (that: (e1: E1) => Either): (self: Either) => Either> (self: Either, that: (e1: E1) => Either): Either> } ``` Added in v1.0.0 ## orElseFail Executes this effect and returns its value, if it succeeds, but otherwise fails with the specified error. **Signature** ```ts export declare const orElseFail: { (onLeft: LazyArg): (self: Either) => Either (self: Either, onLeft: LazyArg): Either } ``` Added in v1.0.0 ## tapError Returns an effect that effectfully "peeks" at the failure of this effect. **Signature** ```ts export declare const tapError: { (onLeft: (e: E1) => Either): (self: Either) => Either (self: Either, onLeft: (e: E1) => Either): Either } ``` Added in v1.0.0 # filtering ## compact **Signature** ```ts export declare const compact: { (onNone: LazyArg): (self: Either>) => Either (self: Either>, onNone: LazyArg): Either } ``` Added in v1.0.0 ## filter **Signature** ```ts export declare const filter: { (refinement: Refinement, onFalse: LazyArg): ( self: Either ) => Either (predicate: Predicate, onFalse: LazyArg): ( self: Either ) => Either ( self: Either, refinement: Refinement, onFalse: LazyArg ): Either (self: Either, predicate: Predicate, onFalse: LazyArg): Either } ``` Added in v1.0.0 ## filterMap **Signature** ```ts export declare const filterMap: { (f: (a: A) => Option, onNone: LazyArg): (self: Either) => Either (self: Either, f: (a: A) => Option, onNone: LazyArg): Either } ``` Added in v1.0.0 # getters ## getOrElse Returns the wrapped value if it's a `Right` or a default value if is a `Left`. **Signature** ```ts export declare const getOrElse: { (onLeft: (e: E) => B): (self: Either) => B | A (self: Either, onLeft: (e: E) => B): A | B } ``` **Example** ```ts import * as E from '@fp-ts/core/Either' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual( E.getOrElse(E.right(1), () => 0), 1 ) assert.deepStrictEqual( E.getOrElse(E.left('error'), () => 0), 0 ) ``` Added in v1.0.0 ## getOrNull **Signature** ```ts export declare const getOrNull: (self: Either) => A | null ``` Added in v1.0.0 ## getOrUndefined **Signature** ```ts export declare const getOrUndefined: (self: Either) => A | undefined ``` Added in v1.0.0 ## lefts Return all the `Left` elements from an `Interable` of `Either`s. **Signature** ```ts export declare const lefts: (self: Iterable>) => E[] ``` Added in v1.0.0 ## rights Return all the `Right` elements from an `Interable` of `Either`s. **Signature** ```ts export declare const rights: (self: Iterable>) => A[] ``` Added in v1.0.0 # guards ## isEither Tests if a value is a `Either`. **Signature** ```ts export declare const isEither: (input: unknown) => input is Either ``` **Example** ```ts import { isEither, left, right } from '@fp-ts/core/Either' assert.deepStrictEqual(isEither(right(1)), true) assert.deepStrictEqual(isEither(left('error')), true) assert.deepStrictEqual(isEither({ right: 1 }), false) ``` Added in v1.0.0 ## isLeft Determine if a `Either` is a `Left`. **Signature** ```ts export declare const isLeft: (self: Either) => self is Left ``` **Example** ```ts import { isLeft, left, right } from '@fp-ts/core/Either' assert.deepStrictEqual(isLeft(right(1)), false) assert.deepStrictEqual(isLeft(left('error')), true) ``` Added in v1.0.0 ## isRight Determine if a `Either` is a `Right`. **Signature** ```ts export declare const isRight: (self: Either) => self is Right ``` **Example** ```ts import { isRight, left, right } from '@fp-ts/core/Either' assert.deepStrictEqual(isRight(right(1)), true) assert.deepStrictEqual(isRight(left('error')), false) ``` Added in v1.0.0 # instances ## Applicative **Signature** ```ts export declare const Applicative: applicative.Applicative ``` Added in v1.0.0 ## Bicovariant **Signature** ```ts export declare const Bicovariant: bicovariant.Bicovariant ``` Added in v1.0.0 ## Chainable **Signature** ```ts export declare const Chainable: chainable.Chainable ``` Added in v1.0.0 ## Covariant **Signature** ```ts export declare const Covariant: covariant.Covariant ``` Added in v1.0.0 ## FlatMap **Signature** ```ts export declare const FlatMap: flatMap_.FlatMap ``` Added in v1.0.0 ## Foldable **Signature** ```ts export declare const Foldable: foldable.Foldable ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Monad **Signature** ```ts export declare const Monad: monad.Monad ``` Added in v1.0.0 ## Of **Signature** ```ts export declare const Of: of_.Of ``` Added in v1.0.0 ## Pointed **Signature** ```ts export declare const Pointed: pointed.Pointed ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiAlternative **Signature** ```ts export declare const SemiAlternative: semiAlternative.SemiAlternative ``` Added in v1.0.0 ## SemiApplicative **Signature** ```ts export declare const SemiApplicative: semiApplicative.SemiApplicative ``` Added in v1.0.0 ## SemiCoproduct **Signature** ```ts export declare const SemiCoproduct: semiCoproduct.SemiCoproduct ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## Traversable **Signature** ```ts export declare const Traversable: traversable.Traversable ``` Added in v1.0.0 ## getOptionalSemigroup Semigroup that models the combination of values that may be absent, elements that are `Left` are ignored while elements that are `Right` are combined using the provided `Semigroup`. **Signature** ```ts export declare const getOptionalSemigroup: (S: Semigroup) => Semigroup> ``` Added in v1.0.0 # interop ## fromNullable Takes a lazy default and a nullable value, if the value is not nully, turn it into a `Right`, if the value is nully use the provided default as a `Left`. **Signature** ```ts export declare const fromNullable: { (onNullable: (a: A) => E): (a: A) => Either> (a: A, onNullable: (a: A) => E): Either> } ``` **Example** ```ts import * as E from '@fp-ts/core/Either' const parse = E.fromNullable(() => 'nullable') assert.deepStrictEqual(parse(1), E.right(1)) assert.deepStrictEqual(parse(null), E.left('nullable')) ``` Added in v1.0.0 ## getOrThrow Extracts the value of an `Either` or throws if the `Either` is `Left`. The thrown error is a default error. To configure the error thrown, see {@link getOrThrowWith}. **Signature** ```ts export declare const getOrThrow: (self: Either) => A ``` **Example** ```ts import * as E from '@fp-ts/core/Either' assert.deepStrictEqual(E.getOrThrow(E.right(1)), 1) assert.throws(() => E.getOrThrow(E.left('error'))) ``` Added in v1.0.0 ## getOrThrowWith Extracts the value of an `Either` or throws if the `Either` is `Left`. If a default error is sufficient for your use case and you don't need to configure the thrown error, see {@link getOrThrow}. **Signature** ```ts export declare const getOrThrowWith: { (onLeft: (e: E) => unknown): (self: Either) => A (self: Either, onLeft: (e: E) => unknown): A } ``` **Example** ```ts import * as E from '@fp-ts/core/Either' assert.deepStrictEqual( E.getOrThrowWith(E.right(1), () => new Error('Unexpected Left')), 1 ) assert.throws(() => E.getOrThrowWith(E.left('error'), () => new Error('Unexpected Left'))) ``` Added in v1.0.0 ## liftNullable **Signature** ```ts export declare const liftNullable: ( f: (...a: A) => B | null | undefined, onNullable: (...a: A) => E ) => (...a: A) => Either> ``` Added in v1.0.0 ## liftThrowable Lifts a function that may throw to one returning a `Either`. **Signature** ```ts export declare const liftThrowable: ( f: (...a: A) => B, onThrow: (error: unknown) => E ) => (...a: A) => Either ``` Added in v1.0.0 ## merge **Signature** ```ts export declare const merge: (self: Either) => E | A ``` Added in v1.0.0 # lifting ## lift2 Lifts a binary function into `Either`. **Signature** ```ts export declare const lift2: ( f: (a: A, b: B) => C ) => { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } ``` Added in v1.0.0 ## liftOption **Signature** ```ts export declare const liftOption: ( f: (...a: A) => Option, onNone: (...a: A) => E ) => (...a: A) => Either ``` Added in v1.0.0 ## liftPredicate **Signature** ```ts export declare const liftPredicate: { (refinement: Refinement, onFalse: (c: C) => E): (c: C) => Either (predicate: Predicate, onFalse: (b: B) => E): (b: B) => Either } ``` **Example** ```ts import { liftPredicate, left, right } from '@fp-ts/core/Either' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual( pipe( 1, liftPredicate( (n) => n > 0, () => 'error' ) ), right(1) ) assert.deepStrictEqual( pipe( -1, liftPredicate( (n) => n > 0, () => 'error' ) ), left('error') ) ``` Added in v1.0.0 # mapping ## as Maps the Right value of this effect to the specified constant value. **Signature** ```ts export declare const as: { (self: Either, b: B): Either (b: B): (self: Either) => Either } ``` Added in v1.0.0 ## asUnit Returns the effect Eithering from mapping the Right of this effect to unit. **Signature** ```ts export declare const asUnit: (self: Either) => Either ``` Added in v1.0.0 ## bimap **Signature** ```ts export declare const bimap: { (f: (e: E1) => E2, g: (a: A) => B): (self: Either) => Either (self: Either, f: (e: E1) => E2, g: (a: A) => B): Either } ``` Added in v1.0.0 ## flap **Signature** ```ts export declare const flap: { (a: A, self: Either B>): Either (self: Either B>): (a: A) => Either } ``` Added in v1.0.0 ## map Maps the `Right` side of an `Either` value to a new `Either` value. **Signature** ```ts export declare const map: { (f: (a: A) => B): (self: Either) => Either (self: Either, f: (a: A) => B): Either } ``` Added in v1.0.0 # math ## divide **Signature** ```ts export declare const divide: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } ``` Added in v1.0.0 ## multiply **Signature** ```ts export declare const multiply: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } ``` Added in v1.0.0 ## subtract **Signature** ```ts export declare const subtract: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } ``` Added in v1.0.0 ## sum **Signature** ```ts export declare const sum: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } ``` Added in v1.0.0 # models ## Either (type alias) **Signature** ```ts export type Either = Left | Right ``` Added in v1.0.0 ## Left (interface) **Signature** ```ts export interface Left { readonly _tag: 'Left' readonly left: E } ``` Added in v1.0.0 ## Right (interface) **Signature** ```ts export interface Right { readonly _tag: 'Right' readonly right: A } ``` Added in v1.0.0 # pattern matching ## match Takes two functions and an `Either` value, if the value is a `Left` the inner value is applied to the first function, if the value is a `Right` the inner value is applied to the second function. **Signature** ```ts export declare const match: { (onLeft: (e: E) => B, onRight: (a: A) => C): (self: Either) => B | C (self: Either, onLeft: (e: E) => B, onRight: (a: A) => C): B | C } ``` **Example** ```ts import * as E from '@fp-ts/core/Either' import { pipe } from '@fp-ts/core/Function' const onLeft = (errors: ReadonlyArray): string => `Errors: ${errors.join(', ')}` const onRight = (value: number): string => `Ok: ${value}` assert.deepStrictEqual(pipe(E.right(1), E.match(onLeft, onRight)), 'Ok: 1') assert.deepStrictEqual(pipe(E.left(['error 1', 'error 2']), E.match(onLeft, onRight)), 'Errors: error 1, error 2') ``` Added in v1.0.0 # traversing ## sequence **Signature** ```ts export declare const sequence: ( F: applicative.Applicative ) => (self: Either>) => Kind> ``` Added in v1.0.0 ## traverse **Signature** ```ts export declare const traverse: ( F: applicative.Applicative ) => { (f: (a: A) => Kind): (self: Either) => Kind> (self: Either, f: (a: A) => Kind): Kind> } ``` Added in v1.0.0 ## traverseTap **Signature** ```ts export declare const traverseTap: ( F: applicative.Applicative ) => { (self: Either, f: (a: A) => Kind): Kind> (f: (a: A) => Kind): (self: Either) => Kind> } ``` Added in v1.0.0 # type lambdas ## EitherTypeLambda (interface) **Signature** ```ts export interface EitherTypeLambda extends TypeLambda { readonly type: Either } ``` Added in v1.0.0 # utils ## andThen **Signature** ```ts export declare const andThen: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } ``` Added in v1.0.0 ## ap **Signature** ```ts export declare const ap: { (self: Either B>, that: Either): Either (that: Either): (self: Either B>) => Either } ``` Added in v1.0.0 ## composeKleisliArrow **Signature** ```ts export declare const composeKleisliArrow: { (afb: (a: A) => Either, bfc: (b: B) => Either): (a: A) => Either (bfc: (b: B) => Either): (afb: (a: A) => Either) => (a: A) => Either } ``` Added in v1.0.0 ## contains Returns a function that checks if an `Either` contains a given value using a provided `equivalence` function. **Signature** ```ts export declare const contains: (isEquivalent: (self: A, that: A) => boolean) => { (a: A): (self: Either) => boolean (self: Either, a: A): boolean } ``` Added in v1.0.0 ## exists Returns `false` if `Left` or returns the Either of the application of the given predicate to the `Right` value. **Signature** ```ts export declare const exists: { (predicate: Predicate): (self: Either) => boolean (self: Either, predicate: Predicate): boolean } ``` **Example** ```ts import * as E from '@fp-ts/core/Either' const f = E.exists((n: number) => n > 2) assert.deepStrictEqual(f(E.left('a')), false) assert.deepStrictEqual(f(E.right(1)), false) assert.deepStrictEqual(f(E.right(3)), true) ``` Added in v1.0.0 ## flatten **Signature** ```ts export declare const flatten: (self: Either>) => Either ``` Added in v1.0.0 ## reverse **Signature** ```ts export declare const reverse: (self: Either) => Either ``` Added in v1.0.0 ## struct **Signature** ```ts export declare const struct: >>( fields: R ) => Either< [R[keyof R]] extends [Either] ? E : never, { [K in keyof R]: [R[K]] extends [Either] ? A : never } > ``` Added in v1.0.0 ## tuple Similar to `Promise.all` but operates on `Either`s. ``` [Either, Either, ...] -> Either ``` **Signature** ```ts export declare const tuple: []>( ...elements: T ) => Either< [T[number]] extends [Either] ? E : never, { [I in keyof T]: [T[I]] extends [Either] ? A : never } > ``` Added in v1.0.0 ## unit **Signature** ```ts export declare const unit: Either ``` Added in v1.0.0 ================================================ FILE: docs/modules/Function.ts.md ================================================ --- title: Function.ts nav_order: 4 parent: Modules --- ## Function overview Added in v1.0.0 ---

Table of contents

- [guards](#guards) - [isFunction](#isfunction) - [type lambdas](#type-lambdas) - [FunctionTypeLambda (interface)](#functiontypelambda-interface) - [utils](#utils) - [FunctionN (interface)](#functionn-interface) - [LazyArg (interface)](#lazyarg-interface) - [SK](#sk) - [absurd](#absurd) - [apply](#apply) - [compose](#compose) - [constFalse](#constfalse) - [constNull](#constnull) - [constTrue](#consttrue) - [constUndefined](#constundefined) - [constVoid](#constvoid) - [constant](#constant) - [dual](#dual) - [flip](#flip) - [flow](#flow) - [hole](#hole) - [identity](#identity) - [pipe](#pipe) - [tupled](#tupled) - [unsafeCoerce](#unsafecoerce) - [untupled](#untupled) --- # guards ## isFunction Tests if a value is a `function`. **Signature** ```ts export declare const isFunction: (input: unknown) => input is Function ``` **Example** ```ts import { isFunction } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isFunction(isFunction), true) assert.deepStrictEqual(isFunction('function'), false) ``` Added in v1.0.0 # type lambdas ## FunctionTypeLambda (interface) **Signature** ```ts export interface FunctionTypeLambda extends TypeLambda { readonly type: (a: this['In']) => this['Target'] } ``` Added in v1.0.0 # utils ## FunctionN (interface) **Signature** ```ts export interface FunctionN
, B> { (...args: A): B } ``` **Example** ```ts import { FunctionN } from '@fp-ts/core/Function' export const sum: FunctionN<[number, number], number> = (a, b) => a + b ``` Added in v1.0.0 ## LazyArg (interface) A lazy argument. **Signature** ```ts export interface LazyArg { (): A } ``` **Example** ```ts import { LazyArg, constant } from '@fp-ts/core/Function' export const constNull: LazyArg = constant(null) ``` Added in v1.0.0 ## SK The SK combinator, also known as the "S-K combinator" or "S-combinator", is a fundamental combinator in the lambda calculus and the SKI combinator calculus. This function is useful for discarding the first argument passed to it and returning the second argument. **Signature** ```ts export declare const SK: (_: A, b: B) => B ``` **Example** ```ts import { SK } from '@fp-ts/core/Function' assert.deepStrictEqual(SK(0, 'hello'), 'hello') ``` Added in v1.0.0 ## absurd The `absurd` function is a stub for cases where a value of type `never` is encountered in your code, meaning that it should be impossible for this code to be executed. This function is particularly when it's necessary to specify that certain cases are impossible. **Signature** ```ts export declare const absurd: (_: never) => A ``` Added in v1.0.0 ## apply Apply a function to a given value. **Signature** ```ts export declare const apply: (a: A) => (self: (a: A) => B) => B ``` **Example** ```ts import { pipe, apply } from '@fp-ts/core/Function' import { length } from '@fp-ts/core/String' assert.deepStrictEqual(pipe(length, apply('hello')), 5) ``` Added in v1.0.0 ## compose Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`. The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`. **Signature** ```ts export declare const compose: { (bc: (b: B) => C): (self: (a: A) => B) => (a: A) => C (self: (a: A) => B, bc: (b: B) => C): (a: A) => C } ``` **Example** ```ts import { compose } from '@fp-ts/core/Function' const increment = (n: number) => n + 1 const square = (n: number) => n * n assert.strictEqual(compose(increment, square)(2), 9) ``` Added in v1.0.0 ## constFalse A thunk that returns always `false`. **Signature** ```ts export declare const constFalse: LazyArg ``` **Example** ```ts import { constFalse } from '@fp-ts/core/Function' assert.deepStrictEqual(constFalse(), false) ``` Added in v1.0.0 ## constNull A thunk that returns always `null`. **Signature** ```ts export declare const constNull: LazyArg ``` **Example** ```ts import { constNull } from '@fp-ts/core/Function' assert.deepStrictEqual(constNull(), null) ``` Added in v1.0.0 ## constTrue A thunk that returns always `true`. **Signature** ```ts export declare const constTrue: LazyArg ``` **Example** ```ts import { constTrue } from '@fp-ts/core/Function' assert.deepStrictEqual(constTrue(), true) ``` Added in v1.0.0 ## constUndefined A thunk that returns always `undefined`. **Signature** ```ts export declare const constUndefined: LazyArg ``` **Example** ```ts import { constUndefined } from '@fp-ts/core/Function' assert.deepStrictEqual(constUndefined(), undefined) ``` Added in v1.0.0 ## constVoid A thunk that returns always `void`. **Signature** ```ts export declare const constVoid: LazyArg ``` **Example** ```ts import { constVoid } from '@fp-ts/core/Function' assert.deepStrictEqual(constVoid(), undefined) ``` Added in v1.0.0 ## constant Creates a constant value that never changes. This is useful when you want to pass a value to a higher-order function (a function that takes another function as its argument) and want that inner function to always use the same value, no matter how many times it is called. **Signature** ```ts export declare const constant: (value: A) => LazyArg ``` **Example** ```ts import { constant } from '@fp-ts/core/Function' const constNull = constant(null) assert.deepStrictEqual(constNull(), null) assert.deepStrictEqual(constNull(), null) ``` Added in v1.0.0 ## dual Creates a function that can be used in a data-last (aka `pipe`able) or data-first style. **Signature** ```ts export declare const dual: < DataLast extends (...args: Array) => any, DataFirst extends (...args: Array) => any >( arity: Parameters['length'], body: DataFirst ) => DataLast & DataFirst ``` **Example** ```ts import { dual, pipe } from '@fp-ts/core/Function' export const sum: { (that: number): (self: number) => number (self: number, that: number): number } = dual(2, (self: number, that: number): number => self + that) assert.deepStrictEqual(sum(2, 3), 5) assert.deepStrictEqual(pipe(2, sum(3)), 5) ``` Added in v1.0.0 ## flip Reverses the order of arguments for a curried function. **Signature** ```ts export declare const flip: ( f: (...a: A) => (...b: B) => C ) => (...b: B) => (...a: A) => C ``` **Example** ```ts import { flip } from '@fp-ts/core/Function' const f = (a: number) => (b: string) => a - b.length assert.deepStrictEqual(flip(f)('aaa')(2), -1) ``` Added in v1.0.0 ## flow Performs left-to-right function composition. The first argument may have any arity, the remaining arguments must be unary. See also {@link pipe}. **Signature** ```ts export declare function flow, B>(ab: (...a: A) => B): (...a: A) => B export declare function flow, B, C>( ab: (...a: A) => B, bc: (b: B) => C ): (...a: A) => C export declare function flow, B, C, D>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D ): (...a: A) => D export declare function flow, B, C, D, E>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E ): (...a: A) => E export declare function flow, B, C, D, E, F>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F ): (...a: A) => F export declare function flow, B, C, D, E, F, G>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G ): (...a: A) => G export declare function flow, B, C, D, E, F, G, H>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H ): (...a: A) => H export declare function flow, B, C, D, E, F, G, H, I>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I ): (...a: A) => I export declare function flow, B, C, D, E, F, G, H, I, J>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J ): (...a: A) => J ``` **Example** ```ts import { flow } from '@fp-ts/core/Function' const len = (s: string): number => s.length const double = (n: number): number => n * 2 const f = flow(len, double) assert.deepStrictEqual(f('aaa'), 6) ``` Added in v1.0.0 ## hole Type hole simulation. **Signature** ```ts export declare const hole: () => T ``` Added in v1.0.0 ## identity The identity function, i.e. A function that returns its input argument. **Signature** ```ts export declare const identity: (a: A) => A ``` **Example** ```ts import { identity } from '@fp-ts/core/Function' assert.deepStrictEqual(identity(5), 5) ``` Added in v1.0.0 ## pipe Pipes the value of an expression into a pipeline of functions. This is useful in combination with data-last functions as a simulation of methods: ``` as.map(f).filter(g) -> pipe(as, map(f), filter(g)) ``` See also {@link flow}. **Signature** ```ts export declare function pipe(a: A): A export declare function pipe(a: A, ab: (a: A) => B): B export declare function pipe(a: A, ab: (a: A) => B, bc: (b: B) => C): C export declare function pipe(a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D export declare function pipe(a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E): E export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F ): F export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G ): G export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H ): H export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I ): I export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J ): J export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K ): K export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L ): L export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M ): M export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N ): N export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O ): O export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P ): P export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q ): Q export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R ): R export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S ): S export declare function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T ): T ``` **Example** ```ts import { pipe } from '@fp-ts/core/Function' const length = (s: string): number => s.length const double = (n: number): number => n * 2 const decrement = (n: number): number => n - 1 assert.deepStrictEqual(pipe(length('hello'), double, decrement), 9) ``` Added in v1.0.0 ## tupled Creates a tupled version of this function: instead of `n` arguments, it accepts a single tuple argument. **Signature** ```ts export declare const tupled: (f: (...a: A) => B) => (a: A) => B ``` **Example** ```ts import { tupled } from '@fp-ts/core/Function' const sumTupled = tupled((x: number, y: number): number => x + y) assert.deepStrictEqual(sumTupled([1, 2]), 3) ``` Added in v1.0.0 ## unsafeCoerce Casts the result to the specified type. **Signature** ```ts export declare const unsafeCoerce: (a: A) => B ``` **Example** ```ts import { unsafeCoerce, identity } from '@fp-ts/core/Function' assert.deepStrictEqual(unsafeCoerce, identity) ``` Added in v1.0.0 ## untupled Inverse function of `tupled` **Signature** ```ts export declare const untupled: (f: (a: A) => B) => (...a: A) => B ``` **Example** ```ts import { untupled } from '@fp-ts/core/Function' const getFirst = untupled((tuple: [A, B]): A => tuple[0]) assert.deepStrictEqual(getFirst(1, 2), 1) ``` Added in v1.0.0 ================================================ FILE: docs/modules/HKT.ts.md ================================================ --- title: HKT.ts nav_order: 5 parent: Modules --- ## HKT overview Added in v1.0.0 ---

Table of contents

- [utils](#utils) - [Kind (type alias)](#kind-type-alias) - [TypeClass (interface)](#typeclass-interface) - [TypeLambda (interface)](#typelambda-interface) --- # utils ## Kind (type alias) **Signature** ```ts export type Kind = F extends { readonly type: unknown } ? (F & { readonly In: In readonly Out2: Out2 readonly Out1: Out1 readonly Target: Target })['type'] : { readonly F: F readonly In: (_: In) => void readonly Out2: () => Out2 readonly Out1: () => Out1 readonly Target: (_: Target) => Target } ``` Added in v1.0.0 ## TypeClass (interface) **Signature** ```ts export interface TypeClass { readonly [URI]?: F } ``` Added in v1.0.0 ## TypeLambda (interface) **Signature** ```ts export interface TypeLambda { readonly In: unknown readonly Out2: unknown readonly Out1: unknown readonly Target: unknown } ``` Added in v1.0.0 ================================================ FILE: docs/modules/Identity.ts.md ================================================ --- title: Identity.ts nav_order: 6 parent: Modules --- ## Identity overview Added in v1.0.0 ---

Table of contents

- [do notation](#do-notation) - [Do](#do) - [andThenBind](#andthenbind) - [bind](#bind) - [bindTo](#bindto) - [let](#let) - [instances](#instances) - [Applicative](#applicative) - [Chainable](#chainable) - [Covariant](#covariant) - [FlatMap](#flatmap) - [Foldable](#foldable) - [Invariant](#invariant) - [Monad](#monad) - [Of](#of) - [Pointed](#pointed) - [Product](#product) - [SemiApplicative](#semiapplicative) - [SemiProduct](#semiproduct) - [Traversable](#traversable) - [getSemiAlternative](#getsemialternative) - [getSemiCoproduct](#getsemicoproduct) - [models](#models) - [Identity (type alias)](#identity-type-alias) - [type lambdas](#type-lambdas) - [IdentityTypeLambda (interface)](#identitytypelambda-interface) - [IdentityTypeLambdaFix (interface)](#identitytypelambdafix-interface) --- # do notation ## Do **Signature** ```ts export declare const Do: {} ``` Added in v1.0.0 ## andThenBind A variant of `bind` that sequentially ignores the scope. **Signature** ```ts export declare const andThenBind: { (name: Exclude, that: B): (self: A) => { [K in N | keyof A]: K extends keyof A ? A[K] : B }
(self: A, name: Exclude, that: B): { [K in N | keyof A]: K extends keyof A ? A[K] : B } } ``` Added in v1.0.0 ## bind **Signature** ```ts export declare const bind: { (name: Exclude, f: (a: A) => B): (self: A) => { [K in N | keyof A]: K extends keyof A ? A[K] : B } (self: A, name: Exclude, f: (a: A) => B): { [K in N | keyof A]: K extends keyof A ? A[K] : B } } ``` Added in v1.0.0 ## bindTo **Signature** ```ts export declare const bindTo: { (name: N): (self: A) => { [K in N]: A } (self: A, name: N): { [K in N]: A } } ``` Added in v1.0.0 ## let **Signature** ```ts export declare const let: { (name: Exclude, f: (a: A) => B): (self: A) => { [K in N | keyof A]: K extends keyof A ? A[K] : B } (self: A, name: Exclude, f: (a: A) => B): { [K in N | keyof A]: K extends keyof A ? A[K] : B } } ``` Added in v1.0.0 # instances ## Applicative **Signature** ```ts export declare const Applicative: applicative.Applicative ``` Added in v1.0.0 ## Chainable **Signature** ```ts export declare const Chainable: chainable.Chainable ``` Added in v1.0.0 ## Covariant **Signature** ```ts export declare const Covariant: covariant.Covariant ``` Added in v1.0.0 ## FlatMap **Signature** ```ts export declare const FlatMap: flatMap_.FlatMap ``` Added in v1.0.0 ## Foldable **Signature** ```ts export declare const Foldable: foldable.Foldable ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Monad **Signature** ```ts export declare const Monad: monad.Monad ``` Added in v1.0.0 ## Of **Signature** ```ts export declare const Of: of_.Of ``` Added in v1.0.0 ## Pointed **Signature** ```ts export declare const Pointed: pointed.Pointed ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiApplicative **Signature** ```ts export declare const SemiApplicative: semiApplicative.SemiApplicative ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## Traversable **Signature** ```ts export declare const Traversable: traversable.Traversable ``` Added in v1.0.0 ## getSemiAlternative **Signature** ```ts export declare const getSemiAlternative: ( S: Semigroup ) => semiAlternative.SemiAlternative> ``` Added in v1.0.0 ## getSemiCoproduct **Signature** ```ts export declare const getSemiCoproduct: (S: Semigroup) => semiCoproduct.SemiCoproduct> ``` Added in v1.0.0 # models ## Identity (type alias) **Signature** ```ts export type Identity = A ``` Added in v1.0.0 # type lambdas ## IdentityTypeLambda (interface) **Signature** ```ts export interface IdentityTypeLambda extends TypeLambda { readonly type: Identity } ``` Added in v1.0.0 ## IdentityTypeLambdaFix (interface) **Signature** ```ts export interface IdentityTypeLambdaFix extends TypeLambda { readonly type: Identity } ``` Added in v1.0.0 ================================================ FILE: docs/modules/Number.ts.md ================================================ --- title: Number.ts nav_order: 8 parent: Modules --- ## Number overview This module provides utility functions and type class instances for working with the `number` type in TypeScript. It includes functions for basic arithmetic operations, as well as type class instances for `Equivalence`, `Order`, `Semigroup`, and `Monoid`. Added in v1.0.0 ---

Table of contents

- [guards](#guards) - [isNumber](#isnumber) - [instances](#instances) - [Bounded](#bounded) - [Equivalence](#equivalence) - [MonoidMax](#monoidmax) - [MonoidMin](#monoidmin) - [MonoidMultiply](#monoidmultiply) - [MonoidSum](#monoidsum) - [Order](#order) - [SemigroupMax](#semigroupmax) - [SemigroupMin](#semigroupmin) - [SemigroupMultiply](#semigroupmultiply) - [SemigroupSum](#semigroupsum) - [math](#math) - [decrement](#decrement) - [divide](#divide) - [increment](#increment) - [multiply](#multiply) - [multiplyAll](#multiplyall) - [remainder](#remainder) - [sign](#sign) - [subtract](#subtract) - [sum](#sum) - [sumAll](#sumall) - [predicates](#predicates) - [between](#between) - [greaterThan](#greaterthan) - [greaterThanOrEqualTo](#greaterthanorequalto) - [lessThan](#lessthan) - [lessThanOrEqualTo](#lessthanorequalto) - [utils](#utils) - [clamp](#clamp) - [max](#max) - [min](#min) --- # guards ## isNumber Tests if a value is a `number`. **Signature** ```ts export declare const isNumber: (input: unknown) => input is number ``` **Example** ```ts import { isNumber } from '@fp-ts/core/Number' assert.deepStrictEqual(isNumber(2), true) assert.deepStrictEqual(isNumber('2'), false) ``` Added in v1.0.0 # instances ## Bounded **Signature** ```ts export declare const Bounded: bounded.Bounded ``` Added in v1.0.0 ## Equivalence **Signature** ```ts export declare const Equivalence: equivalence.Equivalence ``` Added in v1.0.0 ## MonoidMax A `Monoid` that uses the maximum between two values. The `empty` value is `Infinity`. **Signature** ```ts export declare const MonoidMax: monoid.Monoid ``` **Example** ```ts import { MonoidMax } from '@fp-ts/core/Number' assert.deepStrictEqual(MonoidMax.combine(2, 3), 3) assert.deepStrictEqual(MonoidMax.combine(2, MonoidMax.empty), 2) ``` Added in v1.0.0 ## MonoidMin A `Monoid` that uses the minimum between two values. The `empty` value is `-Infinity`. **Signature** ```ts export declare const MonoidMin: monoid.Monoid ``` **Example** ```ts import { MonoidMin } from '@fp-ts/core/Number' assert.deepStrictEqual(MonoidMin.combine(2, 3), 2) assert.deepStrictEqual(MonoidMin.combine(2, MonoidMin.empty), 2) ``` Added in v1.0.0 ## MonoidMultiply `number` monoid under multiplication. The `empty` value is `1`. **Signature** ```ts export declare const MonoidMultiply: monoid.Monoid ``` **Example** ```ts import { MonoidMultiply } from '@fp-ts/core/Number' assert.deepStrictEqual(MonoidMultiply.combine(2, 3), 6) assert.deepStrictEqual(MonoidMultiply.combine(2, MonoidMultiply.empty), 2) ``` Added in v1.0.0 ## MonoidSum `number` monoid under addition. The `empty` value is `0`. **Signature** ```ts export declare const MonoidSum: monoid.Monoid ``` **Example** ```ts import { MonoidSum } from '@fp-ts/core/Number' assert.deepStrictEqual(MonoidSum.combine(2, 3), 5) assert.deepStrictEqual(MonoidSum.combine(2, MonoidSum.empty), 2) ``` Added in v1.0.0 ## Order **Signature** ```ts export declare const Order: order.Order ``` Added in v1.0.0 ## SemigroupMax A `Semigroup` that uses the maximum between two values. **Signature** ```ts export declare const SemigroupMax: semigroup.Semigroup ``` **Example** ```ts import { SemigroupMax } from '@fp-ts/core/Number' assert.deepStrictEqual(SemigroupMax.combine(2, 3), 3) ``` Added in v1.0.0 ## SemigroupMin A `Semigroup` that uses the minimum between two values. **Signature** ```ts export declare const SemigroupMin: semigroup.Semigroup ``` **Example** ```ts import { SemigroupMin } from '@fp-ts/core/Number' assert.deepStrictEqual(SemigroupMin.combine(2, 3), 2) ``` Added in v1.0.0 ## SemigroupMultiply `number` semigroup under multiplication. **Signature** ```ts export declare const SemigroupMultiply: semigroup.Semigroup ``` **Example** ```ts import { SemigroupMultiply } from '@fp-ts/core/Number' assert.deepStrictEqual(SemigroupMultiply.combine(2, 3), 6) ``` Added in v1.0.0 ## SemigroupSum `number` semigroup under addition. **Signature** ```ts export declare const SemigroupSum: semigroup.Semigroup ``` **Example** ```ts import { SemigroupSum } from '@fp-ts/core/Number' assert.deepStrictEqual(SemigroupSum.combine(2, 3), 5) ``` Added in v1.0.0 # math ## decrement Decrements a number by `1`. **Signature** ```ts export declare const decrement: (n: number) => number ``` **Example** ```ts import { decrement } from '@fp-ts/core/Number' assert.deepStrictEqual(decrement(3), 2) ``` Added in v1.0.0 ## divide Provides a division operation on `number`s. **Signature** ```ts export declare const divide: { (that: number): (self: number) => number; (self: number, that: number): number } ``` **Example** ```ts import { divide } from '@fp-ts/core/Number' assert.deepStrictEqual(divide(6, 3), 2) ``` Added in v1.0.0 ## increment Returns the result of adding `1` to a given number. **Signature** ```ts export declare const increment: (n: number) => number ``` **Example** ```ts import { increment } from '@fp-ts/core/Number' assert.deepStrictEqual(increment(2), 3) ``` Added in v1.0.0 ## multiply Provides a multiplication operation on `number`s. **Signature** ```ts export declare const multiply: { (that: number): (self: number) => number; (self: number, that: number): number } ``` **Example** ```ts import { multiply } from '@fp-ts/core/Number' assert.deepStrictEqual(multiply(2, 3), 6) ``` Added in v1.0.0 ## multiplyAll Takes an `Iterable` of `number`s and returns their multiplication as a single `number`. **Signature** ```ts export declare const multiplyAll: (collection: Iterable) => number ``` **Example** ```ts import { multiplyAll } from '@fp-ts/core/Number' assert.deepStrictEqual(multiplyAll([2, 3, 4]), 24) ``` Added in v1.0.0 ## remainder Returns the remainder left over when one operand is divided by a second operand. It always takes the sign of the dividend. **Signature** ```ts export declare const remainder: { (divisor: number): (self: number) => number; (self: number, divisor: number): number } ``` **Example** ```ts import { remainder } from '@fp-ts/core/Number' assert.deepStrictEqual(remainder(2, 2), 0) assert.deepStrictEqual(remainder(3, 2), 1) assert.deepStrictEqual(remainder(-4, 2), -0) ``` Added in v1.0.0 ## sign Determines the sign of a given `number`. **Signature** ```ts export declare const sign: (n: number) => Ordering ``` **Example** ```ts import { sign } from '@fp-ts/core/Number' assert.deepStrictEqual(sign(-5), -1) assert.deepStrictEqual(sign(0), 0) assert.deepStrictEqual(sign(5), 1) ``` Added in v1.0.0 ## subtract Provides a subtraction operation on `number`s. **Signature** ```ts export declare const subtract: { (that: number): (self: number) => number; (self: number, that: number): number } ``` **Example** ```ts import { subtract } from '@fp-ts/core/Number' assert.deepStrictEqual(subtract(2, 3), -1) ``` Added in v1.0.0 ## sum Provides an addition operation on `number`s. **Signature** ```ts export declare const sum: { (that: number): (self: number) => number; (self: number, that: number): number } ``` **Example** ```ts import { sum } from '@fp-ts/core/Number' assert.deepStrictEqual(sum(2, 3), 5) ``` Added in v1.0.0 ## sumAll Takes an `Iterable` of `number`s and returns their sum as a single `number`. **Signature** ```ts export declare const sumAll: (collection: Iterable) => number ``` **Example** ```ts import { sumAll } from '@fp-ts/core/Number' assert.deepStrictEqual(sumAll([2, 3, 4]), 9) ``` Added in v1.0.0 # predicates ## between Checks if a `number` is between a `minimum` and `maximum` value (inclusive). **Signature** ```ts export declare const between: { (minimum: number, maximum: number): (self: number) => boolean (self: number, minimum: number, maximum: number): boolean } ``` **Example** ```ts import { between } from '@fp-ts/core/Number' assert.deepStrictEqual(between(0, 5)(3), true) assert.deepStrictEqual(between(0, 5)(-1), false) assert.deepStrictEqual(between(0, 5)(6), false) ``` Added in v1.0.0 ## greaterThan Returns `true` if the first argument is greater than the second, otherwise `false`. **Signature** ```ts export declare const greaterThan: { (that: number): (self: number) => boolean; (self: number, that: number): boolean } ``` **Example** ```ts import { greaterThan } from '@fp-ts/core/Number' assert.deepStrictEqual(greaterThan(2, 3), false) assert.deepStrictEqual(greaterThan(3, 3), false) assert.deepStrictEqual(greaterThan(4, 3), true) ``` Added in v1.0.0 ## greaterThanOrEqualTo Returns a function that checks if a given `number` is greater than or equal to the provided one. **Signature** ```ts export declare const greaterThanOrEqualTo: { (that: number): (self: number) => boolean (self: number, that: number): boolean } ``` **Example** ```ts import { greaterThanOrEqualTo } from '@fp-ts/core/Number' assert.deepStrictEqual(greaterThanOrEqualTo(2, 3), false) assert.deepStrictEqual(greaterThanOrEqualTo(3, 3), true) assert.deepStrictEqual(greaterThanOrEqualTo(4, 3), true) ``` Added in v1.0.0 ## lessThan Returns `true` if the first argument is less than the second, otherwise `false`. **Signature** ```ts export declare const lessThan: { (that: number): (self: number) => boolean; (self: number, that: number): boolean } ``` **Example** ```ts import { lessThan } from '@fp-ts/core/Number' assert.deepStrictEqual(lessThan(2, 3), true) assert.deepStrictEqual(lessThan(3, 3), false) assert.deepStrictEqual(lessThan(4, 3), false) ``` Added in v1.0.0 ## lessThanOrEqualTo Returns a function that checks if a given `number` is less than or equal to the provided one. **Signature** ```ts export declare const lessThanOrEqualTo: { (that: number): (self: number) => boolean (self: number, that: number): boolean } ``` **Example** ```ts import { lessThanOrEqualTo } from '@fp-ts/core/Number' assert.deepStrictEqual(lessThanOrEqualTo(2, 3), true) assert.deepStrictEqual(lessThanOrEqualTo(3, 3), true) assert.deepStrictEqual(lessThanOrEqualTo(4, 3), false) ``` Added in v1.0.0 # utils ## clamp Restricts the given `number` to be within the range specified by the `minimum` and `maximum` values. - If the `number` is less than the `minimum` value, the function returns the `minimum` value. - If the `number` is greater than the `maximum` value, the function returns the `maximum` value. - Otherwise, it returns the original `number`. **Signature** ```ts export declare const clamp: { (minimum: number, maximum: number): (self: number) => number (self: number, minimum: number, maximum: number): number } ``` **Example** ```ts import { clamp } from '@fp-ts/core/Number' assert.deepStrictEqual(clamp(0, 5)(3), 3) assert.deepStrictEqual(clamp(0, 5)(-1), 0) assert.deepStrictEqual(clamp(0, 5)(6), 5) ``` Added in v1.0.0 ## max Returns the maximum between two `number`s. **Signature** ```ts export declare const max: { (that: number): (self: number) => number; (self: number, that: number): number } ``` **Example** ```ts import { max } from '@fp-ts/core/Number' assert.deepStrictEqual(max(2, 3), 3) ``` Added in v1.0.0 ## min Returns the minimum between two `number`s. **Signature** ```ts export declare const min: { (that: number): (self: number) => number; (self: number, that: number): number } ``` **Example** ```ts import { min } from '@fp-ts/core/Number' assert.deepStrictEqual(min(2, 3), 2) ``` Added in v1.0.0 ================================================ FILE: docs/modules/Option.ts.md ================================================ --- title: Option.ts nav_order: 9 parent: Modules --- ## Option overview Added in v1.0.0 ---

Table of contents

- [combining](#combining) - [all](#all) - [ap](#ap) - [getFailureMonoid](#getfailuremonoid) - [getFailureSemigroup](#getfailuresemigroup) - [getFirstSomeSemigroup](#getfirstsomesemigroup) - [sequence](#sequence) - [struct](#struct) - [traverse](#traverse) - [traverseTap](#traversetap) - [tuple](#tuple) - [zipWith](#zipwith) - [constructors](#constructors) - [none](#none) - [of](#of) - [some](#some) - [conversions](#conversions) - [fromEither](#fromeither) - [fromIterable](#fromiterable) - [fromNullable](#fromnullable) - [getLeft](#getleft) - [getOrThrow](#getorthrow) - [getOrThrowWith](#getorthrowwith) - [getRight](#getright) - [liftNullable](#liftnullable) - [liftThrowable](#liftthrowable) - [toArray](#toarray) - [toEither](#toeither) - [toRefinement](#torefinement) - [debugging](#debugging) - [inspectNone](#inspectnone) - [inspectSome](#inspectsome) - [do notation](#do-notation) - [Do](#do) - [andThenBind](#andthenbind) - [appendElement](#appendelement) - [bind](#bind) - [bindTo](#bindto) - [let](#let) - [tupled](#tupled) - [equivalence](#equivalence) - [getEquivalence](#getequivalence) - [error handling](#error-handling) - [firstSomeOf](#firstsomeof) - [orElse](#orelse) - [orElseEither](#orelseeither) - [filtering](#filtering) - [filter](#filter) - [filterMap](#filtermap) - [partitionMap](#partitionmap) - [folding](#folding) - [reduceCompact](#reducecompact) - [getters](#getters) - [getOrElse](#getorelse) - [getOrNull](#getornull) - [getOrUndefined](#getorundefined) - [guards](#guards) - [isNone](#isnone) - [isOption](#isoption) - [isSome](#issome) - [lifting](#lifting) - [lift2](#lift2) - [liftEither](#lifteither) - [liftPredicate](#liftpredicate) - [math](#math) - [divide](#divide) - [multiply](#multiply) - [multiplyCompact](#multiplycompact) - [subtract](#subtract) - [sum](#sum) - [sumCompact](#sumcompact) - [models](#models) - [None (interface)](#none-interface) - [Option (type alias)](#option-type-alias) - [Some (interface)](#some-interface) - [pattern matching](#pattern-matching) - [match](#match) - [sorting](#sorting) - [getOrder](#getorder) - [transforming](#transforming) - [andThen](#andthen) - [andThenDiscard](#andthendiscard) - [as](#as) - [asUnit](#asunit) - [composeKleisliArrow](#composekleisliarrow) - [flap](#flap) - [flatMap](#flatmap) - [flatMapEither](#flatmapeither) - [flatMapNullable](#flatmapnullable) - [flatten](#flatten) - [map](#map) - [tap](#tap) - [type lambdas](#type-lambdas) - [OptionTypeLambda (interface)](#optiontypelambda-interface) - [utils](#utils) - [Alternative](#alternative) - [Applicative](#applicative) - [Chainable](#chainable) - [Coproduct](#coproduct) - [Covariant](#covariant) - [Filterable](#filterable) - [FlatMap](#flatmap) - [Foldable](#foldable) - [Invariant](#invariant) - [Monad](#monad) - [Of](#of) - [Pointed](#pointed) - [Product](#product) - [SemiAlternative](#semialternative) - [SemiApplicative](#semiapplicative) - [SemiCoproduct](#semicoproduct) - [SemiProduct](#semiproduct) - [Traversable](#traversable) - [contains](#contains) - [exists](#exists) - [getOptionalMonoid](#getoptionalmonoid) - [unit](#unit) --- # combining ## all Similar to `Promise.all` but operates on `Option`s. ``` Iterable> -> Option ``` Flattens a collection of `Option`s into a single `Option` that contains a list of all the `Some` values. If there is a `None` value in the collection, it returns `None` as the result. **Signature** ```ts export declare const all:
(collection: Iterable>) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.all([O.some(1), O.some(2), O.some(3)]), O.some([1, 2, 3])) assert.deepStrictEqual(O.all([O.some(1), O.none(), O.some(3)]), O.none()) ``` Added in v1.0.0 ## ap **Signature** ```ts export declare const ap: { (self: Option<(a: A) => B>, that: Option): Option (that: Option): (self: Option<(a: A) => B>) => Option } ``` Added in v1.0.0 ## getFailureMonoid Monoid that models the combination of computations that can fail, if at least one element is `None` then the resulting combination is `None`, otherwise if all elements are `Some` then the resulting combination is the combination of the wrapped elements using the provided `Monoid`. The `empty` value is `some(M.empty)`. See also `getFailureSemigroup` if you need a `Semigroup` instead of a `Monoid`. **Signature** ```ts export declare const getFailureMonoid: (M: Monoid) => Monoid> ``` Added in v1.0.0 ## getFailureSemigroup Semigroup that models the combination of computations that can fail, if at least one element is `None` then the resulting combination is `None`, otherwise if all elements are `Some` then the resulting combination is the combination of the wrapped elements using the provided `Semigroup`. See also `getFailureMonoid` if you need a `Monoid` instead of a `Semigroup`. **Signature** ```ts export declare const getFailureSemigroup: (S: Semigroup) => Semigroup> ``` Added in v1.0.0 ## getFirstSomeSemigroup Semigroup returning the first `Some` value encountered. **Signature** ```ts export declare const getFirstSomeSemigroup: () => Semigroup> ``` Added in v1.0.0 ## sequence Combines an `Option` of an `F`-structure to an `F`-structure of an `Option` with the same inner type. **Signature** ```ts export declare const sequence: ( F: applicative.Applicative ) => (self: Option>) => Kind> ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' const sequence = O.sequence(E.Applicative) assert.deepStrictEqual(sequence(O.some(E.right(1))), E.right(O.some(1))) assert.deepStrictEqual(sequence(O.some(E.left('error'))), E.left('error')) assert.deepStrictEqual(sequence(O.none()), E.right(O.none())) ``` Added in v1.0.0 ## struct Takes a struct of `Option`s and returns an `Option` of a struct of values. **Signature** ```ts export declare const struct: >>( fields: R ) => Option<{ [K in keyof R]: [R[K]] extends [Option] ? A : never }> ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.struct({ a: O.some(1), b: O.some('hello') }), O.some({ a: 1, b: 'hello' })) assert.deepStrictEqual(O.struct({ a: O.some(1), b: O.none() }), O.none()) ``` Added in v1.0.0 ## traverse Applies an `Option` value to an effectful function that returns an `F` value. **Signature** ```ts export declare const traverse: ( F: applicative.Applicative ) => { (f: (a: A) => Kind): (self: Option) => Kind> (self: Option, f: (a: A) => Kind): Kind> } ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' const traverse = O.traverse(E.Applicative) const f = (n: number) => (n >= 0 ? E.right(1) : E.left('negative')) assert.deepStrictEqual(traverse(O.some(1), f), E.right(O.some(1))) assert.deepStrictEqual(traverse(O.some(-1), f), E.left('negative')) assert.deepStrictEqual(traverse(O.none(), f), E.right(O.none())) ``` Added in v1.0.0 ## traverseTap **Signature** ```ts export declare const traverseTap: ( F: applicative.Applicative ) => { (self: Option, f: (a: A) => Kind): Kind> (f: (a: A) => Kind): (self: Option) => Kind> } ``` Added in v1.0.0 ## tuple Similar to `Promise.all` but operates on `Option`s. ``` [Option, Option, ...] -> Option<[A, B, ...]> ``` Takes a tuple of `Option`s and returns an `Option` of a tuple of values. **Signature** ```ts export declare const tuple: []>( ...elements: T ) => Option<{ [I in keyof T]: [T[I]] extends [Option] ? A : never }> ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.tuple(O.some(1), O.some('hello')), O.some([1, 'hello'])) assert.deepStrictEqual(O.tuple(O.some(1), O.none()), O.none()) ``` Added in v1.0.0 ## zipWith Zips two `Option` values together using a provided function, returning a new `Option` of the result. **Signature** ```ts export declare const zipWith: { (self: Option, that: Option, f: (a: A, b: B) => C): Option (that: Option, f: (a: A, b: B) => C): (self: Option) => Option } ``` Added in v1.0.0 # constructors ## none Creates a new `Option` that represents the absence of a value. **Signature** ```ts export declare const none: () => Option ``` Added in v1.0.0 ## of Alias of {@link some}. **Signature** ```ts export declare const of: (value: A) => Option ``` Added in v1.0.0 ## some Creates a new `Option` that wraps the given value. **Signature** ```ts export declare const some: (value: A) => Option ``` Added in v1.0.0 # conversions ## fromEither Converts a `Either` to an `Option` discarding the error. **Signature** ```ts export declare const fromEither: (self: Either) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' assert.deepStrictEqual(O.fromEither(E.right(1)), O.some(1)) assert.deepStrictEqual(O.fromEither(E.left('error message')), O.none()) ``` Added in v1.0.0 ## fromIterable Converts an `Iterable` of values into an `Option`. Returns the first value of the `Iterable` wrapped in a `Some` if the `Iterable` is not empty, otherwise returns `None`. **Signature** ```ts export declare const fromIterable: (collection: Iterable) => Option ``` **Example** ```ts import { fromIterable, some, none } from '@fp-ts/core/Option' assert.deepStrictEqual(fromIterable([1, 2, 3]), some(1)) assert.deepStrictEqual(fromIterable([]), none()) ``` Added in v1.0.0 ## fromNullable Constructs a new `Option` from a nullable type. If the value is `null` or `undefined`, returns `None`, otherwise returns the value wrapped in a `Some`. **Signature** ```ts export declare const fromNullable: (nullableValue: A) => Option> ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.fromNullable(undefined), O.none()) assert.deepStrictEqual(O.fromNullable(null), O.none()) assert.deepStrictEqual(O.fromNullable(1), O.some(1)) ``` Added in v1.0.0 ## getLeft Converts a `Either` to an `Option` discarding the value. **Signature** ```ts export declare const getLeft: (self: Either) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' assert.deepStrictEqual(O.getLeft(E.right('ok')), O.none()) assert.deepStrictEqual(O.getLeft(E.left('error')), O.some('error')) ``` Added in v1.0.0 ## getOrThrow Extracts the value of an `Option` or throws if the `Option` is `None`. The thrown error is a default error. To configure the error thrown, see {@link getOrThrowWith}. **Signature** ```ts export declare const getOrThrow: (self: Option) => A ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.getOrThrow(O.some(1)), 1) assert.throws(() => O.getOrThrow(O.none())) ``` Added in v1.0.0 ## getOrThrowWith Extracts the value of an `Option` or throws if the `Option` is `None`. If a default error is sufficient for your use case and you don't need to configure the thrown error, see {@link getOrThrow}. **Signature** ```ts export declare const getOrThrowWith: { (onNone: () => unknown): (self: Option) => A (self: Option, onNone: () => unknown): A } ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual( O.getOrThrowWith(O.some(1), () => new Error('Unexpected None')), 1 ) assert.throws(() => O.getOrThrowWith(O.none(), () => new Error('Unexpected None'))) ``` Added in v1.0.0 ## getRight Converts a `Either` to an `Option` discarding the error. Alias of {@link fromEither}. **Signature** ```ts export declare const getRight: (self: Either) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' assert.deepStrictEqual(O.getRight(E.right('ok')), O.some('ok')) assert.deepStrictEqual(O.getRight(E.left('err')), O.none()) ``` Added in v1.0.0 ## liftNullable This API is useful for lifting a function that returns `null` or `undefined` into the `Option` context. **Signature** ```ts export declare const liftNullable: ( f: (...a: A) => B | null | undefined ) => (...a: A) => Option> ``` **Example** ```ts import * as O from '@fp-ts/core/Option' const parse = (s: string): number | undefined => { const n = parseFloat(s) return isNaN(n) ? undefined : n } const parseOption = O.liftNullable(parse) assert.deepStrictEqual(parseOption('1'), O.some(1)) assert.deepStrictEqual(parseOption('not a number'), O.none()) ``` Added in v1.0.0 ## liftThrowable A utility function that lifts a function that throws exceptions into a function that returns an `Option`. This function is useful for any function that might throw an exception, allowing the developer to handle the exception in a more functional way. **Signature** ```ts export declare const liftThrowable: (f: (...a: A) => B) => (...a: A) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' const parse = O.liftThrowable(JSON.parse) assert.deepStrictEqual(parse('1'), O.some(1)) assert.deepStrictEqual(parse(''), O.none()) ``` Added in v1.0.0 ## toArray Transforms an `Option` into an `Array`. If the input is `None`, an empty array is returned. If the input is `Some`, the value is wrapped in an array. **Signature** ```ts export declare const toArray: (self: Option) => A[] ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.toArray(O.some(1)), [1]) assert.deepStrictEqual(O.toArray(O.none()), []) ``` Added in v1.0.0 ## toEither Converts an `Option` to an `Either`, allowing you to provide a value to be used in the case of a `None`. **Signature** ```ts export declare const toEither: { (self: Option, onNone: () => E): Either (onNone: () => E): (self: Option) => Either } ``` **Example** ```ts import { pipe } from '@fp-ts/core/Function' import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' const onNone = () => 'error' assert.deepStrictEqual(pipe(O.some(1), O.toEither(onNone)), E.right(1)) assert.deepStrictEqual(pipe(O.none(), O.toEither(onNone)), E.left('error')) ``` Added in v1.0.0 ## toRefinement Returns a type guard from a `Option` returning function. This function ensures that a type guard definition is type-safe. **Signature** ```ts export declare const toRefinement: (f: (a: A) => Option) => (a: A) => a is B ``` **Example** ```ts import * as O from '@fp-ts/core/Option' const parsePositive = (n: number): O.Option => (n > 0 ? O.some(n) : O.none()) const isPositive = O.toRefinement(parsePositive) assert.deepStrictEqual(isPositive(1), true) assert.deepStrictEqual(isPositive(-1), false) ``` Added in v1.0.0 # debugging ## inspectNone Useful for debugging purposes, the `onNone` callback is is called if `self` is a `None`. **Signature** ```ts export declare const inspectNone: { (onNone: () => void): (self: Option) => Option (self: Option, onNone: () => void): Option } ``` Added in v1.0.0 ## inspectSome Useful for debugging purposes, the `onSome` callback is called with the value of `self` if it is a `Some`. **Signature** ```ts export declare const inspectSome: { (onSome: (a: A) => void): (self: Option) => Option (self: Option, onSome: (a: A) => void): Option } ``` Added in v1.0.0 # do notation ## Do **Signature** ```ts export declare const Do: Option<{}> ``` Added in v1.0.0 ## andThenBind A variant of `bind` that sequentially ignores the scope. **Signature** ```ts export declare const andThenBind: { (name: Exclude, that: Option): ( self: Option ) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> (self: Option, name: Exclude, that: Option): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } ``` Added in v1.0.0 ## appendElement Appends an element to the end of a tuple wrapped in an `Option` type. **Signature** ```ts export declare const appendElement: { (self: Option, that: Option): Option<[...A, B]> (that: Option): (self: Option) => Option<[...A, B]> } ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.appendElement(O.some([1, 2]), O.some(3)), O.some([1, 2, 3])) assert.deepStrictEqual(O.appendElement(O.some([1, 2]), O.none()), O.none()) ``` Added in v1.0.0 ## bind **Signature** ```ts export declare const bind: { (name: Exclude, f: (a: A) => Option): ( self: Option ) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> (self: Option, name: Exclude, f: (a: A) => Option): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } ``` Added in v1.0.0 ## bindTo **Signature** ```ts export declare const bindTo: { (name: N): (self: Option) => Option<{ [K in N]: A }> (self: Option, name: N): Option<{ [K in N]: A }> } ``` Added in v1.0.0 ## let **Signature** ```ts export declare const let: { (name: Exclude, f: (a: A) => B): ( self: Option ) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> (self: Option, name: Exclude, f: (a: A) => B): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } ``` Added in v1.0.0 ## tupled **Signature** ```ts export declare const tupled: (self: Option) => Option<[A]> ``` Added in v1.0.0 # equivalence ## getEquivalence **Signature** ```ts export declare const getEquivalence: (E: Equivalence) => Equivalence> ``` **Example** ```ts import { none, some, getEquivalence } from '@fp-ts/core/Option' import * as N from '@fp-ts/core/Number' const isEquivalent = getEquivalence(N.Equivalence) assert.deepStrictEqual(isEquivalent(none(), none()), true) assert.deepStrictEqual(isEquivalent(none(), some(1)), false) assert.deepStrictEqual(isEquivalent(some(1), none()), false) assert.deepStrictEqual(isEquivalent(some(1), some(2)), false) assert.deepStrictEqual(isEquivalent(some(1), some(1)), true) ``` Added in v1.0.0 # error handling ## firstSomeOf Given an `Iterable` collection of `Option`s, returns the first `Some` found in the collection. **Signature** ```ts export declare const firstSomeOf: (collection: Iterable>) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.firstSomeOf([O.none(), O.some(1), O.some(2)]), O.some(1)) ``` Added in v1.0.0 ## orElse Returns the provided `Option` `that` if `self` is `None`, otherwise returns `self`. **Signature** ```ts export declare const orElse: { (that: LazyArg>): (self: Option) => Option (self: Option, that: LazyArg>): Option } ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual( pipe( O.none(), O.orElse(() => O.none()) ), O.none() ) assert.deepStrictEqual( pipe( O.some('a'), O.orElse(() => O.none()) ), O.some('a') ) assert.deepStrictEqual( pipe( O.none(), O.orElse(() => O.some('b')) ), O.some('b') ) assert.deepStrictEqual( pipe( O.some('a'), O.orElse(() => O.some('b')) ), O.some('a') ) ``` Added in v1.0.0 ## orElseEither Similar to `orElse`, but instead of returning a simple union, it returns an `Either` object, which contains information about which of the two `Option`s has been chosen. This is useful when it's important to know whether the value was retrieved from the first `Option` or the second option. **Signature** ```ts export declare const orElseEither: { (that: LazyArg>): (self: Option) => Option> (self: Option, that: LazyArg>): Option> } ``` Added in v1.0.0 # filtering ## filter Filters an `Option` using a predicate. If the predicate is not satisfied or the `Option` is `None` returns `None`. If you need to change the type of the `Option` in addition to filtering, see `filterMap`. **Signature** ```ts export declare const filter: { (self: Option, refinement: (a: A) => a is B): Option (self: Option, predicate: (a: A) => boolean): Option (refinement: (a: A) => a is B): (self: Option) => Option (predicate: (a: A) => boolean): (self: Option) => Option } ``` Added in v1.0.0 ## filterMap Maps over the value of an `Option` and filters out `None`s. Useful when in addition to filtering you also want to change the type of the `Option`. **Signature** ```ts export declare const filterMap: { (f: (a: A) => Option): (self: Option) => Option (self: Option, f: (a: A) => Option): Option } ``` Added in v1.0.0 ## partitionMap **Signature** ```ts export declare const partitionMap: { (f: (a: A) => Either): (self: Option) => [Option, Option] (self: Option, f: (a: A) => Either): [Option, Option] } ``` Added in v1.0.0 # folding ## reduceCompact Reduces an `Iterable` of `Option` to a single value of type `B`, elements that are `None` are ignored. **Signature** ```ts export declare const reduceCompact: { (b: B, f: (b: B, a: A) => B): (self: Iterable>) => B (self: Iterable>, b: B, f: (b: B, a: A) => B): B } ``` **Example** ```ts import { some, none, reduceCompact } from '@fp-ts/core/Option' import { pipe } from '@fp-ts/core/Function' const iterable = [some(1), none(), some(2), none()] assert.deepStrictEqual( pipe( iterable, reduceCompact(0, (b, a) => b + a) ), 3 ) ``` Added in v1.0.0 # getters ## getOrElse Returns the value of the `Option` if it is `Some`, otherwise returns `onNone` **Signature** ```ts export declare const getOrElse: { (onNone: LazyArg): (self: Option) => B | A (self: Option, onNone: LazyArg): A | B } ``` **Example** ```ts import { some, none, getOrElse } from '@fp-ts/core/Option' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual( pipe( some(1), getOrElse(() => 0) ), 1 ) assert.deepStrictEqual( pipe( none(), getOrElse(() => 0) ), 0 ) ``` Added in v1.0.0 ## getOrNull Returns the value of the `Option` if it is a `Some`, otherwise returns `null`. **Signature** ```ts export declare const getOrNull: (self: Option) => A | null ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.getOrNull(O.some(1)), 1) assert.deepStrictEqual(O.getOrNull(O.none()), null) ``` Added in v1.0.0 ## getOrUndefined Returns the value of the `Option` if it is a `Some`, otherwise returns `undefined`. **Signature** ```ts export declare const getOrUndefined: (self: Option) => A | undefined ``` **Example** ```ts import * as O from '@fp-ts/core/Option' assert.deepStrictEqual(O.getOrUndefined(O.some(1)), 1) assert.deepStrictEqual(O.getOrUndefined(O.none()), undefined) ``` Added in v1.0.0 # guards ## isNone Determine if a `Option` is a `None`. **Signature** ```ts export declare const isNone: (self: Option) => self is None ``` **Example** ```ts import { some, none, isNone } from '@fp-ts/core/Option' assert.deepStrictEqual(isNone(some(1)), false) assert.deepStrictEqual(isNone(none()), true) ``` Added in v1.0.0 ## isOption Tests if a value is a `Option`. **Signature** ```ts export declare const isOption: (input: unknown) => input is Option ``` **Example** ```ts import { some, none, isOption } from '@fp-ts/core/Option' assert.deepStrictEqual(isOption(some(1)), true) assert.deepStrictEqual(isOption(none()), true) assert.deepStrictEqual(isOption({}), false) ``` Added in v1.0.0 ## isSome Determine if a `Option` is a `Some`. **Signature** ```ts export declare const isSome: (self: Option) => self is Some ``` **Example** ```ts import { some, none, isSome } from '@fp-ts/core/Option' assert.deepStrictEqual(isSome(some(1)), true) assert.deepStrictEqual(isSome(none()), false) ``` Added in v1.0.0 # lifting ## lift2 Lifts a binary function into `Option`. **Signature** ```ts export declare const lift2: ( f: (a: A, b: B) => C ) => { (self: Option, that: Option): Option; (that: Option): (self: Option) => Option } ``` Added in v1.0.0 ## liftEither Lifts an `Either` function to an `Option` function. **Signature** ```ts export declare const liftEither: ( f: (...a: A) => Either ) => (...a: A) => Option ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' const parse = (s: string) => (isNaN(+s) ? E.left(`Error: ${s} is not a number`) : E.right(+s)) const parseNumber = O.liftEither(parse) assert.deepEqual(parseNumber('12'), O.some(12)) assert.deepEqual(parseNumber('not a number'), O.none()) ``` Added in v1.0.0 ## liftPredicate Transforms a `Predicate` function into a `Some` of the input value if the predicate returns `true` or `None` if the predicate returns `false`. **Signature** ```ts export declare const liftPredicate: { (refinement: Refinement): (c: C) => Option (predicate: Predicate): (b: B) => Option } ``` **Example** ```ts import * as O from '@fp-ts/core/Option' const getOption = O.liftPredicate((n: number) => n >= 0) assert.deepStrictEqual(getOption(-1), O.none()) assert.deepStrictEqual(getOption(1), O.some(1)) ``` Added in v1.0.0 # math ## divide **Signature** ```ts export declare const divide: { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } ``` Added in v1.0.0 ## multiply **Signature** ```ts export declare const multiply: { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } ``` Added in v1.0.0 ## multiplyCompact Multiply all numbers in an iterable of `Option` ignoring the `None` values. **Signature** ```ts export declare const multiplyCompact: (self: Iterable>) => number ``` **Example** ```ts import { multiplyCompact, some, none } from '@fp-ts/core/Option' const iterable = [some(2), none(), some(3), none()] assert.deepStrictEqual(multiplyCompact(iterable), 6) ``` Added in v1.0.0 ## subtract **Signature** ```ts export declare const subtract: { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } ``` Added in v1.0.0 ## sum **Signature** ```ts export declare const sum: { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } ``` Added in v1.0.0 ## sumCompact Sum all numbers in an iterable of `Option` ignoring the `None` values. **Signature** ```ts export declare const sumCompact: (self: Iterable>) => number ``` **Example** ```ts import { sumCompact, some, none } from '@fp-ts/core/Option' const iterable = [some(2), none(), some(3), none()] assert.deepStrictEqual(sumCompact(iterable), 5) ``` Added in v1.0.0 # models ## None (interface) **Signature** ```ts export interface None { readonly _tag: 'None' } ``` Added in v1.0.0 ## Option (type alias) **Signature** ```ts export type Option = None | Some ``` Added in v1.0.0 ## Some (interface) **Signature** ```ts export interface Some { readonly _tag: 'Some' readonly value: A } ``` Added in v1.0.0 # pattern matching ## match Matches the given `Option` and returns either the provided `onNone` value or the result of the provided `onSome` function when passed the `Option`'s value. **Signature** ```ts export declare const match: { (onNone: LazyArg, onSome: (a: A) => C): (self: Option) => B | C (self: Option, onNone: LazyArg, onSome: (a: A) => C): B | C } ``` **Example** ```ts import { some, none, match } from '@fp-ts/core/Option' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual( pipe( some(1), match( () => 'a none', (a) => `a some containing ${a}` ) ), 'a some containing 1' ) assert.deepStrictEqual( pipe( none(), match( () => 'a none', (a) => `a some containing ${a}` ) ), 'a none' ) ``` Added in v1.0.0 # sorting ## getOrder The `Order` instance allows `Option` values to be compared with `compare`, whenever there is an `Order` instance for the type the `Option` contains. `None` is considered to be less than any `Some` value. **Signature** ```ts export declare const getOrder: (O: Order) => Order> ``` **Example** ```ts import { none, some, getOrder } from '@fp-ts/core/Option' import * as N from '@fp-ts/core/Number' import { pipe } from '@fp-ts/core/Function' const O = getOrder(N.Order) assert.deepStrictEqual(O.compare(none(), none()), 0) assert.deepStrictEqual(O.compare(none(), some(1)), -1) assert.deepStrictEqual(O.compare(some(1), none()), 1) assert.deepStrictEqual(O.compare(some(1), some(2)), -1) assert.deepStrictEqual(O.compare(some(1), some(1)), 0) ``` Added in v1.0.0 # transforming ## andThen **Signature** ```ts export declare const andThen: { <_, B>(self: Option<_>, that: Option): Option (that: Option): <_>(self: Option<_>) => Option } ``` Added in v1.0.0 ## andThenDiscard Sequences the specified `that` `Option` but ignores its value. It is useful when we want to chain multiple operations, but only care about the result of `self`. **Signature** ```ts export declare const andThenDiscard: { (self: Option, that: Option<_>): Option <_>(that: Option<_>): (self: Option) => Option } ``` Added in v1.0.0 ## as Maps the `Some` value of this `Option` to the specified constant value. **Signature** ```ts export declare const as: { <_, B>(self: Option<_>, b: B): Option; (b: B): <_>(self: Option<_>) => Option } ``` Added in v1.0.0 ## asUnit Returns the `Option` resulting from mapping the `Some` value to `void`. This is useful when the value of the `Option` is not needed, but the presence or absence of the value is important. **Signature** ```ts export declare const asUnit: <_>(self: Option<_>) => Option ``` Added in v1.0.0 ## composeKleisliArrow **Signature** ```ts export declare const composeKleisliArrow: { (afb: (a: A) => Option, bfc: (b: B) => Option): (a: A) => Option (bfc: (b: B) => Option): (afb: (a: A) => Option) => (a: A) => Option } ``` Added in v1.0.0 ## flap **Signature** ```ts export declare const flap: { (a: A, self: Option<(a: A) => B>): Option (self: Option<(a: A) => B>): (a: A) => Option } ``` Added in v1.0.0 ## flatMap Applies a function to the value of an `Option` and flattens the result, if the input is `Some`. **Signature** ```ts export declare const flatMap: { (f: (a: A) => Option): (self: Option) => Option (self: Option, f: (a: A) => Option): Option } ``` Added in v1.0.0 ## flatMapEither Applies a provided function that returns an `Either` to the contents of an `Option`, flattening the result into another `Option`. **Signature** ```ts export declare const flatMapEither: { (f: (a: A) => Either): (self: Option) => Option (self: Option, f: (a: A) => Either): Option } ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as E from '@fp-ts/core/Either' import { pipe } from '@fp-ts/core/Function' const f = (n: number) => (n > 2 ? E.left('Too big') : E.right(n + 1)) assert.deepStrictEqual(pipe(O.some(1), O.flatMapEither(f)), O.some(2)) assert.deepStrictEqual(pipe(O.some(3), O.flatMapEither(f)), O.none()) ``` Added in v1.0.0 ## flatMapNullable This is `flatMap` + `fromNullable`, useful when working with optional values. **Signature** ```ts export declare const flatMapNullable: { (f: (a: A) => B | null | undefined): (self: Option) => Option> (self: Option, f: (a: A) => B | null | undefined): Option> } ``` **Example** ```ts import { some, none, flatMapNullable } from '@fp-ts/core/Option' import { pipe } from '@fp-ts/core/Function' interface Employee { company?: { address?: { street?: { name?: string } } } } const employee1: Employee = { company: { address: { street: { name: 'high street' } } } } assert.deepStrictEqual( pipe( some(employee1), flatMapNullable((employee) => employee.company?.address?.street?.name) ), some('high street') ) const employee2: Employee = { company: { address: { street: {} } } } assert.deepStrictEqual( pipe( some(employee2), flatMapNullable((employee) => employee.company?.address?.street?.name) ), none() ) ``` Added in v1.0.0 ## flatten **Signature** ```ts export declare const flatten: (self: Option>) => Option ``` Added in v1.0.0 ## map Maps the `Some` side of an `Option` value to a new `Option` value. **Signature** ```ts export declare const map: { (f: (a: A) => B): (self: Option) => Option (self: Option, f: (a: A) => B): Option } ``` Added in v1.0.0 ## tap Applies the provided function `f` to the value of the `Option` if it is `Some` and returns the original `Option` unless `f` returns `None`, in which case it returns `None`. This function is useful for performing additional computations on the value of the input `Option` without affecting its value. **Signature** ```ts export declare const tap: { (self: Option, f: (a: A) => Option<_>): Option (f: (a: A) => Option<_>): (self: Option) => Option } ``` Added in v1.0.0 # type lambdas ## OptionTypeLambda (interface) **Signature** ```ts export interface OptionTypeLambda extends TypeLambda { readonly type: Option } ``` Added in v1.0.0 # utils ## Alternative **Signature** ```ts export declare const Alternative: alternative.Alternative ``` Added in v1.0.0 ## Applicative **Signature** ```ts export declare const Applicative: applicative.Applicative ``` Added in v1.0.0 ## Chainable **Signature** ```ts export declare const Chainable: chainable.Chainable ``` Added in v1.0.0 ## Coproduct **Signature** ```ts export declare const Coproduct: coproduct_.Coproduct ``` Added in v1.0.0 ## Covariant **Signature** ```ts export declare const Covariant: covariant.Covariant ``` Added in v1.0.0 ## Filterable **Signature** ```ts export declare const Filterable: filterable.Filterable ``` Added in v1.0.0 ## FlatMap **Signature** ```ts export declare const FlatMap: flatMap_.FlatMap ``` Added in v1.0.0 ## Foldable **Signature** ```ts export declare const Foldable: foldable.Foldable ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Monad **Signature** ```ts export declare const Monad: monad.Monad ``` Added in v1.0.0 ## Of **Signature** ```ts export declare const Of: of_.Of ``` Added in v1.0.0 ## Pointed **Signature** ```ts export declare const Pointed: pointed.Pointed ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiAlternative **Signature** ```ts export declare const SemiAlternative: semiAlternative.SemiAlternative ``` Added in v1.0.0 ## SemiApplicative **Signature** ```ts export declare const SemiApplicative: semiApplicative.SemiApplicative ``` Added in v1.0.0 ## SemiCoproduct **Signature** ```ts export declare const SemiCoproduct: semiCoproduct.SemiCoproduct ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## Traversable **Signature** ```ts export declare const Traversable: traversable.Traversable ``` Added in v1.0.0 ## contains Returns a function that checks if an `Option` contains a given value using a provided `Equivalence` instance. **Signature** ```ts export declare const contains: (isEquivalent: (self: A, that: A) => boolean) => { (a: A): (self: Option) => boolean (self: Option, a: A): boolean } ``` **Example** ```ts import { some, none, contains } from '@fp-ts/core/Option' import { Equivalence } from '@fp-ts/core/Number' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual(pipe(some(2), contains(Equivalence)(2)), true) assert.deepStrictEqual(pipe(some(1), contains(Equivalence)(2)), false) assert.deepStrictEqual(pipe(none(), contains(Equivalence)(2)), false) ``` Added in v1.0.0 ## exists Check if a value in an `Option` type meets a certain predicate. **Signature** ```ts export declare const exists: { (predicate: Predicate): (self: Option) => boolean (self: Option, predicate: Predicate): boolean } ``` **Example** ```ts import { some, none, exists } from '@fp-ts/core/Option' import { pipe } from '@fp-ts/core/Function' const isEven = (n: number) => n % 2 === 0 assert.deepStrictEqual(pipe(some(2), exists(isEven)), true) assert.deepStrictEqual(pipe(some(1), exists(isEven)), false) assert.deepStrictEqual(pipe(none(), exists(isEven)), false) ``` Added in v1.0.0 ## getOptionalMonoid Monoid that models the combination of values that may be absent, elements that are `None` are ignored while elements that are `Some` are combined using the provided `Semigroup`. The `empty` value is `none()`. **Signature** ```ts export declare const getOptionalMonoid: (Semigroup: Semigroup) => Monoid> ``` **Example** ```ts import * as O from '@fp-ts/core/Option' import * as N from '@fp-ts/core/Number' import { pipe } from '@fp-ts/core/Function' const M = O.getOptionalMonoid(N.SemigroupSum) assert.deepStrictEqual(M.combine(O.none(), O.none()), O.none()) assert.deepStrictEqual(M.combine(O.some(1), O.none()), O.some(1)) assert.deepStrictEqual(M.combine(O.none(), O.some(1)), O.some(1)) assert.deepStrictEqual(M.combine(O.some(1), O.some(2)), O.some(3)) ``` Added in v1.0.0 ## unit **Signature** ```ts export declare const unit: Option ``` Added in v1.0.0 ================================================ FILE: docs/modules/Ordering.ts.md ================================================ --- title: Ordering.ts nav_order: 10 parent: Modules --- ## Ordering overview Added in v1.0.0 ---

Table of contents

- [instances](#instances) - [Monoid](#monoid) - [Semigroup](#semigroup) - [model](#model) - [Ordering (type alias)](#ordering-type-alias) - [pattern matching](#pattern-matching) - [match](#match) - [utils](#utils) - [reverse](#reverse) --- # instances ## Monoid `Monoid` instance for `Ordering`, returns the left-most non-zero `Ordering`. The `empty` value is `0`. **Signature** ```ts export declare const Monoid: monoid.Monoid<0 | 1 | -1> ``` **Example** ```ts import { Monoid } from '@fp-ts/core/Ordering' assert.deepStrictEqual(Monoid.combine(Monoid.empty, -1), -1) assert.deepStrictEqual(Monoid.combine(Monoid.empty, 1), 1) assert.deepStrictEqual(Monoid.combine(1, -1), 1) ``` Added in v1.0.0 ## Semigroup `Semigroup` instance for `Ordering`, returns the left-most non-zero `Ordering`. **Signature** ```ts export declare const Semigroup: semigroup.Semigroup<0 | 1 | -1> ``` **Example** ```ts import { Semigroup } from '@fp-ts/core/Ordering' assert.deepStrictEqual(Semigroup.combine(0, -1), -1) assert.deepStrictEqual(Semigroup.combine(0, 1), 1) assert.deepStrictEqual(Semigroup.combine(1, -1), 1) ``` Added in v1.0.0 # model ## Ordering (type alias) **Signature** ```ts export type Ordering = -1 | 0 | 1 ``` Added in v1.0.0 # pattern matching ## match Depending on the `Ordering` parameter given to it, returns a value produced by one of the 3 functions provided as parameters. **Signature** ```ts export declare const match: { (onLessThan: LazyArg
, onEqual: LazyArg, onGreaterThan: LazyArg): (self: Ordering) => A | B | C (o: Ordering, onLessThan: LazyArg, onEqual: LazyArg, onGreaterThan: LazyArg): A | B | C } ``` **Example** ```ts import { match } from '@fp-ts/core/Ordering' import { constant } from '@fp-ts/core/Function' const toMessage = match(constant('less than'), constant('equal'), constant('greater than')) assert.deepStrictEqual(toMessage(-1), 'less than') assert.deepStrictEqual(toMessage(0), 'equal') assert.deepStrictEqual(toMessage(1), 'greater than') ``` Added in v1.0.0 # utils ## reverse Inverts the ordering of the input `Ordering`. **Signature** ```ts export declare const reverse: (o: Ordering) => Ordering ``` **Example** ```ts import { reverse } from '@fp-ts/core/Ordering' assert.deepStrictEqual(reverse(1), -1) assert.deepStrictEqual(reverse(-1), 1) assert.deepStrictEqual(reverse(0), 0) ``` Added in v1.0.0 ================================================ FILE: docs/modules/Predicate.ts.md ================================================ --- title: Predicate.ts nav_order: 11 parent: Modules --- ## Predicate overview Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [and](#and) - [not](#not) - [or](#or) - [constructors](#constructors) - [contramap](#contramap) - [do notation](#do-notation) - [Do](#do) - [andThenBind](#andthenbind) - [bindTo](#bindto) - [guards](#guards) - [isBigint](#isbigint) - [isBoolean](#isboolean) - [isDate](#isdate) - [isError](#iserror) - [isFunction](#isfunction) - [isNever](#isnever) - [isNotNull](#isnotnull) - [isNotNullable](#isnotnullable) - [isNotUndefined](#isnotundefined) - [isNull](#isnull) - [isNullable](#isnullable) - [isNumber](#isnumber) - [isObject](#isobject) - [isReadonlyRecord](#isreadonlyrecord) - [isRecord](#isrecord) - [isString](#isstring) - [isSymbol](#issymbol) - [isUndefined](#isundefined) - [isUnknown](#isunknown) - [instances](#instances) - [Contravariant](#contravariant) - [Invariant](#invariant) - [Of](#of) - [Product](#product) - [SemiProduct](#semiproduct) - [getMonoidAll](#getmonoidall) - [getMonoidAny](#getmonoidany) - [getSemigroupAll](#getsemigroupall) - [getSemigroupAny](#getsemigroupany) - [models](#models) - [Predicate (interface)](#predicate-interface) - [Refinement (interface)](#refinement-interface) - [type lambdas](#type-lambdas) - [PredicateTypeLambda (interface)](#predicatetypelambda-interface) - [utils](#utils) - [all](#all) - [any](#any) - [appendElement](#appendelement) - [compose](#compose) - [of](#of) - [struct](#struct) - [tuple](#tuple) - [tupled](#tupled) - [unit](#unit) --- # combinators ## and Combines two predicates into a new predicate that returns `true` if both of the predicates returns `true`. **Signature** ```ts export declare const and: {
(that: Predicate): (self: Predicate) => Predicate (self: Predicate, that: Predicate): Predicate } ``` **Example** ```ts import * as P from '@fp-ts/core/Predicate' const minLength = (n: number) => (s: string) => s.length >= n const maxLength = (n: number) => (s: string) => s.length <= n const length = (n: number) => P.and(minLength(n), maxLength(n)) assert.deepStrictEqual(length(2)('aa'), true) assert.deepStrictEqual(length(2)('a'), false) assert.deepStrictEqual(length(2)('aaa'), false) ``` Added in v1.0.0 ## not Negates the result of a given predicate. **Signature** ```ts export declare const not: (self: Predicate) => Predicate ``` **Example** ```ts import * as P from '@fp-ts/core/Predicate' import * as N from '@fp-ts/core/Number' const isPositive = P.not(N.lessThan(0)) assert.deepStrictEqual(isPositive(-1), false) assert.deepStrictEqual(isPositive(0), true) assert.deepStrictEqual(isPositive(1), true) ``` Added in v1.0.0 ## or Combines two predicates into a new predicate that returns `true` if at least one of the predicates returns `true`. **Signature** ```ts export declare const or: { (that: Predicate): (self: Predicate) => Predicate (self: Predicate, that: Predicate): Predicate } ``` **Example** ```ts import * as P from '@fp-ts/core/Predicate' import * as N from '@fp-ts/core/Number' const nonZero = P.or(N.lessThan(0), N.greaterThan(0)) assert.deepStrictEqual(nonZero(-1), true) assert.deepStrictEqual(nonZero(0), false) assert.deepStrictEqual(nonZero(1), true) ``` Added in v1.0.0 # constructors ## contramap Given a `Predicate` returns a `Predicate` **Signature** ```ts export declare const contramap: { (f: (b: B) => A): (self: Predicate) => Predicate (self: Predicate, f: (b: B) => A): Predicate } ``` **Example** ```ts import * as P from '@fp-ts/core/Predicate' import * as N from '@fp-ts/core/Number' const minLength3 = P.contramap(N.greaterThan(2), (s: string) => s.length) assert.deepStrictEqual(minLength3('a'), false) assert.deepStrictEqual(minLength3('aa'), false) assert.deepStrictEqual(minLength3('aaa'), true) assert.deepStrictEqual(minLength3('aaaa'), true) ``` Added in v1.0.0 # do notation ## Do **Signature** ```ts export declare const Do: Predicate<{}> ``` Added in v1.0.0 ## andThenBind A variant of `bind` that sequentially ignores the scope. **Signature** ```ts export declare const andThenBind: { (name: Exclude, that: Predicate): ( self: Predicate ) => Predicate<{ readonly [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: Predicate, name: Exclude, that: Predicate ): Predicate<{ readonly [K in N | keyof A]: K extends keyof A ? A[K] : B }> } ``` Added in v1.0.0 ## bindTo **Signature** ```ts export declare const bindTo: { (name: N): (self: Predicate) => Predicate<{ readonly [K in N]: A }> (self: Predicate, name: N): Predicate<{ readonly [K in N]: A }> } ``` Added in v1.0.0 # guards ## isBigint Tests if a value is a `bigint`. **Signature** ```ts export declare const isBigint: (input: unknown) => input is bigint ``` **Example** ```ts import { isBigint } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isBigint(1n), true) assert.deepStrictEqual(isBigint(1), false) ``` Added in v1.0.0 ## isBoolean Tests if a value is a `boolean`. **Signature** ```ts export declare const isBoolean: (input: unknown) => input is boolean ``` **Example** ```ts import { isBoolean } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isBoolean(true), true) assert.deepStrictEqual(isBoolean('true'), false) ``` Added in v1.0.0 ## isDate A guard that succeeds when the input is a `Date`. **Signature** ```ts export declare const isDate: (input: unknown) => input is Date ``` **Example** ```ts import { isDate } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isDate(new Date()), true) assert.deepStrictEqual(isDate(null), false) assert.deepStrictEqual(isDate({}), false) ``` Added in v1.0.0 ## isError A guard that succeeds when the input is an `Error`. **Signature** ```ts export declare const isError: (input: unknown) => input is Error ``` **Example** ```ts import { isError } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isError(new Error()), true) assert.deepStrictEqual(isError(null), false) assert.deepStrictEqual(isError({}), false) ``` Added in v1.0.0 ## isFunction Tests if a value is a `function`. **Signature** ```ts export declare const isFunction: (input: unknown) => input is Function ``` **Example** ```ts import { isFunction } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isFunction(isFunction), true) assert.deepStrictEqual(isFunction('function'), false) ``` Added in v1.0.0 ## isNever A guard that always fails. **Signature** ```ts export declare const isNever: (input: unknown) => input is never ``` **Example** ```ts import { isNever } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isNever(null), false) assert.deepStrictEqual(isNever(undefined), false) assert.deepStrictEqual(isNever({}), false) assert.deepStrictEqual(isNever([]), false) ``` Added in v1.0.0 ## isNotNull Tests if a value is not `undefined`. **Signature** ```ts export declare const isNotNull: (input: A) => input is Exclude ``` **Example** ```ts import { isNotNull } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isNotNull(undefined), true) assert.deepStrictEqual(isNotNull('null'), true) assert.deepStrictEqual(isNotNull(null), false) ``` Added in v1.0.0 ## isNotNullable A guard that succeeds when the input is not `null` or `undefined`. **Signature** ```ts export declare const isNotNullable: (input: A) => input is NonNullable ``` **Example** ```ts import { isNotNullable } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isNotNullable({}), true) assert.deepStrictEqual(isNotNullable([]), true) assert.deepStrictEqual(isNotNullable(null), false) assert.deepStrictEqual(isNotNullable(undefined), false) ``` Added in v1.0.0 ## isNotUndefined Tests if a value is not `undefined`. **Signature** ```ts export declare const isNotUndefined: (input: A) => input is Exclude ``` **Example** ```ts import { isNotUndefined } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isNotUndefined(null), true) assert.deepStrictEqual(isNotUndefined('undefined'), true) assert.deepStrictEqual(isNotUndefined(undefined), false) ``` Added in v1.0.0 ## isNull Tests if a value is `undefined`. **Signature** ```ts export declare const isNull: (input: unknown) => input is null ``` **Example** ```ts import { isNull } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isNull(null), true) assert.deepStrictEqual(isNull(undefined), false) assert.deepStrictEqual(isNull('null'), false) ``` Added in v1.0.0 ## isNullable A guard that succeeds when the input is `null` or `undefined`. **Signature** ```ts export declare const isNullable: (input: A) => input is Extract ``` **Example** ```ts import { isNullable } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isNullable(null), true) assert.deepStrictEqual(isNullable(undefined), true) assert.deepStrictEqual(isNullable({}), false) assert.deepStrictEqual(isNullable([]), false) ``` Added in v1.0.0 ## isNumber Tests if a value is a `number`. **Signature** ```ts export declare const isNumber: (input: unknown) => input is number ``` **Example** ```ts import { isNumber } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isNumber(2), true) assert.deepStrictEqual(isNumber('2'), false) ``` Added in v1.0.0 ## isObject Tests if a value is an `object`. **Signature** ```ts export declare const isObject: (input: unknown) => input is object ``` **Example** ```ts import { isObject } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isObject({}), true) assert.deepStrictEqual(isObject([]), true) assert.deepStrictEqual(isObject(null), false) assert.deepStrictEqual(isObject(undefined), false) ``` Added in v1.0.0 ## isReadonlyRecord A guard that succeeds when the input is a readonly record. **Signature** ```ts export declare const isReadonlyRecord: (input: unknown) => input is {} ``` **Example** ```ts import { isReadonlyRecord } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isReadonlyRecord({}), true) assert.deepStrictEqual(isReadonlyRecord({ a: 1 }), true) assert.deepStrictEqual(isReadonlyRecord([]), false) assert.deepStrictEqual(isReadonlyRecord([1, 2, 3]), false) assert.deepStrictEqual(isReadonlyRecord(null), false) assert.deepStrictEqual(isReadonlyRecord(undefined), false) ``` Added in v1.0.0 ## isRecord A guard that succeeds when the input is a record. **Signature** ```ts export declare const isRecord: (input: unknown) => input is {} ``` **Example** ```ts import { isRecord } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isRecord({}), true) assert.deepStrictEqual(isRecord({ a: 1 }), true) assert.deepStrictEqual(isRecord([]), false) assert.deepStrictEqual(isRecord([1, 2, 3]), false) assert.deepStrictEqual(isRecord(null), false) assert.deepStrictEqual(isRecord(undefined), false) ``` Added in v1.0.0 ## isString Tests if a value is a `string`. **Signature** ```ts export declare const isString: (input: unknown) => input is string ``` **Example** ```ts import { isString } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isString('a'), true) assert.deepStrictEqual(isString(1), false) ``` Added in v1.0.0 ## isSymbol Tests if a value is a `symbol`. **Signature** ```ts export declare const isSymbol: (input: unknown) => input is symbol ``` **Example** ```ts import { isSymbol } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isSymbol(Symbol.for('a')), true) assert.deepStrictEqual(isSymbol('a'), false) ``` Added in v1.0.0 ## isUndefined Tests if a value is `undefined`. **Signature** ```ts export declare const isUndefined: (input: unknown) => input is undefined ``` **Example** ```ts import { isUndefined } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isUndefined(undefined), true) assert.deepStrictEqual(isUndefined(null), false) assert.deepStrictEqual(isUndefined('undefined'), false) ``` Added in v1.0.0 ## isUnknown A guard that always succeeds. **Signature** ```ts export declare const isUnknown: (input: unknown) => input is unknown ``` **Example** ```ts import { isUnknown } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isUnknown(null), true) assert.deepStrictEqual(isUnknown(undefined), true) assert.deepStrictEqual(isUnknown({}), true) assert.deepStrictEqual(isUnknown([]), true) ``` Added in v1.0.0 # instances ## Contravariant **Signature** ```ts export declare const Contravariant: contravariant.Contravariant ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Of **Signature** ```ts export declare const Of: of_.Of ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## getMonoidAll **Signature** ```ts export declare const getMonoidAll: () => monoid.Monoid> ``` Added in v1.0.0 ## getMonoidAny **Signature** ```ts export declare const getMonoidAny: () => monoid.Monoid> ``` Added in v1.0.0 ## getSemigroupAll **Signature** ```ts export declare const getSemigroupAll: () => semigroup.Semigroup> ``` Added in v1.0.0 ## getSemigroupAny **Signature** ```ts export declare const getSemigroupAny: () => semigroup.Semigroup> ``` Added in v1.0.0 # models ## Predicate (interface) **Signature** ```ts export interface Predicate { (a: A): boolean } ``` Added in v1.0.0 ## Refinement (interface) **Signature** ```ts export interface Refinement { (a: A): a is B } ``` Added in v1.0.0 # type lambdas ## PredicateTypeLambda (interface) **Signature** ```ts export interface PredicateTypeLambda extends TypeLambda { readonly type: Predicate } ``` Added in v1.0.0 # utils ## all **Signature** ```ts export declare const all: (collection: Iterable>) => Predicate ``` Added in v1.0.0 ## any **Signature** ```ts export declare const any: (collection: Iterable>) => Predicate ``` Added in v1.0.0 ## appendElement This function appends a predicate to a tuple-like predicate, allowing you to create a new predicate that includes the original elements and the new one. **Signature** ```ts export declare const appendElement: { (self: Predicate, that: Predicate): Predicate (that: Predicate): (self: Predicate) => Predicate } ``` Added in v1.0.0 ## compose **Signature** ```ts export declare const compose: { (bc: Refinement): (ab: Refinement) => Refinement (ab: Refinement, bc: Refinement): Refinement } ``` Added in v1.0.0 ## of **Signature** ```ts export declare const of: (_: A) => Predicate ``` Added in v1.0.0 ## struct **Signature** ```ts export declare const struct: >>( predicates: R ) => Predicate<{ readonly [K in keyof R]: [R[K]] extends [Predicate] ? A : never }> ``` Added in v1.0.0 ## tuple Similar to `Promise.all` but operates on `Predicate`s. ``` [Predicate, Predicate, ...] -> Predicate<[A, B, ...]> ``` **Signature** ```ts export declare const tuple: []>( ...predicates: T ) => Predicate] ? A : never }>> ``` Added in v1.0.0 ## tupled **Signature** ```ts export declare const tupled: (self: Predicate) => Predicate ``` Added in v1.0.0 ## unit **Signature** ```ts export declare const unit: Predicate ``` Added in v1.0.0 ================================================ FILE: docs/modules/ReadonlyArray.ts.md ================================================ --- title: ReadonlyArray.ts nav_order: 12 parent: Modules --- ## ReadonlyArray overview This module provides utility functions for working with arrays in TypeScript. Added in v1.0.0 ---

Table of contents

- [combining](#combining) - [flatMap](#flatmap) - [flatMapNonEmpty](#flatmapnonempty) - [flatMapNullable](#flatmapnullable) - [flatten](#flatten) - [flattenNonEmpty](#flattennonempty) - [constructors](#constructors) - [empty](#empty) - [make](#make) - [makeBy](#makeby) - [of](#of) - [range](#range) - [replicate](#replicate) - [unfold](#unfold) - [conversions](#conversions) - [fromEither](#fromeither) - [fromIterable](#fromiterable) - [fromNullable](#fromnullable) - [fromOption](#fromoption) - [do notation](#do-notation) - [Do](#do) - [andThenBind](#andthenbind) - [bind](#bind) - [bindTo](#bindto) - [let](#let) - [filtering](#filtering) - [compact](#compact) - [filter](#filter) - [filterMap](#filtermap) - [partition](#partition) - [partitionMap](#partitionmap) - [separate](#separate) - [span](#span) - [traverseFilterMap](#traversefiltermap) - [traversePartitionMap](#traversepartitionmap) - [folding](#folding) - [combineMap](#combinemap) - [combineMapNonEmpty](#combinemapnonempty) - [coproductMapKind](#coproductmapkind) - [reduce](#reduce) - [reduceKind](#reducekind) - [reduceRight](#reduceright) - [scan](#scan) - [scanRight](#scanright) - [getters](#getters) - [chunksOf](#chunksof) - [chunksOfNonEmpty](#chunksofnonempty) - [drop](#drop) - [dropRight](#dropright) - [dropWhile](#dropwhile) - [findFirst](#findfirst) - [findFirstIndex](#findfirstindex) - [findLast](#findlast) - [findLastIndex](#findlastindex) - [get](#get) - [head](#head) - [headNonEmpty](#headnonempty) - [init](#init) - [initNonEmpty](#initnonempty) - [last](#last) - [lastNonEmpty](#lastnonempty) - [lefts](#lefts) - [length](#length) - [rights](#rights) - [splitAt](#splitat) - [splitNonEmptyAt](#splitnonemptyat) - [tail](#tail) - [tailNonEmpty](#tailnonempty) - [take](#take) - [takeRight](#takeright) - [takeWhile](#takewhile) - [unappend](#unappend) - [unprepend](#unprepend) - [grouping](#grouping) - [group](#group) - [groupBy](#groupby) - [guards](#guards) - [isEmpty](#isempty) - [isEmptyArray](#isemptyarray) - [isNonEmpty](#isnonempty) - [isNonEmptyArray](#isnonemptyarray) - [instances](#instances) - [Applicative](#applicative) - [Chainable](#chainable) - [Covariant](#covariant) - [Filterable](#filterable) - [FlatMap](#flatmap) - [Foldable](#foldable) - [Invariant](#invariant) - [Monad](#monad) - [Of](#of) - [Pointed](#pointed) - [Product](#product) - [SemiApplicative](#semiapplicative) - [SemiProduct](#semiproduct) - [Traversable](#traversable) - [TraversableFilterable](#traversablefilterable) - [getIntersectionSemigroup](#getintersectionsemigroup) - [getMonoid](#getmonoid) - [getSemigroup](#getsemigroup) - [getUnionMonoid](#getunionmonoid) - [getUnionSemigroup](#getunionsemigroup) - [lifting](#lifting) - [getOrder](#getorder) - [lift2](#lift2) - [liftEither](#lifteither) - [liftMonoid](#liftmonoid) - [liftNullable](#liftnullable) - [liftOption](#liftoption) - [liftPredicate](#liftpredicate) - [mapping](#mapping) - [as](#as) - [flap](#flap) - [map](#map) - [mapNonEmpty](#mapnonempty) - [tupled](#tupled) - [models](#models) - [NonEmptyArray (type alias)](#nonemptyarray-type-alias) - [NonEmptyReadonlyArray (type alias)](#nonemptyreadonlyarray-type-alias) - [pattern matching](#pattern-matching) - [match](#match) - [matchLeft](#matchleft) - [matchRight](#matchright) - [predicates](#predicates) - [contains](#contains) - [every](#every) - [some](#some) - [sorting](#sorting) - [sort](#sort) - [sortBy](#sortby) - [sortByNonEmpty](#sortbynonempty) - [sortNonEmpty](#sortnonempty) - [traversing](#traversing) - [sequence](#sequence) - [sequenceNonEmpty](#sequencenonempty) - [traverse](#traverse) - [traverseNonEmpty](#traversenonempty) - [traverseTap](#traversetap) - [type lambdas](#type-lambdas) - [ReadonlyArrayTypeLambda (interface)](#readonlyarraytypelambda-interface) - [unsafe](#unsafe) - [unsafeGet](#unsafeget) - [utils](#utils) - [ap](#ap) - [append](#append) - [appendAll](#appendall) - [appendAllNonEmpty](#appendallnonempty) - [chop](#chop) - [chopNonEmpty](#chopnonempty) - [composeKleisliArrow](#composekleisliarrow) - [copy](#copy) - [difference](#difference) - [extend](#extend) - [insertAt](#insertat) - [intercalate](#intercalate) - [intercalateNonEmpty](#intercalatenonempty) - [intersection](#intersection) - [intersperse](#intersperse) - [intersperseNonEmpty](#interspersenonempty) - [join](#join) - [max](#max) - [min](#min) - [modify](#modify) - [modifyNonEmptyHead](#modifynonemptyhead) - [modifyNonEmptyLast](#modifynonemptylast) - [modifyOption](#modifyoption) - [prepend](#prepend) - [prependAll](#prependall) - [prependAllNonEmpty](#prependallnonempty) - [remove](#remove) - [replace](#replace) - [replaceOption](#replaceoption) - [reverse](#reverse) - [reverseNonEmpty](#reversenonempty) - [rotate](#rotate) - [rotateNonEmpty](#rotatenonempty) - [setNonEmptyHead](#setnonemptyhead) - [setNonEmptyLast](#setnonemptylast) - [traverseFilter](#traversefilter) - [traversePartition](#traversepartition) - [union](#union) - [unionNonEmpty](#unionnonempty) - [uniq](#uniq) - [uniqNonEmpty](#uniqnonempty) - [unzip](#unzip) - [unzipNonEmpty](#unzipnonempty) - [zip](#zip) - [zipNonEmpty](#zipnonempty) - [zipNonEmptyWith](#zipnonemptywith) - [zipWith](#zipwith) --- # combining ## flatMap **Signature** ```ts export declare const flatMap: { (f: (a: A, i: number) => readonly B[]): (self: readonly A[]) => B[] (self: readonly A[], f: (a: A, i: number) => readonly B[]): B[] } ``` Added in v1.0.0 ## flatMapNonEmpty **Signature** ```ts export declare const flatMapNonEmpty: { (f: (a: A, i: number) => readonly [B, ...B[]]): (self: readonly [A, ...A[]]) => [B, ...B[]] (self: readonly [A, ...A[]], f: (a: A, i: number) => readonly [B, ...B[]]): [B, ...B[]] } ``` Added in v1.0.0 ## flatMapNullable **Signature** ```ts export declare const flatMapNullable: { (f: (a: A) => B | null | undefined): (self: readonly A[]) => NonNullable[] (self: readonly A[], f: (a: A) => B | null | undefined): NonNullable[] } ``` Added in v1.0.0 ## flatten **Signature** ```ts export declare const flatten:
(self: readonly (readonly A[])[]) => A[] ``` Added in v1.0.0 ## flattenNonEmpty **Signature** ```ts export declare const flattenNonEmpty: ( self: readonly [readonly [A, ...A[]], ...(readonly [A, ...A[]])[]] ) => [A, ...A[]] ``` Added in v1.0.0 # constructors ## empty **Signature** ```ts export declare const empty: () => A[] ``` Added in v1.0.0 ## make Builds a `NonEmptyArray` from an non-empty collection of elements. **Signature** ```ts export declare const make: ( ...elements: Elements ) => [Elements[number], ...Elements[number][]] ``` Added in v1.0.0 ## makeBy Return a `NonEmptyArray` of length `n` with element `i` initialized with `f(i)`. **Note**. `n` is normalized to an integer >= 1. **Signature** ```ts export declare const makeBy: (n: number, f: (i: number) => A) => [A, ...A[]] ``` **Example** ```ts import { makeBy } from '@fp-ts/core/ReadonlyArray' assert.deepStrictEqual( makeBy(5, (n) => n * 2), [0, 2, 4, 6, 8] ) ``` Added in v1.0.0 ## of **Signature** ```ts export declare const of: (a: A) => [A, ...A[]] ``` Added in v1.0.0 ## range Return a `NonEmptyArray` containing a range of integers, including both endpoints. **Signature** ```ts export declare const range: (start: number, end: number) => [number, ...number[]] ``` **Example** ```ts import { range } from '@fp-ts/core/ReadonlyArray' assert.deepStrictEqual(range(1, 3), [1, 2, 3]) ``` Added in v1.0.0 ## replicate Return a `NonEmptyArray` containing a value repeated the specified number of times. **Note**. `n` is normalized to an integer >= 1. **Signature** ```ts export declare const replicate: { (n: number): (a: A) => [A, ...A[]]; (a: A, n: number): [A, ...A[]] } ``` **Example** ```ts import { replicate } from '@fp-ts/core/ReadonlyArray' assert.deepStrictEqual(replicate('a', 3), ['a', 'a', 'a']) ``` Added in v1.0.0 ## unfold **Signature** ```ts export declare const unfold: (b: B, f: (b: B) => Option) => A[] ``` Added in v1.0.0 # conversions ## fromEither **Signature** ```ts export declare const fromEither: (self: Either) => A[] ``` Added in v1.0.0 ## fromIterable **Signature** ```ts export declare const fromIterable: (collection: Iterable) => A[] ``` Added in v1.0.0 ## fromNullable **Signature** ```ts export declare const fromNullable: (a: A) => NonNullable[] ``` Added in v1.0.0 ## fromOption **Signature** ```ts export declare const fromOption: (self: Option) => A[] ``` Added in v1.0.0 # do notation ## Do **Signature** ```ts export declare const Do: readonly {}[] ``` Added in v1.0.0 ## andThenBind A variant of `bind` that sequentially ignores the scope. **Signature** ```ts export declare const andThenBind: { (name: Exclude, that: readonly B[]): ( self: readonly A[] ) => { [K in N | keyof A]: K extends keyof A ? A[K] : B }[] (self: readonly A[], name: Exclude, that: readonly B[]): { [K in N | keyof A]: K extends keyof A ? A[K] : B }[] } ``` Added in v1.0.0 ## bind **Signature** ```ts export declare const bind: { (name: Exclude, f: (a: A) => readonly B[]): ( self: readonly A[] ) => { [K in N | keyof A]: K extends keyof A ? A[K] : B }[] (self: readonly A[], name: Exclude, f: (a: A) => readonly B[]): { [K in N | keyof A]: K extends keyof A ? A[K] : B }[] } ``` Added in v1.0.0 ## bindTo **Signature** ```ts export declare const bindTo: { (name: N): (self: readonly A[]) => { [K in N]: A }[] (self: readonly A[], name: N): { [K in N]: A }[] } ``` Added in v1.0.0 ## let **Signature** ```ts export declare const let: { (name: Exclude, f: (a: A) => B): ( self: readonly A[] ) => { [K in N | keyof A]: K extends keyof A ? A[K] : B }[] (self: readonly A[], name: Exclude, f: (a: A) => B): { [K in N | keyof A]: K extends keyof A ? A[K] : B }[] } ``` Added in v1.0.0 # filtering ## compact **Signature** ```ts export declare const compact: (self: Iterable>) => A[] ``` Added in v1.0.0 ## filter **Signature** ```ts export declare const filter: { (refinement: (a: A, i: number) => a is B): (self: Iterable) => B[] (predicate: (a: A, i: number) => boolean): (self: Iterable) => B[] (self: Iterable, refinement: (a: A, i: number) => a is B): B[] (self: Iterable, predicate: (a: A, i: number) => boolean): B[] } ``` Added in v1.0.0 ## filterMap **Signature** ```ts export declare const filterMap: { (f: (a: A, i: number) => Option): (self: Iterable) => B[] (self: Iterable, f: (a: A, i: number) => Option): B[] } ``` Added in v1.0.0 ## partition **Signature** ```ts export declare const partition: { (refinement: (a: A, i: number) => a is B): (self: Iterable) => [C[], B[]] (predicate: (a: A, i: number) => boolean): (self: Iterable) => [B[], B[]] (self: Iterable, refinement: (a: A, i: number) => a is B): [C[], B[]] (self: Iterable, predicate: (a: A, i: number) => boolean): [B[], B[]] } ``` Added in v1.0.0 ## partitionMap **Signature** ```ts export declare const partitionMap: { (f: (a: A, i: number) => Either): (self: Iterable) => [B[], C[]] (self: Iterable, f: (a: A, i: number) => Either): [B[], C[]] } ``` Added in v1.0.0 ## separate **Signature** ```ts export declare const separate: (self: Iterable>) => [A[], B[]] ``` Added in v1.0.0 ## span Split an `Iterable` into two parts: 1. the longest initial subarray for which all elements satisfy the specified predicate 2. the remaining elements **Signature** ```ts export declare const span: { (refinement: Refinement): (self: Iterable) => [init: B[], rest: A[]] (predicate: Predicate): (self: Iterable) => [init: B[], rest: B[]] (self: Iterable, refinement: Refinement): [init: B[], rest: A[]] (self: Iterable, predicate: Predicate): [init: B[], rest: B[]] } ``` Added in v1.0.0 ## traverseFilterMap **Signature** ```ts export declare const traverseFilterMap: ( F: applicative.Applicative ) => { (f: (a: A) => Kind>): (self: readonly A[]) => Kind (self: readonly A[], f: (a: A) => Kind>): Kind } ``` Added in v1.0.0 ## traversePartitionMap **Signature** ```ts export declare const traversePartitionMap: ( F: applicative.Applicative ) => { (f: (a: A) => Kind>): (self: readonly A[]) => Kind (self: readonly A[], f: (a: A) => Kind>): Kind } ``` Added in v1.0.0 # folding ## combineMap **Signature** ```ts export declare const combineMap: (Monoid: Monoid) => { (f: (a: A, i: number) => M): (self: Iterable) => M (self: Iterable, f: (a: A, i: number) => M): M } ``` Added in v1.0.0 ## combineMapNonEmpty **Signature** ```ts export declare const combineMapNonEmpty: (S: Semigroup) => { (f: (a: A, i: number) => S): (self: readonly [A, ...A[]]) => S (self: readonly [A, ...A[]], f: (a: A, i: number) => S): S } ``` Added in v1.0.0 ## coproductMapKind **Signature** ```ts export declare const coproductMapKind: ( G: Coproduct ) => { (f: (a: A) => Kind): (self: readonly A[]) => Kind (self: readonly A[], f: (a: A) => Kind): Kind } ``` Added in v1.0.0 ## reduce **Signature** ```ts export declare const reduce: { (b: B, f: (b: B, a: A, i: number) => B): (self: Iterable) => B (self: Iterable, b: B, f: (b: B, a: A, i: number) => B): B } ``` Added in v1.0.0 ## reduceKind **Signature** ```ts export declare const reduceKind: ( G: monad.Monad ) => { (b: B, f: (b: B, a: A) => Kind): (self: readonly A[]) => Kind (self: readonly A[], b: B, f: (b: B, a: A) => Kind): Kind } ``` Added in v1.0.0 ## reduceRight **Signature** ```ts export declare const reduceRight: { (b: B, f: (b: B, a: A, i: number) => B): (self: Iterable) => B (self: Iterable, b: B, f: (b: B, a: A, i: number) => B): B } ``` Added in v1.0.0 ## scan Reduce an `Iterable` from the left, keeping all intermediate results instead of only the final result. **Signature** ```ts export declare const scan: { (b: B, f: (b: B, a: A) => B): (self: Iterable) => [B, ...B[]] (self: Iterable, b: B, f: (b: B, a: A) => B): [B, ...B[]] } ``` Added in v1.0.0 ## scanRight Reduce an `Iterable` from the right, keeping all intermediate results instead of only the final result. **Signature** ```ts export declare const scanRight: { (b: B, f: (b: B, a: A) => B): (self: Iterable) => [B, ...B[]] (self: Iterable, b: B, f: (b: B, a: A) => B): [B, ...B[]] } ``` Added in v1.0.0 # getters ## chunksOf Splits an `Iterable` into length-`n` pieces. The last piece will be shorter if `n` does not evenly divide the length of the `Iterable`. Note that `chunksOf(n)([])` is `[]`, not `[[]]`. This is intentional, and is consistent with a recursive definition of `chunksOf`; it satisfies the property that ```ts chunksOf(n)(xs).concat(chunksOf(n)(ys)) == chunksOf(n)(xs.concat(ys))) ``` whenever `n` evenly divides the length of `self`. **Signature** ```ts export declare const chunksOf: { (n: number): (self: Iterable) => [A, ...A[]][] (self: Iterable, n: number): [A, ...A[]][] } ``` Added in v1.0.0 ## chunksOfNonEmpty Splits a `NonEmptyReadonlyArray` into length-`n` pieces. The last piece will be shorter if `n` does not evenly divide the length of the `NonEmptyReadonlyArray`. **Signature** ```ts export declare const chunksOfNonEmpty: { (n: number): (self: readonly [A, ...A[]]) => [[A, ...A[]], ...[A, ...A[]][]] (self: readonly [A, ...A[]], n: number): [[A, ...A[]], ...[A, ...A[]][]] } ``` Added in v1.0.0 ## drop Drop a max number of elements from the start of an `Iterable`, creating a new `Array`. **Note**. `n` is normalized to a non negative integer. **Signature** ```ts export declare const drop: { (n: number): (self: Iterable) => A[]; (self: Iterable, n: number): A[] } ``` Added in v1.0.0 ## dropRight Drop a max number of elements from the end of an `Iterable`, creating a new `Array`. **Note**. `n` is normalized to a non negative integer. **Signature** ```ts export declare const dropRight: { (n: number): (self: Iterable) => A[]; (self: Iterable, n: number): A[] } ``` Added in v1.0.0 ## dropWhile Remove the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`. **Signature** ```ts export declare const dropWhile: { (refinement: Refinement): (self: Iterable) => B[] (predicate: Predicate): (self: Iterable) => B[] (self: Iterable, refinement: Refinement): B[] (self: Iterable, predicate: Predicate): B[] } ``` Added in v1.0.0 ## findFirst Find the first element for which a predicate holds. **Signature** ```ts export declare const findFirst: { (refinement: Refinement): (self: Iterable) => Option (predicate: Predicate): (self: Iterable) => Option (self: Iterable, refinement: Refinement): Option (self: Iterable, predicate: Predicate): Option } ``` Added in v1.0.0 ## findFirstIndex Return the first index for which a predicate holds. **Signature** ```ts export declare const findFirstIndex: { (predicate: Predicate): (self: Iterable) => Option (self: Iterable, predicate: Predicate): Option } ``` Added in v1.0.0 ## findLast Find the last element for which a predicate holds. **Signature** ```ts export declare const findLast: { (refinement: Refinement): (self: Iterable) => Option (predicate: Predicate): (self: Iterable) => Option (self: Iterable, refinement: Refinement): Option (self: Iterable, predicate: Predicate): Option } ``` Added in v1.0.0 ## findLastIndex Return the last index for which a predicate holds. **Signature** ```ts export declare const findLastIndex: { (predicate: Predicate): (self: Iterable) => Option (self: Iterable, predicate: Predicate): Option } ``` Added in v1.0.0 ## get This function provides a safe way to read a value at a particular index from a `ReadonlyArray`. **Signature** ```ts export declare const get: { (index: number): (self: readonly A[]) => Option (self: readonly A[], index: number): Option } ``` Added in v1.0.0 ## head Get the first element of a `ReadonlyArray`, or `None` if the `ReadonlyArray` is empty. **Signature** ```ts export declare const head: (self: readonly A[]) => Option ``` Added in v1.0.0 ## headNonEmpty **Signature** ```ts export declare const headNonEmpty: (self: readonly [A, ...A[]]) => A ``` Added in v1.0.0 ## init Get all but the last element of an `Iterable`, creating a new `Array`, or `None` if the `Iterable` is empty. **Signature** ```ts export declare const init: (self: Iterable) => Option ``` Added in v1.0.0 ## initNonEmpty Get all but the last element of a non empty array, creating a new array. **Signature** ```ts export declare const initNonEmpty: (self: readonly [A, ...A[]]) => A[] ``` Added in v1.0.0 ## last Get the last element in a `ReadonlyArray`, or `None` if the `ReadonlyArray` is empty. **Signature** ```ts export declare const last: (self: readonly A[]) => Option ``` Added in v1.0.0 ## lastNonEmpty **Signature** ```ts export declare const lastNonEmpty: (self: readonly [A, ...A[]]) => A ``` Added in v1.0.0 ## lefts Return all the `Left` elements from an `Interable` of `Either`s. **Signature** ```ts export declare const lefts: (self: Iterable>) => E[] ``` Added in v1.0.0 ## length Return the number of elements in a `ReadonlyArray`. **Signature** ```ts export declare const length: (self: readonly A[]) => number ``` Added in v1.0.0 ## rights Return all the `Right` elements from an `Interable` of `Either`s. **Signature** ```ts export declare const rights: (self: Iterable>) => A[] ``` Added in v1.0.0 ## splitAt Splits an `Iterable` into two pieces, the first piece has max `n` elements. **Signature** ```ts export declare const splitAt: { (n: number): (self: Iterable) => [A[], A[]] (self: Iterable, n: number): [A[], A[]] } ``` Added in v1.0.0 ## splitNonEmptyAt Splits a `NonEmptyReadonlyArray` into two pieces, the first piece has max `n` elements. **Signature** ```ts export declare const splitNonEmptyAt: { (n: number): (self: readonly [A, ...A[]]) => [[A, ...A[]], A[]] (self: readonly [A, ...A[]], n: number): [[A, ...A[]], A[]] } ``` Added in v1.0.0 ## tail Get all but the first element of an `Iterable`, creating a new `Array`, or `None` if the `Iterable` is empty. **Signature** ```ts export declare const tail: (self: Iterable) => Option ``` Added in v1.0.0 ## tailNonEmpty **Signature** ```ts export declare const tailNonEmpty: (self: readonly [A, ...A[]]) => A[] ``` Added in v1.0.0 ## take Keep only a max number of elements from the start of an `Iterable`, creating a new `Array`. **Note**. `n` is normalized to a non negative integer. **Signature** ```ts export declare const take: { (n: number): (self: Iterable) => A[]; (self: Iterable, n: number): A[] } ``` Added in v1.0.0 ## takeRight Keep only a max number of elements from the end of an `Iterable`, creating a new `Array`. **Note**. `n` is normalized to a non negative integer. **Signature** ```ts export declare const takeRight: { (n: number): (self: Iterable) => A[]; (self: Iterable, n: number): A[] } ``` Added in v1.0.0 ## takeWhile Calculate the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`. **Signature** ```ts export declare const takeWhile: { (refinement: Refinement): (self: Iterable) => B[] (predicate: Predicate): (self: Iterable) => B[] (self: Iterable, refinement: Refinement): B[] (self: Iterable, predicate: Predicate): B[] } ``` Added in v1.0.0 ## unappend Return a tuple containing a copy of the `NonEmptyReadonlyArray` without its last element, and that last element. **Signature** ```ts export declare const unappend: (self: readonly [A, ...A[]]) => [A[], A] ``` Added in v1.0.0 ## unprepend Return a tuple containing the first element, and a new `Array` of the remaining elements, if any. **Signature** ```ts export declare const unprepend: (self: readonly [A, ...A[]]) => [A, A[]] ``` Added in v1.0.0 # grouping ## group Group equal, consecutive elements of a `NonEmptyReadonlyArray` into `NonEmptyArray`s. **Signature** ```ts export declare const group: ( isEquivalent: (self: A, that: A) => boolean ) => (self: readonly [A, ...A[]]) => [[A, ...A[]], ...[A, ...A[]][]] ``` Added in v1.0.0 ## groupBy Splits an `Iterable` into sub-non-empty-arrays stored in an object, based on the result of calling a `string`-returning function on each element, and grouping the results according to values returned **Signature** ```ts export declare const groupBy: { (f: (a: A) => string): (self: Iterable) => Record (self: Iterable, f: (a: A) => string): Record } ``` Added in v1.0.0 # guards ## isEmpty Determine if a `ReadonlyArray` is empty narrowing down the type to `readonly []`. **Signature** ```ts export declare const isEmpty: (self: readonly A[]) => self is readonly [] ``` **Example** ```ts import { isEmpty } from '@fp-ts/core/ReadonlyArray' assert.deepStrictEqual(isEmpty([]), true) assert.deepStrictEqual(isEmpty([1, 2, 3]), false) ``` Added in v1.0.0 ## isEmptyArray Determine if an `Array` is empty narrowing down the type to `[]`. **Signature** ```ts export declare const isEmptyArray: (self: A[]) => self is [] ``` **Example** ```ts import { isEmptyArray } from '@fp-ts/core/ReadonlyArray' assert.deepStrictEqual(isEmptyArray([]), true) assert.deepStrictEqual(isEmptyArray([1, 2, 3]), false) ``` Added in v1.0.0 ## isNonEmpty Determine if a `ReadonlyArray` is non empty narrowing down the type to `NonEmptyReadonlyArray`. A `ReadonlyArray` is considered to be a `NonEmptyReadonlyArray` if it contains at least one element. **Signature** ```ts export declare const isNonEmpty: (self: readonly A[]) => self is readonly [A, ...A[]] ``` **Example** ```ts import { isNonEmpty } from '@fp-ts/core/ReadonlyArray' assert.deepStrictEqual(isNonEmpty([]), false) assert.deepStrictEqual(isNonEmpty([1, 2, 3]), true) ``` Added in v1.0.0 ## isNonEmptyArray Determine if an `Array` is non empty narrowing down the type to `NonEmptyArray`. An `Array` is considered to be a `NonEmptyArray` if it contains at least one element. **Signature** ```ts export declare const isNonEmptyArray: (self: A[]) => self is [A, ...A[]] ``` **Example** ```ts import { isNonEmptyArray } from '@fp-ts/core/ReadonlyArray' assert.deepStrictEqual(isNonEmptyArray([]), false) assert.deepStrictEqual(isNonEmptyArray([1, 2, 3]), true) ``` Added in v1.0.0 # instances ## Applicative **Signature** ```ts export declare const Applicative: applicative.Applicative ``` Added in v1.0.0 ## Chainable **Signature** ```ts export declare const Chainable: chainable.Chainable ``` Added in v1.0.0 ## Covariant **Signature** ```ts export declare const Covariant: covariant.Covariant ``` Added in v1.0.0 ## Filterable **Signature** ```ts export declare const Filterable: filterable.Filterable ``` Added in v1.0.0 ## FlatMap **Signature** ```ts export declare const FlatMap: flatMap_.FlatMap ``` Added in v1.0.0 ## Foldable **Signature** ```ts export declare const Foldable: foldable.Foldable ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Monad **Signature** ```ts export declare const Monad: monad.Monad ``` Added in v1.0.0 ## Of **Signature** ```ts export declare const Of: of_.Of ``` Added in v1.0.0 ## Pointed **Signature** ```ts export declare const Pointed: pointed.Pointed ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiApplicative **Signature** ```ts export declare const SemiApplicative: semiApplicative.SemiApplicative ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## Traversable **Signature** ```ts export declare const Traversable: traversable.Traversable ``` Added in v1.0.0 ## TraversableFilterable **Signature** ```ts export declare const TraversableFilterable: traversableFilterable.TraversableFilterable ``` Added in v1.0.0 ## getIntersectionSemigroup **Signature** ```ts export declare const getIntersectionSemigroup: ( isEquivalent: (self: A, that: A) => boolean ) => Semigroup ``` Added in v1.0.0 ## getMonoid Returns a `Monoid` for `ReadonlyArray`. **Signature** ```ts export declare const getMonoid: () => Monoid ``` Added in v1.0.0 ## getSemigroup Returns a `Semigroup` for `ReadonlyArray`. **Signature** ```ts export declare const getSemigroup: () => Semigroup ``` Added in v1.0.0 ## getUnionMonoid **Signature** ```ts export declare const getUnionMonoid: (isEquivalent: (self: A, that: A) => boolean) => Monoid ``` Added in v1.0.0 ## getUnionSemigroup **Signature** ```ts export declare const getUnionSemigroup: (isEquivalent: (self: A, that: A) => boolean) => Semigroup ``` Added in v1.0.0 # lifting ## getOrder This function creates and returns a new `Order` for an array of values based on a given `Order` for the elements of the array. The returned `Order` compares two arrays by applying the given `Order` to each element in the arrays. If all elements are equal, the arrays are then compared based on their length. It is useful when you need to compare two arrays of the same type and you have a specific way of comparing each element of the array. **Signature** ```ts export declare const getOrder: (O: order.Order) => order.Order ``` Added in v1.0.0 ## lift2 Lifts a binary function into `ReadonlyArray`. **Signature** ```ts export declare const lift2: ( f: (a: A, b: B) => C ) => { (self: readonly A[], that: readonly B[]): C[]; (that: readonly B[]): (self: readonly A[]) => C[] } ``` Added in v1.0.0 ## liftEither **Signature** ```ts export declare const liftEither: (f: (...a: A) => Either) => (...a: A) => B[] ``` Added in v1.0.0 ## liftMonoid **Signature** ```ts export declare const liftMonoid: (M: Monoid) => Monoid ``` Added in v1.0.0 ## liftNullable **Signature** ```ts export declare const liftNullable: ( f: (...a: A) => B | null | undefined ) => (...a: A) => NonNullable[] ``` Added in v1.0.0 ## liftOption **Signature** ```ts export declare const liftOption: (f: (...a: A) => Option) => (...a: A) => B[] ``` Added in v1.0.0 ## liftPredicate **Signature** ```ts export declare const liftPredicate: { (refinement: Refinement): (c: C) => B[] (predicate: Predicate): (b: B) => B[] } ``` Added in v1.0.0 # mapping ## as Maps the success value of this effect to the specified constant value. **Signature** ```ts export declare const as: { <_, B>(self: readonly _[], b: B): B[]; (b: B): <_>(self: readonly _[]) => B[] } ``` Added in v1.0.0 ## flap **Signature** ```ts export declare const flap: { (a: A, self: readonly ((a: A) => B)[]): B[] (self: readonly ((a: A) => B)[]): (a: A) => B[] } ``` Added in v1.0.0 ## map **Signature** ```ts export declare const map: { (f: (a: A, i: number) => B): (self: readonly A[]) => B[] (self: readonly A[], f: (a: A, i: number) => B): B[] } ``` Added in v1.0.0 ## mapNonEmpty **Signature** ```ts export declare const mapNonEmpty: { (f: (a: A, i: number) => B): (self: readonly [A, ...A[]]) => [B, ...B[]] (self: readonly [A, ...A[]], f: (a: A, i: number) => B): [B, ...B[]] } ``` Added in v1.0.0 ## tupled **Signature** ```ts export declare const tupled: (self: readonly A[]) => [A][] ``` Added in v1.0.0 # models ## NonEmptyArray (type alias) **Signature** ```ts export type NonEmptyArray = [A, ...Array] ``` Added in v1.0.0 ## NonEmptyReadonlyArray (type alias) **Signature** ```ts export type NonEmptyReadonlyArray = readonly [A, ...Array] ``` Added in v1.0.0 # pattern matching ## match **Signature** ```ts export declare const match: { (onEmpty: LazyArg, onNonEmpty: (self: readonly [A, ...A[]]) => C): (self: readonly A[]) => B | C (self: readonly A[], onEmpty: LazyArg, onNonEmpty: (self: readonly [A, ...A[]]) => C): B | C } ``` Added in v1.0.0 ## matchLeft **Signature** ```ts export declare const matchLeft: { (onEmpty: LazyArg, onNonEmpty: (head: A, tail: A[]) => C): (self: readonly A[]) => B | C (self: readonly A[], onEmpty: LazyArg, onNonEmpty: (head: A, tail: A[]) => C): B | C } ``` Added in v1.0.0 ## matchRight **Signature** ```ts export declare const matchRight: { (onEmpty: LazyArg, onNonEmpty: (init: A[], last: A) => C): (self: readonly A[]) => B | C (self: readonly A[], onEmpty: LazyArg, onNonEmpty: (init: A[], last: A) => C): B | C } ``` Added in v1.0.0 # predicates ## contains Returns a function that checks if a `ReadonlyArray` contains a given value using a provided `equivalence` function. **Signature** ```ts export declare const contains: (isEquivalent: (self: A, that: A) => boolean) => { (a: A): (self: Iterable) => boolean (self: Iterable, a: A): boolean } ``` Added in v1.0.0 ## every Check if a predicate holds true for every `ReadonlyArray` member. **Signature** ```ts export declare function every( refinement: Refinement ): Refinement, ReadonlyArray> export declare function every(predicate: Predicate): Predicate> ``` Added in v1.0.0 ## some Check if a predicate holds true for some `ReadonlyArray` member. **Signature** ```ts export declare const some: (predicate: Predicate) => (self: readonly A[]) => self is readonly [A, ...A[]] ``` Added in v1.0.0 # sorting ## sort Sort the elements of an `Iterable` in increasing order, creating a new `Array`. **Signature** ```ts export declare const sort: (O: order.Order) => (self: Iterable) => A[] ``` Added in v1.0.0 ## sortBy Sort the elements of an `Iterable` in increasing order, where elements are compared using first `orders[0]`, then `orders[1]`, etc... **Signature** ```ts export declare const sortBy: (...orders: readonly order.Order[]) => (self: Iterable) => A[] ``` Added in v1.0.0 ## sortByNonEmpty **Signature** ```ts export declare const sortByNonEmpty: ( ...orders: readonly order.Order[] ) => (as: readonly [A, ...A[]]) => [A, ...A[]] ``` Added in v1.0.0 ## sortNonEmpty Sort the elements of a `NonEmptyReadonlyArray` in increasing order, creating a new `NonEmptyArray`. **Signature** ```ts export declare const sortNonEmpty: (O: order.Order) => (self: readonly [A, ...A[]]) => [A, ...A[]] ``` Added in v1.0.0 # traversing ## sequence **Signature** ```ts export declare const sequence: ( F: applicative.Applicative ) => (self: readonly Kind[]) => Kind ``` Added in v1.0.0 ## sequenceNonEmpty **Signature** ```ts export declare const sequenceNonEmpty: ( F: semiApplicative.SemiApplicative ) => (self: readonly [Kind, ...Kind[]]) => Kind ``` Added in v1.0.0 ## traverse **Signature** ```ts export declare const traverse: ( F: applicative.Applicative ) => { (f: (a: A, i: number) => Kind): (self: Iterable) => Kind (self: Iterable, f: (a: A, i: number) => Kind): Kind } ``` Added in v1.0.0 ## traverseNonEmpty **Signature** ```ts export declare const traverseNonEmpty: ( F: semiApplicative.SemiApplicative ) => { (f: (a: A, i: number) => Kind): ( self: readonly [A, ...A[]] ) => Kind (self: readonly [A, ...A[]], f: (a: A, i: number) => Kind): Kind< F, R, O, E, [B, ...B[]] > } ``` Added in v1.0.0 ## traverseTap **Signature** ```ts export declare const traverseTap: ( F: applicative.Applicative ) => { (self: readonly A[], f: (a: A) => Kind): Kind (f: (a: A) => Kind): (self: readonly A[]) => Kind } ``` Added in v1.0.0 # type lambdas ## ReadonlyArrayTypeLambda (interface) **Signature** ```ts export interface ReadonlyArrayTypeLambda extends TypeLambda { readonly type: ReadonlyArray } ``` Added in v1.0.0 # unsafe ## unsafeGet Gets an element unsafely, will throw on out of bounds. **Signature** ```ts export declare const unsafeGet: { (index: number): (self: readonly A[]) => A (self: readonly A[], index: number): A } ``` Added in v1.0.0 # utils ## ap **Signature** ```ts export declare const ap: { (self: readonly ((a: A) => B)[], that: readonly A[]): B[] (that: readonly A[]): (self: readonly ((a: A) => B)[]) => B[] } ``` Added in v1.0.0 ## append Append an element to the end of an `Iterable`, creating a new `NonEmptyArray`. **Signature** ```ts export declare const append: { (last: B): (self: Iterable) => [B | A, ...(B | A)[]] (self: Iterable, last: B): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## appendAll **Signature** ```ts export declare const appendAll: { (that: Iterable): (self: Iterable) => (B | A)[] (self: Iterable, that: Iterable): (A | B)[] } ``` Added in v1.0.0 ## appendAllNonEmpty **Signature** ```ts export declare const appendAllNonEmpty: { (that: readonly [B, ...B[]]): (self: Iterable) => [B | A, ...(B | A)[]] (that: Iterable): (self: readonly [A, ...A[]]) => [B | A, ...(B | A)[]] (self: Iterable, that: readonly [B, ...B[]]): [A | B, ...(A | B)[]] (self: readonly [A, ...A[]], that: Iterable): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## chop A useful recursion pattern for processing an `Iterable` to produce a new `Array`, often used for "chopping" up the input `Iterable`. Typically chop is called with some function that will consume an initial prefix of the `Iterable` and produce a value and the rest of the `Array`. **Signature** ```ts export declare const chop: { (f: (as: readonly [A, ...A[]]) => readonly [B, readonly A[]]): (self: Iterable) => B[] (self: Iterable, f: (as: readonly [A, ...A[]]) => readonly [B, readonly A[]]): B[] } ``` Added in v1.0.0 ## chopNonEmpty A useful recursion pattern for processing a `NonEmptyReadonlyArray` to produce a new `NonEmptyReadonlyArray`, often used for "chopping" up the input `NonEmptyReadonlyArray`. Typically `chop` is called with some function that will consume an initial prefix of the `NonEmptyReadonlyArray` and produce a value and the tail of the `NonEmptyReadonlyArray`. **Signature** ```ts export declare const chopNonEmpty: { (f: (as: readonly [A, ...A[]]) => readonly [B, readonly A[]]): (self: readonly [A, ...A[]]) => [B, ...B[]] (self: readonly [A, ...A[]], f: (as: readonly [A, ...A[]]) => readonly [B, readonly A[]]): [B, ...B[]] } ``` Added in v1.0.0 ## composeKleisliArrow **Signature** ```ts export declare const composeKleisliArrow: { (afb: (a: A) => readonly B[], bfc: (b: B) => readonly C[]): (a: A) => readonly C[] (bfc: (b: B) => readonly C[]): (afb: (a: A) => readonly B[]) => (a: A) => readonly C[] } ``` Added in v1.0.0 ## copy **Signature** ```ts export declare const copy: { (self: readonly [A, ...A[]]): [A, ...A[]]; (self: readonly A[]): A[] } ``` Added in v1.0.0 ## difference Creates a `Array` of values not included in the other given `Iterable`. The order and references of result values are determined by the first `Iterable`. **Signature** ```ts export declare const difference: (isEquivalent: (self: A, that: A) => boolean) => { (that: Iterable): (self: Iterable) => A[] (self: Iterable, that: Iterable): A[] } ``` Added in v1.0.0 ## extend **Signature** ```ts export declare const extend: { (f: (as: readonly A[]) => B): (self: readonly A[]) => B[] (self: readonly A[], f: (as: readonly A[]) => B): B[] } ``` Added in v1.0.0 ## insertAt Insert an element at the specified index, creating a new `NonEmptyArray`, or return `None` if the index is out of bounds. **Signature** ```ts export declare const insertAt: { (i: number, b: B): (self: Iterable) => Option<[B | A, ...(B | A)[]]> (self: Iterable, i: number, b: B): Option<[A | B, ...(A | B)[]]> } ``` Added in v1.0.0 ## intercalate Fold an `Iterable`, accumulating values in some `Monoid`, combining adjacent elements using the specified separator. **Signature** ```ts export declare const intercalate: (M: Monoid) => { (middle: A): (self: Iterable) => A (self: Iterable, middle: A): A } ``` Added in v1.0.0 ## intercalateNonEmpty Places an element in between members of a `NonEmptyReadonlyArray`, then folds the results using the provided `Semigroup`. **Signature** ```ts export declare const intercalateNonEmpty: (S: Semigroup) => { (middle: A): (self: readonly [A, ...A[]]) => A (self: readonly [A, ...A[]], middle: A): A } ``` Added in v1.0.0 ## intersection Creates an `Array` of unique values that are included in all given `Iterable`s. The order and references of result values are determined by the first `Iterable`. **Signature** ```ts export declare const intersection: (isEquivalent: (self: A, that: A) => boolean) => { (that: Iterable): (self: Iterable) => A[] (self: Iterable, that: Iterable): A[] } ``` Added in v1.0.0 ## intersperse Places an element in between members of an `Iterable` **Signature** ```ts export declare const intersperse: { (middle: B): (self: Iterable) => (B | A)[] (self: Iterable, middle: B): (A | B)[] } ``` Added in v1.0.0 ## intersperseNonEmpty Places an element in between members of a `NonEmptyReadonlyArray` **Signature** ```ts export declare const intersperseNonEmpty: { (middle: B): (self: readonly [A, ...A[]]) => [B | A, ...(B | A)[]] (self: readonly [A, ...A[]], middle: B): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## join **Signature** ```ts export declare const join: { (middle: string): (self: ReadonlyArray) => string (self: ReadonlyArray, middle: string): string } ``` Added in v1.0.0 ## max **Signature** ```ts export declare const max: (O: order.Order) => (self: readonly [A, ...A[]]) => A ``` Added in v1.0.0 ## min **Signature** ```ts export declare const min: (O: order.Order) => (self: readonly [A, ...A[]]) => A ``` Added in v1.0.0 ## modify Apply a function to the element at the specified index, creating a new `Array`, or return a copy of the input if the index is out of bounds. **Signature** ```ts export declare const modify: { (i: number, f: (a: A) => B): (self: Iterable) => (A | B)[] (self: Iterable, i: number, f: (a: A) => B): (A | B)[] } ``` Added in v1.0.0 ## modifyNonEmptyHead Apply a function to the head, creating a new `NonEmptyReadonlyArray`. **Signature** ```ts export declare const modifyNonEmptyHead: { (f: (a: A) => B): (self: readonly [A, ...A[]]) => [A | B, ...(A | B)[]] (self: readonly [A, ...A[]], f: (a: A) => B): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## modifyNonEmptyLast Apply a function to the last element, creating a new `NonEmptyReadonlyArray`. **Signature** ```ts export declare const modifyNonEmptyLast: { (f: (a: A) => B): (self: readonly [A, ...A[]]) => [A | B, ...(A | B)[]] (self: readonly [A, ...A[]], f: (a: A) => B): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## modifyOption Apply a function to the element at the specified index, creating a new `Array`, or return `None` if the index is out of bounds. **Signature** ```ts export declare const modifyOption: { (i: number, f: (a: A) => B): (self: Iterable) => Option<(A | B)[]> (self: Iterable, i: number, f: (a: A) => B): Option<(A | B)[]> } ``` Added in v1.0.0 ## prepend Prepend an element to the front of an `Iterable`, creating a new `NonEmptyArray`. **Signature** ```ts export declare const prepend: { (head: B): (self: Iterable) => [B | A, ...(B | A)[]] (self: Iterable, head: B): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## prependAll **Signature** ```ts export declare const prependAll: { (that: Iterable): (self: Iterable) => (B | A)[] (self: Iterable, that: Iterable): (A | B)[] } ``` Added in v1.0.0 ## prependAllNonEmpty **Signature** ```ts export declare const prependAllNonEmpty: { (that: readonly [B, ...B[]]): (self: Iterable) => [B | A, ...(B | A)[]] (that: Iterable): (self: readonly [A, ...A[]]) => [B | A, ...(B | A)[]] (self: Iterable, that: readonly [B, ...B[]]): [A | B, ...(A | B)[]] (self: readonly [A, ...A[]], that: Iterable): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## remove Delete the element at the specified index, creating a new `Array`, or return a copy of the input if the index is out of bounds. **Signature** ```ts export declare const remove: { (i: number): (self: Iterable) => A[]; (self: Iterable, i: number): A[] } ``` Added in v1.0.0 ## replace Change the element at the specified index, creating a new `Array`, or return a copy of the input if the index is out of bounds. **Signature** ```ts export declare const replace: { (i: number, b: B): (self: Iterable) => (B | A)[] (self: Iterable, i: number, b: B): (A | B)[] } ``` Added in v1.0.0 ## replaceOption **Signature** ```ts export declare const replaceOption: { (i: number, b: B): (self: Iterable) => Option<(B | A)[]> (self: Iterable, i: number, b: B): Option<(A | B)[]> } ``` Added in v1.0.0 ## reverse Reverse an `Iterable`, creating a new `Array`. **Signature** ```ts export declare const reverse: (self: Iterable) => A[] ``` Added in v1.0.0 ## reverseNonEmpty **Signature** ```ts export declare const reverseNonEmpty: (self: readonly [A, ...A[]]) => [A, ...A[]] ``` Added in v1.0.0 ## rotate Rotate an `Iterable` by `n` steps. **Signature** ```ts export declare const rotate: { (n: number): (self: Iterable) => A[]; (self: Iterable, n: number): A[] } ``` Added in v1.0.0 ## rotateNonEmpty Rotate a `NonEmptyReadonlyArray` by `n` steps. **Signature** ```ts export declare const rotateNonEmpty: { (n: number): (self: readonly [A, ...A[]]) => [A, ...A[]] (self: readonly [A, ...A[]], n: number): [A, ...A[]] } ``` Added in v1.0.0 ## setNonEmptyHead Change the head, creating a new `NonEmptyReadonlyArray`. **Signature** ```ts export declare const setNonEmptyHead: { (b: B): (self: readonly [A, ...A[]]) => [B | A, ...(B | A)[]] (self: readonly [A, ...A[]], b: B): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## setNonEmptyLast Change the last element, creating a new `NonEmptyReadonlyArray`. **Signature** ```ts export declare const setNonEmptyLast: { (b: B): (self: readonly [A, ...A[]]) => [B | A, ...(B | A)[]] (self: readonly [A, ...A[]], b: B): [A | B, ...(A | B)[]] } ``` Added in v1.0.0 ## traverseFilter Filter values inside a context. **Signature** ```ts export declare const traverseFilter: ( F: applicative.Applicative ) => { (predicate: (a: A) => Kind): ( self: readonly B[] ) => Kind (self: readonly B[], predicate: (a: A) => Kind): Kind< F, R, O, E, B[] > } ``` Added in v1.0.0 ## traversePartition **Signature** ```ts export declare const traversePartition: ( F: applicative.Applicative ) => { (predicate: (a: A) => Kind): ( self: readonly B[] ) => Kind (self: readonly B[], predicate: (a: A) => Kind): Kind< F, R, O, E, [B[], B[]] > } ``` Added in v1.0.0 ## union **Signature** ```ts export declare const union: (isEquivalent: (self: A, that: A) => boolean) => { (that: readonly A[]): (self: readonly A[]) => A[] (self: readonly A[], that: readonly A[]): A[] } ``` Added in v1.0.0 ## unionNonEmpty **Signature** ```ts export declare const unionNonEmpty: (isEquivalent: (self: A, that: A) => boolean) => { (that: readonly [A, ...A[]]): (self: readonly A[]) => [A, ...A[]] (that: readonly A[]): (self: readonly [A, ...A[]]) => [A, ...A[]] (self: readonly A[], that: readonly [A, ...A[]]): [A, ...A[]] (self: readonly [A, ...A[]], that: readonly A[]): [A, ...A[]] } ``` Added in v1.0.0 ## uniq Remove duplicates from am `Iterable`, keeping the first occurrence of an element. **Signature** ```ts export declare const uniq: (isEquivalent: (self: A, that: A) => boolean) => (self: Iterable) => A[] ``` Added in v1.0.0 ## uniqNonEmpty Remove duplicates from a `NonEmptyReadonlyArray`, keeping the first occurrence of an element. **Signature** ```ts export declare const uniqNonEmpty: ( isEquivalent: (self: A, that: A) => boolean ) => (self: readonly [A, ...A[]]) => [A, ...A[]] ``` Added in v1.0.0 ## unzip This function is the inverse of `zip`. Takes an `Iterable` of pairs and return two corresponding `Array`s. **Signature** ```ts export declare const unzip: (self: Iterable<[A, B]>) => [A[], B[]] ``` Added in v1.0.0 ## unzipNonEmpty **Signature** ```ts export declare const unzipNonEmpty: (self: readonly [[A, B], ...[A, B][]]) => [[A, ...A[]], [B, ...B[]]] ``` Added in v1.0.0 ## zip Takes two `Iterable`s and returns an `Array` of corresponding pairs. If one input `Iterable` is short, excess elements of the longer `Iterable` are discarded. **Signature** ```ts export declare const zip: { (that: Iterable): (self: Iterable) => [A, B][] (self: Iterable, that: Iterable): [A, B][] } ``` Added in v1.0.0 ## zipNonEmpty **Signature** ```ts export declare const zipNonEmpty: { (that: readonly [B, ...B[]]): (self: readonly [A, ...A[]]) => [[A, B], ...[A, B][]] (self: readonly [A, ...A[]], that: readonly [B, ...B[]]): [[A, B], ...[A, B][]] } ``` Added in v1.0.0 ## zipNonEmptyWith **Signature** ```ts export declare const zipNonEmptyWith: { (that: readonly [B, ...B[]], f: (a: A, b: B) => C): (self: readonly [A, ...A[]]) => [C, ...C[]] (self: readonly [A, ...A[]], that: readonly [B, ...B[]], f: (a: A, b: B) => C): [C, ...C[]] } ``` Added in v1.0.0 ## zipWith Apply a function to pairs of elements at the same index in two `Iterable`s, collecting the results in a new `Array`. If one input `Iterable` is short, excess elements of the longer `Iterable` are discarded. **Signature** ```ts export declare const zipWith: { (that: Iterable, f: (a: A, b: B) => C): (self: Iterable) => C[] (self: Iterable, that: Iterable, f: (a: A, b: B) => C): C[] } ``` Added in v1.0.0 ================================================ FILE: docs/modules/ReadonlyRecord.ts.md ================================================ --- title: ReadonlyRecord.ts nav_order: 13 parent: Modules --- ## ReadonlyRecord overview This module provides utility functions for working with records in TypeScript. Added in v1.0.0 ---

Table of contents

- [constructors](#constructors) - [empty](#empty) - [fromIterable](#fromiterable) - [conversions](#conversions) - [collect](#collect) - [toArray](#toarray) - [filtering](#filtering) - [compact](#compact) - [filter](#filter) - [partition](#partition) - [partitionMap](#partitionmap) - [separate](#separate) - [traverseFilterMap](#traversefiltermap) - [traversePartitionMap](#traversepartitionmap) - [guards](#guards) - [isEmpty](#isempty) - [instances](#instances) - [Covariant](#covariant) - [Filterable](#filterable) - [Invariant](#invariant) - [Traversable](#traversable) - [TraversableFilterable](#traversablefilterable) - [mapping](#mapping) - [as](#as) - [flap](#flap) - [tupled](#tupled) - [models](#models) - [ReadonlyRecord (interface)](#readonlyrecord-interface) - [record](#record) - [pop](#pop) - [traversing](#traversing) - [sequence](#sequence) - [traverse](#traverse) - [traverseTap](#traversetap) - [type lambdas](#type-lambdas) - [ReadonlyRecordTypeLambda (interface)](#readonlyrecordtypelambda-interface) - [utils](#utils) - [filterMap](#filtermap) - [get](#get) - [has](#has) - [map](#map) - [modifyOption](#modifyoption) - [remove](#remove) - [replaceOption](#replaceoption) - [size](#size) - [traverseFilter](#traversefilter) - [traversePartition](#traversepartition) --- # constructors ## empty Creates a new, empty record. **Signature** ```ts export declare const empty:
() => Record ``` Added in v1.0.0 ## fromIterable Takes an iterable and a projection function and returns a record. The projection function maps each value of the iterable to a tuple of a key and a value, which is then added to the resulting record. **Signature** ```ts export declare const fromIterable: { (f: (a: A) => readonly [string, B]): (self: Iterable) => Record (self: Iterable, f: (a: A) => readonly [string, B]): Record } ``` **Example** ```ts import { fromIterable } from '@fp-ts/core/ReadonlyRecord' const input = [1, 2, 3, 4] assert.deepStrictEqual( fromIterable(input, (a) => [String(a), a * 2]), { '1': 2, '2': 4, '3': 6, '4': 8 } ) ``` Added in v1.0.0 # conversions ## collect Transforms the values of a `ReadonlyRecord` into an `Array` with a custom mapping function. **Signature** ```ts export declare const collect: { (f: (key: string, a: A) => B): (self: ReadonlyRecord) => B[] (self: ReadonlyRecord, f: (key: string, a: A) => B): B[] } ``` **Example** ```ts import { collect } from '@fp-ts/core/ReadonlyRecord' const x = { a: 1, b: 2, c: 3 } assert.deepStrictEqual( collect(x, (key, n) => [key, n]), [ ['a', 1], ['b', 2], ['c', 3], ] ) ``` Added in v1.0.0 ## toArray Converts a `ReadonlyRecord` to an `Array` of key-value pairs. **Signature** ```ts export declare const toArray: (self: ReadonlyRecord) => [string, A][] ``` **Example** ```ts import { toArray } from '@fp-ts/core/ReadonlyRecord' const x = { a: 1, b: 2 } assert.deepStrictEqual(toArray(x), [ ['a', 1], ['b', 2], ]) ``` Added in v1.0.0 # filtering ## compact Given a `ReadonlyRecord` with `Option` values, returns a `Record` with only the `Some` values, with the same keys. **Signature** ```ts export declare const compact: (self: ReadonlyRecord>) => Record ``` **Example** ```ts import { compact } from '@fp-ts/core/ReadonlyRecord' import { some, none } from '@fp-ts/core/Option' assert.deepStrictEqual(compact({ a: some(1), b: none(), c: some(2) }), { a: 1, c: 2 }) ``` Added in v1.0.0 ## filter Selects properties from a record whose values match the given predicate. **Signature** ```ts export declare const filter: { (refinement: (a: A, key: string) => a is B): ( self: ReadonlyRecord ) => Record (predicate: (a: A, key: string) => boolean): (self: ReadonlyRecord) => Record (self: ReadonlyRecord, refinement: (a: A, key: string) => a is B): Record< string, B > (self: ReadonlyRecord, predicate: (a: A, key: string) => boolean): Record } ``` **Example** ```ts import { filter } from '@fp-ts/core/ReadonlyRecord' const x = { a: 1, b: 2, c: 3, d: 4 } assert.deepStrictEqual( filter(x, (n) => n > 2), { c: 3, d: 4 } ) ``` Added in v1.0.0 ## partition Partitions a `ReadonlyRecord` into two separate `Record`s based on the result of a predicate function. **Signature** ```ts export declare const partition: { (refinement: (a: A, key: string) => a is B): ( self: ReadonlyRecord ) => [Record, Record] (predicate: (a: A, key: string) => boolean): ( self: ReadonlyRecord ) => [Record, Record] (self: ReadonlyRecord, refinement: (a: A, key: string) => a is B): [ Record, Record ] (self: ReadonlyRecord, predicate: (a: A, key: string) => boolean): [ Record, Record ] } ``` **Example** ```ts import { partition } from '@fp-ts/core/ReadonlyRecord' assert.deepStrictEqual( partition({ a: 1, b: 3 }, (n) => n > 2), [{ a: 1 }, { b: 3 }] ) ``` Added in v1.0.0 ## partitionMap Partitions the elements of a `ReadonlyRecord` into two groups: those that match a predicate, and those that don't. **Signature** ```ts export declare const partitionMap: { (f: (a: A, key: string) => Either): (self: ReadonlyRecord) => [Record, Record] (self: ReadonlyRecord, f: (a: A, key: string) => Either): [Record, Record] } ``` **Example** ```ts import { partitionMap } from '@fp-ts/core/ReadonlyRecord' import { left, right } from '@fp-ts/core/Either' const x = { a: 1, b: 2, c: 3 } const f = (n: number) => (n % 2 === 0 ? right(n) : left(n)) assert.deepStrictEqual(partitionMap(x, f), [{ a: 1, c: 3 }, { b: 2 }]) ``` Added in v1.0.0 ## separate Partitions a `ReadonlyRecord` of `Either` values into two separate records, one with the `Left` values and one with the `Right` values. **Signature** ```ts export declare const separate: (self: ReadonlyRecord>) => [Record, Record] ``` **Example** ```ts import { separate } from '@fp-ts/core/ReadonlyRecord' import { left, right } from '@fp-ts/core/Either' assert.deepStrictEqual(separate({ a: left('e'), b: right(1) }), [{ a: 'e' }, { b: 1 }]) ``` Added in v1.0.0 ## traverseFilterMap **Signature** ```ts export declare const traverseFilterMap: ( F: applicative.Applicative ) => { (f: (a: A) => Kind>): ( self: ReadonlyRecord ) => Kind> (self: ReadonlyRecord, f: (a: A) => Kind>): Kind< F, R, O, E, Record > } ``` Added in v1.0.0 ## traversePartitionMap **Signature** ```ts export declare const traversePartitionMap: ( F: applicative.Applicative ) => { (f: (a: A) => Kind>): ( self: ReadonlyRecord ) => Kind, Record]> (self: ReadonlyRecord, f: (a: A) => Kind>): Kind< F, R, O, E, [Record, Record] > } ``` Added in v1.0.0 # guards ## isEmpty Determine if a `ReadonlyRecord` is empty. **Signature** ```ts export declare const isEmpty: (self: ReadonlyRecord) => self is Record ``` **Example** ```ts import { isEmpty } from '@fp-ts/core/ReadonlyRecord' assert.deepStrictEqual(isEmpty({}), true) assert.deepStrictEqual(isEmpty({ a: 3 }), false) ``` Added in v1.0.0 # instances ## Covariant **Signature** ```ts export declare const Covariant: covariant.Covariant ``` Added in v1.0.0 ## Filterable **Signature** ```ts export declare const Filterable: filterable.Filterable ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Traversable **Signature** ```ts export declare const Traversable: traversable.Traversable ``` Added in v1.0.0 ## TraversableFilterable **Signature** ```ts export declare const TraversableFilterable: traversableFilterable.TraversableFilterable ``` Added in v1.0.0 # mapping ## as Maps the success value of this effect to the specified constant value. **Signature** ```ts export declare const as: { (b: B): <_>(self: ReadonlyRecord<_>) => Record <_, B>(self: ReadonlyRecord<_>, b: B): Record } ``` Added in v1.0.0 ## flap **Signature** ```ts export declare const flap: { (self: ReadonlyRecord<(a: A) => B>): (a: A) => Record (a: A, self: ReadonlyRecord<(a: A) => B>): Record } ``` Added in v1.0.0 ## tupled **Signature** ```ts export declare const tupled: (self: ReadonlyRecord) => Record ``` Added in v1.0.0 # models ## ReadonlyRecord (interface) **Signature** ```ts export interface ReadonlyRecord { readonly [x: string]: A } ``` Added in v1.0.0 # record ## pop Retrieves the value of the property with the given `key` from a `ReadonlyRecord` and returns an `Option` of a tuple with the value and the `ReadonlyRecord` with the removed property. If the key is not present, returns `O.none`. **Signature** ```ts export declare const pop: { (key: string): (self: ReadonlyRecord) => Option]> (self: ReadonlyRecord, key: string): Option]> } ``` **Example** ```ts import { pop } from '@fp-ts/core/ReadonlyRecord' import { some, none } from '@fp-ts/core/Option' assert.deepStrictEqual(pop({ a: 1, b: 2 }, 'a'), some([1, { b: 2 }])) assert.deepStrictEqual(pop({ a: 1, b: 2 }, 'c'), none()) ``` Added in v1.0.0 # traversing ## sequence Transforms a `ReadonlyRecord` of `Kind` values into a `Kind` of `Record` values. **Signature** ```ts export declare const sequence: ( F: applicative.Applicative ) => (self: ReadonlyRecord>) => Kind> ``` **Example** ```ts import * as RR from '@fp-ts/core/ReadonlyRecord' import { some, none, Applicative } from '@fp-ts/core/Option' const sequence = RR.sequence(Applicative) assert.deepStrictEqual(sequence({ a: some(1), b: some(2) }), some({ a: 1, b: 2 })) assert.deepStrictEqual(sequence({ a: none(), b: some(2) }), none()) ``` Added in v1.0.0 ## traverse Maps each entry of a `ReadonlyRecord` to an effect and collects the results into a new record. **Signature** ```ts export declare const traverse: ( F: applicative.Applicative ) => { (f: (a: A, key: string) => Kind): ( self: ReadonlyRecord ) => Kind> (self: ReadonlyRecord, f: (a: A, key: string) => Kind): Kind< F, R, O, E, Record > } ``` **Example** ```ts import { traverse } from '@fp-ts/core/ReadonlyRecord' import { some, none, Applicative } from '@fp-ts/core/Option' assert.deepStrictEqual( traverse(Applicative)({ a: 1, b: 2 }, (n: number) => (n <= 2 ? some(n) : none())), some({ a: 1, b: 2 }) ) assert.deepStrictEqual( traverse(Applicative)({ a: 1, b: 2 }, (n: number) => (n >= 2 ? some(n) : none())), none() ) ``` Added in v1.0.0 ## traverseTap **Signature** ```ts export declare const traverseTap: ( F: applicative.Applicative ) => { (f: (a: A) => Kind): (self: ReadonlyRecord) => Kind> (self: ReadonlyRecord, f: (a: A) => Kind): Kind> } ``` Added in v1.0.0 # type lambdas ## ReadonlyRecordTypeLambda (interface) **Signature** ```ts export interface ReadonlyRecordTypeLambda extends TypeLambda { readonly type: ReadonlyRecord } ``` Added in v1.0.0 # utils ## filterMap Transforms a `ReadonlyRecord` into a `Record` by applying the function `f` to each key and value in the original `ReadonlyRecord`. If the function returns `Some`, the key-value pair is included in the output `Record`. **Signature** ```ts export declare const filterMap: { (f: (a: A, key: string) => Option): (self: ReadonlyRecord) => Record (self: ReadonlyRecord, f: (a: A, key: string) => Option): Record } ``` **Example** ```ts import { filterMap } from '@fp-ts/core/ReadonlyRecord' import { some, none } from '@fp-ts/core/Option' const x = { a: 1, b: 2, c: 3 } const f = (a: number, key: string) => (a > 2 ? some(a * 2) : none()) assert.deepStrictEqual(filterMap(x, f), { c: 6 }) ``` Added in v1.0.0 ## get Retrieve a value at a particular key from a `ReadonlyRecord`, returning it wrapped in an `Option`. **Signature** ```ts export declare const get: { (key: string): (self: ReadonlyRecord) => Option (self: ReadonlyRecord, key: string): Option } ``` **Example** ```ts import { get } from '@fp-ts/core/ReadonlyRecord' import { some, none } from '@fp-ts/core/Option' const person = { name: 'John Doe', age: 35 } assert.deepStrictEqual(get(person, 'name'), some('John Doe')) assert.deepStrictEqual(get(person, 'email'), none()) ``` Added in v1.0.0 ## has Check if a given `key` exists in a `ReadonlyRecord`. **Signature** ```ts export declare const has: { (key: string): (self: ReadonlyRecord) => boolean (self: ReadonlyRecord, key: string): boolean } ``` **Example** ```ts import { has } from '@fp-ts/core/ReadonlyRecord' assert.deepStrictEqual(has({ a: 1, b: 2 }, 'a'), true) assert.deepStrictEqual(has({ a: 1, b: 2 }, 'c'), false) ``` Added in v1.0.0 ## map Maps a `ReadonlyRecord` into another `Record` by applying a transformation function to each of its values. **Signature** ```ts export declare const map: { (f: (a: A, key: K) => B): (self: Readonly>) => Record (self: Readonly>, f: (a: A, key: K) => B): Record } ``` **Example** ```ts import { map } from '@fp-ts/core/ReadonlyRecord' const f = (n: number) => `-${n}` assert.deepStrictEqual(map({ a: 3, b: 5 }, f), { a: '-3', b: '-5' }) const g = (n: number, key: string) => `${key.toUpperCase()}-${n}` assert.deepStrictEqual(map({ a: 3, b: 5 }, g), { a: 'A-3', b: 'B-5' }) ``` Added in v1.0.0 ## modifyOption Apply a function to the element at the specified key, creating a new record, or return `None` if the key doesn't exist. **Signature** ```ts export declare const modifyOption: { (key: string, f: (a: A) => B): (self: ReadonlyRecord) => Option> (self: ReadonlyRecord, key: string, f: (a: A) => B): Option> } ``` **Example** ```ts import { modifyOption } from '@fp-ts/core/ReadonlyRecord' import { some, none } from '@fp-ts/core/Option' const f = (x: number) => x * 2 assert.deepStrictEqual(modifyOption({ a: 3 }, 'a', f), some({ a: 6 })) assert.deepStrictEqual(modifyOption({ a: 3 }, 'b', f), none()) ``` Added in v1.0.0 ## remove Removes a key from a `ReadonlyRecord` and returns a new `Record` **Signature** ```ts export declare const remove: { (key: string): (self: ReadonlyRecord) => Record (self: ReadonlyRecord, key: string): Record } ``` **Example** ```ts import { remove } from '@fp-ts/core/ReadonlyRecord' assert.deepStrictEqual(remove({ a: 1, b: 2 }, 'a'), { b: 2 }) ``` Added in v1.0.0 ## replaceOption Replaces a value in the record with the new value passed as parameter. **Signature** ```ts export declare const replaceOption: { (key: string, b: B): (self: ReadonlyRecord) => Option> (self: ReadonlyRecord, key: string, b: B): Option> } ``` **Example** ```ts import { replaceOption } from '@fp-ts/core/ReadonlyRecord' import { some, none } from '@fp-ts/core/Option' assert.deepStrictEqual(replaceOption({ a: 1, b: 2, c: 3 }, 'a', 10), some({ a: 10, b: 2, c: 3 })) assert.deepStrictEqual(replaceOption({}, 'a', 10), none()) ``` Added in v1.0.0 ## size Returns the number of key/value pairs in a `ReadonlyRecord`. **Signature** ```ts export declare const size: (self: ReadonlyRecord) => number ``` **Example** ```ts import { size } from '@fp-ts/core/ReadonlyRecord' assert.deepStrictEqual(size({ a: 'a', b: 1, c: true }), 3) ``` Added in v1.0.0 ## traverseFilter Filter values inside a context. **Signature** ```ts export declare const traverseFilter: ( F: applicative.Applicative ) => { (predicate: (a: A) => Kind): ( self: ReadonlyRecord ) => Kind> (self: ReadonlyRecord, predicate: (a: A) => Kind): Kind< F, R, O, E, Record > } ``` Added in v1.0.0 ## traversePartition **Signature** ```ts export declare const traversePartition: ( F: applicative.Applicative ) => { (predicate: (a: A) => Kind): ( self: ReadonlyRecord ) => Kind, Record]> (self: ReadonlyRecord, predicate: (a: A) => Kind): Kind< F, R, O, E, [Record, Record] > } ``` Added in v1.0.0 ================================================ FILE: docs/modules/String.ts.md ================================================ --- title: String.ts nav_order: 14 parent: Modules --- ## String overview This module provides utility functions and type class instances for working with the `string` type in TypeScript. It includes functions for basic string manipulation, as well as type class instances for `Equivalence`, `Order`, `Semigroup`, and `Monoid`. Added in v1.0.0 ---

Table of contents

- [guards](#guards) - [isString](#isstring) - [instances](#instances) - [Equivalence](#equivalence) - [Monoid](#monoid) - [Order](#order) - [Semigroup](#semigroup) - [utils](#utils) - [concat](#concat) - [empty](#empty) - [endsWith](#endswith) - [endsWithPosition](#endswithposition) - [includes](#includes) - [includesWithPosition](#includeswithposition) - [isEmpty](#isempty) - [isNonEmpty](#isnonempty) - [length](#length) - [replace](#replace) - [slice](#slice) - [split](#split) - [startsWith](#startswith) - [startsWithPosition](#startswithposition) - [takeLeft](#takeleft) - [takeRight](#takeright) - [toLowerCase](#tolowercase) - [toUpperCase](#touppercase) - [trim](#trim) - [trimEnd](#trimend) - [trimStart](#trimstart) --- # guards ## isString Tests if a value is a `string`. **Signature** ```ts export declare const isString: Refinement ``` **Example** ```ts import { isString } from '@fp-ts/core/String' assert.deepStrictEqual(isString('a'), true) assert.deepStrictEqual(isString(1), false) ``` Added in v1.0.0 # instances ## Equivalence **Signature** ```ts export declare const Equivalence: equivalence.Equivalence ``` Added in v1.0.0 ## Monoid `string` monoid under concatenation. The `empty` value is `''`. **Signature** ```ts export declare const Monoid: monoid.Monoid ``` Added in v1.0.0 ## Order **Signature** ```ts export declare const Order: order.Order ``` Added in v1.0.0 ## Semigroup `string` semigroup under concatenation. **Signature** ```ts export declare const Semigroup: semigroup.Semigroup ``` Added in v1.0.0 # utils ## concat **Signature** ```ts export declare const concat: { (that: string): (self: string) => string; (self: string, that: string): string } ``` Added in v1.0.0 ## empty The empty string `""`. **Signature** ```ts export declare const empty: '' ``` Added in v1.0.0 ## endsWith **Signature** ```ts export declare const endsWith: { (searchString: string): (self: string) => boolean (self: string, searchString: string): boolean } ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.endsWith('abc', 'c'), true) assert.deepStrictEqual(S.endsWith('ab', 'c'), false) ``` Added in v1.0.0 ## endsWithPosition **Signature** ```ts export declare const endsWithPosition: { (searchString: string, position: number): (self: string) => boolean (self: string, searchString: string, position: number): boolean } ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.endsWithPosition('abc', 'b', 2), true) assert.deepStrictEqual(S.endsWithPosition('abc', 'c', 2), false) ``` Added in v1.0.0 ## includes Returns `true` if `searchString` appears as a substring of `self`, at one or more positions that are greater than or equal to `0`; otherwise, returns `false`. **Signature** ```ts export declare const includes: { (searchString: string): (self: string) => boolean (self: string, searchString: string): boolean } ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.includes('abc', 'b'), true) assert.deepStrictEqual(S.includes('abc', 'd'), false) ``` Added in v1.0.0 ## includesWithPosition Returns `true` if `searchString` appears as a substring of `self`, at one or more positions that are greater than or equal to `position`; otherwise, returns `false`. **Signature** ```ts export declare const includesWithPosition: { (searchString: string, position: number): (self: string) => boolean (self: string, searchString: string, position: number): boolean } ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.includesWithPosition('abc', 'b', 1), true) assert.deepStrictEqual(S.includesWithPosition('abc', 'a', 1), false) ``` Added in v1.0.0 ## isEmpty Test whether a `string` is empty. **Signature** ```ts export declare const isEmpty: (self: string) => self is '' ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.isEmpty(''), true) assert.deepStrictEqual(S.isEmpty('a'), false) ``` Added in v1.0.0 ## isNonEmpty Test whether a `string` is non empty. **Signature** ```ts export declare const isNonEmpty: (self: string) => boolean ``` Added in v1.0.0 ## length Calculate the number of characters in a `string`. **Signature** ```ts export declare const length: (self: string) => number ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.length('abc'), 3) ``` Added in v1.0.0 ## replace **Signature** ```ts export declare const replace: { (searchValue: string | RegExp, replaceValue: string): (self: string) => string (self: string, searchValue: string | RegExp, replaceValue: string): string } ``` **Example** ```ts import * as S from '@fp-ts/core/String' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual(pipe('abc', S.replace('b', 'd')), 'adc') ``` Added in v1.0.0 ## slice **Signature** ```ts export declare const slice: { (start: number, end: number): (self: string) => string (self: string, start: number, end: number): string } ``` **Example** ```ts import * as S from '@fp-ts/core/String' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual(pipe('abcd', S.slice(1, 3)), 'bc') ``` Added in v1.0.0 ## split **Signature** ```ts export declare const split: { (separator: string | RegExp): (self: string) => [string, ...string[]] (self: string, separator: string | RegExp): [string, ...string[]] } ``` **Example** ```ts import * as S from '@fp-ts/core/String' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual(pipe('abc', S.split('')), ['a', 'b', 'c']) assert.deepStrictEqual(pipe('', S.split('')), ['']) ``` Added in v1.0.0 ## startsWith Returns `true` if the sequence of elements of `searchString` is the same as the corresponding elements of `s` starting at position. Otherwise returns false. **Signature** ```ts export declare const startsWith: { (searchString: string): (self: string) => boolean (self: string, searchString: string): boolean } ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.startsWith('abc', 'a'), true) assert.deepStrictEqual(S.startsWith('bc', 'a'), false) ``` Added in v1.0.0 ## startsWithPosition **Signature** ```ts export declare const startsWithPosition: { (searchString: string, position: number): (self: string) => boolean (self: string, searchString: string, position: number): boolean } ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.startsWithPosition('abc', 'b', 1), true) assert.deepStrictEqual(S.startsWithPosition('bc', 'a', 1), false) ``` Added in v1.0.0 ## takeLeft Keep the specified number of characters from the start of a string. If `n` is larger than the available number of characters, the string will be returned whole. If `n` is not a positive number, an empty string will be returned. If `n` is a float, it will be rounded down to the nearest integer. **Signature** ```ts export declare const takeLeft: { (n: number): (self: string) => string; (self: string, n: number): string } ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.takeLeft('Hello World', 5), 'Hello') ``` Added in v1.0.0 ## takeRight Keep the specified number of characters from the end of a string. If `n` is larger than the available number of characters, the string will be returned whole. If `n` is not a positive number, an empty string will be returned. If `n` is a float, it will be rounded down to the nearest integer. **Signature** ```ts export declare const takeRight: { (n: number): (self: string) => string; (self: string, n: number): string } ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.takeRight('Hello World', 5), 'World') ``` Added in v1.0.0 ## toLowerCase **Signature** ```ts export declare const toLowerCase: (self: string) => string ``` **Example** ```ts import * as S from '@fp-ts/core/String' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual(pipe('A', S.toLowerCase), 'a') ``` Added in v1.0.0 ## toUpperCase **Signature** ```ts export declare const toUpperCase: (self: string) => string ``` **Example** ```ts import * as S from '@fp-ts/core/String' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual(pipe('a', S.toUpperCase), 'A') ``` Added in v1.0.0 ## trim **Signature** ```ts export declare const trim: (self: string) => string ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.trim(' a '), 'a') ``` Added in v1.0.0 ## trimEnd **Signature** ```ts export declare const trimEnd: (self: string) => string ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.trimEnd(' a '), ' a') ``` Added in v1.0.0 ## trimStart **Signature** ```ts export declare const trimStart: (self: string) => string ``` **Example** ```ts import * as S from '@fp-ts/core/String' assert.deepStrictEqual(S.trimStart(' a '), 'a ') ``` Added in v1.0.0 ================================================ FILE: docs/modules/Struct.ts.md ================================================ --- title: Struct.ts nav_order: 15 parent: Modules --- ## Struct overview This module provides utility functions for working with structs in TypeScript. Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [getEquivalence](#getequivalence) - [getMonoid](#getmonoid) - [getOrder](#getorder) - [getSemigroup](#getsemigroup) - [utils](#utils) - [omit](#omit) - [pick](#pick) --- # combinators ## getEquivalence Given a struct of `Equivalence`s returns a new `Equivalence` that compares values of a struct by applying each `Equivalence` to the corresponding property of the struct. Alias of {@link equivalence.struct}. **Signature** ```ts export declare const getEquivalence: >>( predicates: R ) => equivalence.Equivalence<{ readonly [K in keyof R]: [R[K]] extends [equivalence.Equivalence] ? A : never }> ``` **Example** ```ts import { getEquivalence } from '@fp-ts/core/Struct' import * as S from '@fp-ts/core/String' import * as N from '@fp-ts/core/Number' const PersonEquivalence = getEquivalence({ name: S.Equivalence, age: N.Equivalence, }) assert.deepStrictEqual(PersonEquivalence({ name: 'John', age: 25 }, { name: 'John', age: 25 }), true) assert.deepStrictEqual(PersonEquivalence({ name: 'John', age: 25 }, { name: 'John', age: 40 }), false) ``` Added in v1.0.0 ## getMonoid This function creates and returns a new `Monoid` for a struct of values based on the given `Monoid`s for each property in the struct. The returned `Monoid` combines two structs of the same type by applying the corresponding `Monoid` passed as arguments to each property in the struct. The `empty` value of the returned `Monoid` is a struct where each property is the `empty` value of the corresponding `Monoid` in the input `monoids` object. It is useful when you need to combine two structs of the same type and you have a specific way of combining each property of the struct. See also {@link getSemigroup}. **Signature** ```ts export declare const getMonoid: }>( fields: R ) => monoid.Monoid<{ [K in keyof R]: [R[K]] extends [monoid.Monoid] ? A : never }> ``` Added in v1.0.0 ## getOrder This function creates and returns a new `Order` for a struct of values based on the given `Order`s for each property in the struct. Alias of {@link order.struct}. **Signature** ```ts export declare const getOrder: }>( fields: R ) => order.Order<{ [K in keyof R]: [R[K]] extends [order.Order] ? A : never }> ``` Added in v1.0.0 ## getSemigroup This function creates and returns a new `Semigroup` for a struct of values based on the given `Semigroup`s for each property in the struct. The returned `Semigroup` combines two structs of the same type by applying the corresponding `Semigroup` passed as arguments to each property in the struct. It is useful when you need to combine two structs of the same type and you have a specific way of combining each property of the struct. See also {@link getMonoid}. **Signature** ```ts export declare const getSemigroup: }>( fields: R ) => semigroup.Semigroup<{ [K in keyof R]: [R[K]] extends [semigroup.Semigroup] ? A : never }> ``` **Example** ```ts import { getSemigroup } from '@fp-ts/core/Struct' import * as Semigroup from '@fp-ts/core/typeclass/Semigroup' import * as O from '@fp-ts/core/Option' const PersonSemigroup = getSemigroup({ name: Semigroup.last(), age: O.getOptionalMonoid(Semigroup.last()), }) assert.deepStrictEqual(PersonSemigroup.combine({ name: 'John', age: O.none() }, { name: 'John', age: O.some(25) }), { name: 'John', age: O.some(25), }) assert.deepStrictEqual(PersonSemigroup.combine({ name: 'John', age: O.some(25) }, { name: 'John', age: O.none() }), { name: 'John', age: O.some(25), }) ``` Added in v1.0.0 # utils ## omit Create a new object by omitting properties of an existing object. **Signature** ```ts export declare const omit: ( ...keys: Keys ) => (s: S) => { [K in Exclude]: S[K] } ``` **Example** ```ts import { omit } from '@fp-ts/core/Struct' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual(pipe({ a: 'a', b: 1, c: true }, omit('c')), { a: 'a', b: 1 }) ``` Added in v1.0.0 ## pick Create a new object by picking properties of an existing object. **Signature** ```ts export declare const pick: ( ...keys: Keys ) => (s: S) => { [K in Keys[number]]: S[K] } ``` **Example** ```ts import { pick } from '@fp-ts/core/Struct' import { pipe } from '@fp-ts/core/Function' assert.deepStrictEqual(pipe({ a: 'a', b: 1, c: true }, pick('a', 'b')), { a: 'a', b: 1 }) ``` Added in v1.0.0 ================================================ FILE: docs/modules/Symbol.ts.md ================================================ --- title: Symbol.ts nav_order: 16 parent: Modules --- ## Symbol overview Added in v1.0.0 ---

Table of contents

- [guards](#guards) - [isSymbol](#issymbol) - [instances](#instances) - [Equivalence](#equivalence) --- # guards ## isSymbol Tests if a value is a `symbol`. **Signature** ```ts export declare const isSymbol: (u: unknown) => u is symbol ``` **Example** ```ts import { isSymbol } from '@fp-ts/core/Predicate' assert.deepStrictEqual(isSymbol(Symbol.for('a')), true) assert.deepStrictEqual(isSymbol('a'), false) ``` Added in v1.0.0 # instances ## Equivalence **Signature** ```ts export declare const Equivalence: equivalence.Equivalence ``` Added in v1.0.0 ================================================ FILE: docs/modules/These.ts.md ================================================ --- title: These.ts nav_order: 17 parent: Modules --- ## These overview Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [tap](#tap) - [combining](#combining) - [andThenDiscard](#andthendiscard) - [flatMap](#flatmap) - [flatMapEither](#flatmapeither) - [flatMapNullable](#flatmapnullable) - [flatMapOption](#flatmapoption) - [flatMapThese](#flatmapthese) - [getFirstLeftMonoid](#getfirstleftmonoid) - [getFirstLeftSemigroup](#getfirstleftsemigroup) - [getFirstRightOrBothSemigroup](#getfirstrightorbothsemigroup) - [zipWith](#zipwith) - [constructors](#constructors) - [both](#both) - [fail](#fail) - [left](#left) - [leftOrBoth](#leftorboth) - [of](#of) - [right](#right) - [rightOrBoth](#rightorboth) - [warn](#warn) - [conversions](#conversions) - [absolve](#absolve) - [condemn](#condemn) - [fromEither](#fromeither) - [fromIterable](#fromiterable) - [fromNullable](#fromnullable) - [fromOption](#fromoption) - [fromTuple](#fromtuple) - [toEither](#toeither) - [toValidated](#tovalidated) - [debugging](#debugging) - [inspectBoth](#inspectboth) - [inspectLeft](#inspectleft) - [inspectRight](#inspectright) - [inspectRightOrBoth](#inspectrightorboth) - [do notation](#do-notation) - [Do](#do) - [andThenBind](#andthenbind) - [bind](#bind) - [bindEither](#bindeither) - [bindThese](#bindthese) - [bindTo](#bindto) - [let](#let) - [equivalence](#equivalence) - [getEquivalence](#getequivalence) - [error handling](#error-handling) - [firstRightOrBothOf](#firstrightorbothof) - [mapLeft](#mapleft) - [orElse](#orelse) - [orElseEither](#orelseeither) - [orElseFail](#orelsefail) - [filtering](#filtering) - [compact](#compact) - [filter](#filter) - [filterMap](#filtermap) - [getters](#getters) - [getBoth](#getboth) - [getBothOrElse](#getbothorelse) - [getLeft](#getleft) - [getLeftOnly](#getleftonly) - [getOrElse](#getorelse) - [getOrNull](#getornull) - [getOrUndefined](#getorundefined) - [getRight](#getright) - [getRightOnly](#getrightonly) - [guards](#guards) - [isBoth](#isboth) - [isLeft](#isleft) - [isLeftOrBoth](#isleftorboth) - [isRight](#isright) - [isRightOrBoth](#isrightorboth) - [isThese](#isthese) - [instances](#instances) - [Applicative](#applicative) - [Bicovariant](#bicovariant) - [Chainable](#chainable) - [Covariant](#covariant) - [FlatMap](#flatmap) - [Foldable](#foldable) - [Invariant](#invariant) - [Monad](#monad) - [Of](#of) - [Pointed](#pointed) - [Product](#product) - [SemiAlternative](#semialternative) - [SemiApplicative](#semiapplicative) - [SemiCoproduct](#semicoproduct) - [SemiProduct](#semiproduct) - [Traversable](#traversable) - [interop](#interop) - [getOrThrow](#getorthrow) - [getOrThrowWith](#getorthrowwith) - [getRightOnlyOrThrow](#getrightonlyorthrow) - [getRightOnlyOrThrowWith](#getrightonlyorthrowwith) - [liftThrowable](#liftthrowable) - [lifting](#lifting) - [lift2](#lift2) - [liftEither](#lifteither) - [liftNullable](#liftnullable) - [liftOption](#liftoption) - [liftPredicate](#liftpredicate) - [liftThese](#liftthese) - [mapping](#mapping) - [as](#as) - [asUnit](#asunit) - [bimap](#bimap) - [flap](#flap) - [map](#map) - [tupled](#tupled) - [math](#math) - [divide](#divide) - [multiply](#multiply) - [subtract](#subtract) - [sum](#sum) - [model](#model) - [Both (interface)](#both-interface) - [These (type alias)](#these-type-alias) - [Validated (type alias)](#validated-type-alias) - [pattern matching](#pattern-matching) - [match](#match) - [predicates](#predicates) - [exists](#exists) - [traversing](#traversing) - [sequence](#sequence) - [traverse](#traverse) - [traverseTap](#traversetap) - [type lambdas](#type-lambdas) - [TheseTypeLambda (interface)](#thesetypelambda-interface) - [ValidatedTypeLambda (interface)](#validatedtypelambda-interface) - [utils](#utils) - [andThen](#andthen) - [ap](#ap) - [appendElement](#appendelement) - [composeKleisliArrow](#composekleisliarrow) - [contains](#contains) - [flatten](#flatten) - [reverse](#reverse) - [struct](#struct) - [tuple](#tuple) - [unit](#unit) --- # combinators ## tap Returns an effect that effectfully "peeks" at the success of this effect. **Signature** ```ts export declare const tap: { (self: These, f: (a: A) => These): These< readonly [E1 | E2, ...(E1 | E2)[]], A > (f: (a: A) => These): ( self: These ) => These } ``` Added in v1.0.0 # combining ## andThenDiscard Sequences the specified effect after this effect, but ignores the value produced by the effect. **Signature** ```ts export declare const andThenDiscard: { (self: These, that: These): These< readonly [E1 | E2, ...(E1 | E2)[]], A > (that: These): ( self: These ) => These } ``` Added in v1.0.0 ## flatMap **Signature** ```ts export declare const flatMap: { (f: (a: A) => These): ( self: These ) => These (self: These, f: (a: A) => These): These< readonly [E1 | E2, ...(E1 | E2)[]], B > } ``` Added in v1.0.0 ## flatMapEither **Signature** ```ts export declare const flatMapEither: { (f: (a: A) => Either): ( self: These ) => These (self: These, f: (a: A) => Either): These< readonly [E1 | E2, ...(E1 | E2)[]], B > } ``` Added in v1.0.0 ## flatMapNullable **Signature** ```ts export declare const flatMapNullable: { (f: (a: A) => B | null | undefined, onNullable: (a: A) => E2): ( self: These ) => These> ( self: These, f: (a: A) => B | null | undefined, onNullable: (a: A) => E2 ): These> } ``` Added in v1.0.0 ## flatMapOption **Signature** ```ts export declare const flatMapOption: { (f: (a: A) => O.Option, onNone: (a: A) => E2): ( self: These ) => These (self: These, f: (a: A) => O.Option, onNone: (a: A) => E2): These< readonly [E1 | E2, ...(E1 | E2)[]], B > } ``` Added in v1.0.0 ## flatMapThese **Signature** ```ts export declare const flatMapThese: { (f: (a: A) => These): ( self: These ) => These (self: These, f: (a: A) => These): These< readonly [E1 | E2, ...(E1 | E2)[]], B > } ``` Added in v1.0.0 ## getFirstLeftMonoid **Signature** ```ts export declare const getFirstLeftMonoid: (M: Monoid
) => Monoid> ``` Added in v1.0.0 ## getFirstLeftSemigroup **Signature** ```ts export declare const getFirstLeftSemigroup: (S: Semigroup) => Semigroup> ``` Added in v1.0.0 ## getFirstRightOrBothSemigroup **Signature** ```ts export declare const getFirstRightOrBothSemigroup: () => Semigroup> ``` Added in v1.0.0 ## zipWith **Signature** ```ts export declare const zipWith: { ( self: These, that: These, f: (a: A, b: B) => C ): These (that: These, f: (a: A, b: B) => C): ( self: These ) => These } ``` Added in v1.0.0 # constructors ## both **Signature** ```ts export declare const both: (left: E, right: A) => These ``` Added in v1.0.0 ## fail **Signature** ```ts export declare const fail: (e: E) => These ``` Added in v1.0.0 ## left **Signature** ```ts export declare const left: (left: E) => These ``` Added in v1.0.0 ## leftOrBoth **Signature** ```ts export declare const leftOrBoth: { (onSome: LazyArg): (self: O.Option) => These (self: O.Option, onSome: LazyArg): These } ``` Added in v1.0.0 ## of Alias of {@link right}. **Signature** ```ts export declare const of: (right: A) => These ``` Added in v1.0.0 ## right **Signature** ```ts export declare const right: (right: A) => These ``` Added in v1.0.0 ## rightOrBoth **Signature** ```ts export declare const rightOrBoth: { (onNone: LazyArg): (self: O.Option) => These (self: O.Option, onNone: LazyArg): These } ``` Added in v1.0.0 ## warn **Signature** ```ts export declare const warn: (e: E, a: A) => These ``` Added in v1.0.0 # conversions ## absolve **Signature** ```ts export declare const absolve: (self: These) => Either ``` Added in v1.0.0 ## condemn **Signature** ```ts export declare const condemn: (self: These) => Either ``` Added in v1.0.0 ## fromEither **Signature** ```ts export declare const fromEither: (self: Either) => These ``` Added in v1.0.0 ## fromIterable **Signature** ```ts export declare const fromIterable: { (onEmpty: LazyArg): (collection: Iterable) => These (collection: Iterable, onEmpty: LazyArg): These } ``` Added in v1.0.0 ## fromNullable **Signature** ```ts export declare const fromNullable: { (onNullable: LazyArg): (a: A) => These> (a: A, onNullable: LazyArg): These> } ``` Added in v1.0.0 ## fromOption **Signature** ```ts export declare const fromOption: { (onNone: LazyArg): (self: O.Option) => These (self: O.Option, onNone: LazyArg): These } ``` Added in v1.0.0 ## fromTuple **Signature** ```ts export declare const fromTuple: (self: readonly [E, A]) => These ``` Added in v1.0.0 ## toEither **Signature** ```ts export declare const toEither: { (onBoth: (e: E, a: A) => Either): (self: These) => Either (self: These, onBoth: (e: E, a: A) => Either): Either } ``` Added in v1.0.0 ## toValidated **Signature** ```ts export declare const toValidated: (self: These) => These ``` Added in v1.0.0 # debugging ## inspectBoth **Signature** ```ts export declare const inspectBoth: { (onBoth: (e: E, a: A) => void): (self: These) => These (self: These, onBoth: (e: E, a: A) => void): These } ``` Added in v1.0.0 ## inspectLeft **Signature** ```ts export declare const inspectLeft: { (onLeft: (e: E) => void): (self: These) => These (self: These, onLeft: (e: E) => void): These } ``` Added in v1.0.0 ## inspectRight **Signature** ```ts export declare const inspectRight: { (onRight: (a: A) => void): (self: These) => These (self: These, onRight: (a: A) => void): These } ``` Added in v1.0.0 ## inspectRightOrBoth **Signature** ```ts export declare const inspectRightOrBoth: { (onRightOrBoth: (a: A) => void): (self: These) => These (self: These, onRightOrBoth: (a: A) => void): These } ``` Added in v1.0.0 # do notation ## Do **Signature** ```ts export declare const Do: These ``` Added in v1.0.0 ## andThenBind **Signature** ```ts export declare const andThenBind: { (name: Exclude, that: These): ( self: These ) => These ( self: These, name: Exclude, that: These ): These } ``` Added in v1.0.0 ## bind **Signature** ```ts export declare const bind: { ( name: Exclude, f: (a: A) => These ): ( self: These ) => These ( self: These, name: Exclude, f: (a: A) => These ): These } ``` Added in v1.0.0 ## bindEither **Signature** ```ts export declare const bindEither: { (name: Exclude, f: (a: A) => Either): ( self: These ) => These ( self: These, name: Exclude, f: (a: A) => Either ): These } ``` Added in v1.0.0 ## bindThese **Signature** ```ts export declare const bindThese: { (name: Exclude, f: (a: A) => These): ( self: These ) => These ( self: These, name: Exclude, f: (a: A) => These ): These } ``` Added in v1.0.0 ## bindTo **Signature** ```ts export declare const bindTo: { (name: N): (self: These) => These (self: These, name: N): These } ``` Added in v1.0.0 ## let **Signature** ```ts export declare const let: { (name: Exclude, f: (a: A) => B): ( self: These ) => These (self: These, name: Exclude, f: (a: A) => B): These< E, { [K in N | keyof A]: K extends keyof A ? A[K] : B } > } ``` Added in v1.0.0 # equivalence ## getEquivalence **Signature** ```ts export declare const getEquivalence: (EE: Equivalence, EA: Equivalence) => Equivalence> ``` Added in v1.0.0 # error handling ## firstRightOrBothOf **Signature** ```ts export declare const firstRightOrBothOf: { (collection: Iterable>): (self: These) => These (self: These, collection: Iterable>): These } ``` Added in v1.0.0 ## mapLeft Maps the `Left` side of an `These` value to a new `These` value. **Signature** ```ts export declare const mapLeft: { (f: (e: E) => G): (self: These) => These (self: These, f: (e: E) => G): These } ``` Added in v1.0.0 ## orElse Executes this effect and returns its value, if it succeeds, but otherwise executes the specified effect. **Signature** ```ts export declare const orElse: { (that: (e1: E1) => These): (self: These) => These (self: These, that: (e1: E1) => These): These } ``` Added in v1.0.0 ## orElseEither Returns an effect that will produce the value of this effect, unless it fails, in which case, it will produce the value of the specified effect. **Signature** ```ts export declare const orElseEither: { (that: (e1: E1) => These): (self: These) => These> (self: These, that: (e1: E1) => These): These> } ``` Added in v1.0.0 ## orElseFail Executes this effect and returns its value, if it succeeds, but otherwise fails with the specified error. **Signature** ```ts export declare const orElseFail: { (onLeft: LazyArg): (self: These) => These (self: These, onLeft: LazyArg): These } ``` Added in v1.0.0 # filtering ## compact **Signature** ```ts export declare const compact: { (onNone: LazyArg): (self: These>) => These (self: These>, onNone: LazyArg): These } ``` Added in v1.0.0 ## filter **Signature** ```ts export declare const filter: { (refinement: Refinement, onFalse: LazyArg): ( self: These ) => These (predicate: Predicate, onFalse: LazyArg): (self: These) => These ( self: These, refinement: Refinement, onFalse: LazyArg ): These (self: These, predicate: Predicate, onFalse: LazyArg): These } ``` Added in v1.0.0 ## filterMap **Signature** ```ts export declare const filterMap: { (f: (a: A) => O.Option, onNone: LazyArg): (self: These) => These (self: These, f: (a: A) => O.Option, onNone: LazyArg): These } ``` Added in v1.0.0 # getters ## getBoth **Signature** ```ts export declare const getBoth: (self: These) => O.Option ``` Added in v1.0.0 ## getBothOrElse **Signature** ```ts export declare const getBothOrElse: { (e: LazyArg, a: LazyArg): (self: These) => [E, A] (self: These, e: LazyArg, a: LazyArg): [E, A] } ``` Added in v1.0.0 ## getLeft Converts a `These` to an `Option` discarding the value (`Both` included). **Signature** ```ts export declare const getLeft: (self: These) => O.Option ``` Added in v1.0.0 ## getLeftOnly Returns the error if and only if the value is a `Left` (i.e. `Both` is excluded). **Signature** ```ts export declare const getLeftOnly: (self: These) => O.Option ``` Added in v1.0.0 ## getOrElse **Signature** ```ts export declare const getOrElse: { (onLeft: LazyArg): (self: These) => B | A (self: These, onLeft: LazyArg): A | B } ``` Added in v1.0.0 ## getOrNull **Signature** ```ts export declare const getOrNull: (self: These) => A | null ``` Added in v1.0.0 ## getOrUndefined **Signature** ```ts export declare const getOrUndefined: (self: These) => A | undefined ``` Added in v1.0.0 ## getRight Converts a `These` to an `Option` discarding the error (`Both` included). **Signature** ```ts export declare const getRight: (self: These) => O.Option ``` Added in v1.0.0 ## getRightOnly Returns the value if and only if the value is a `Right` (i.e. `Both` is excluded). **Signature** ```ts export declare const getRightOnly: (self: These) => O.Option ``` Added in v1.0.0 # guards ## isBoth Determine if a `These` is a `Both`. **Signature** ```ts export declare const isBoth: (self: These) => self is Both ``` **Example** ```ts import { isBoth, left, right, both } from '@fp-ts/core/These' assert.deepStrictEqual(isBoth(right(1)), false) assert.deepStrictEqual(isBoth(left('error')), false) assert.deepStrictEqual(isBoth(both('error', 1)), true) ``` Added in v1.0.0 ## isLeft Determine if a `These` is a `Left`. **Signature** ```ts export declare const isLeft: (self: These) => self is Left ``` **Example** ```ts import { isLeft, left, right, both } from '@fp-ts/core/These' assert.deepStrictEqual(isLeft(right(1)), false) assert.deepStrictEqual(isLeft(left('error')), true) assert.deepStrictEqual(isLeft(both('error', 1)), false) ``` Added in v1.0.0 ## isLeftOrBoth Determine if a `These` is a `Left` or a `Both`. **Signature** ```ts export declare const isLeftOrBoth: (self: These) => self is Left | Both ``` **Example** ```ts import { isLeftOrBoth, left, right, both } from '@fp-ts/core/These' assert.deepStrictEqual(isLeftOrBoth(right(1)), false) assert.deepStrictEqual(isLeftOrBoth(left('error')), true) assert.deepStrictEqual(isLeftOrBoth(both('error', 1)), true) ``` Added in v1.0.0 ## isRight Determine if a `These` is a `Right`. **Signature** ```ts export declare const isRight: (self: These) => self is Right ``` **Example** ```ts import { isRight, left, right, both } from '@fp-ts/core/These' assert.deepStrictEqual(isRight(right(1)), true) assert.deepStrictEqual(isRight(left('error')), false) assert.deepStrictEqual(isRight(both('error', 1)), false) ``` Added in v1.0.0 ## isRightOrBoth Determine if a `These` is a `Right` or a `Both`. **Signature** ```ts export declare const isRightOrBoth: (self: These) => self is Right | Both ``` **Example** ```ts import { isRightOrBoth, left, right, both } from '@fp-ts/core/These' assert.deepStrictEqual(isRightOrBoth(right(1)), true) assert.deepStrictEqual(isRightOrBoth(left('error')), false) assert.deepStrictEqual(isRightOrBoth(both('error', 1)), true) ``` Added in v1.0.0 ## isThese Tests if a value is a `These`. **Signature** ```ts export declare const isThese: (input: unknown) => input is These ``` Added in v1.0.0 # instances ## Applicative **Signature** ```ts export declare const Applicative: applicative.Applicative ``` Added in v1.0.0 ## Bicovariant **Signature** ```ts export declare const Bicovariant: bicovariant.Bicovariant ``` Added in v1.0.0 ## Chainable **Signature** ```ts export declare const Chainable: chainable.Chainable ``` Added in v1.0.0 ## Covariant **Signature** ```ts export declare const Covariant: covariant.Covariant ``` Added in v1.0.0 ## FlatMap **Signature** ```ts export declare const FlatMap: flatMap_.FlatMap ``` Added in v1.0.0 ## Foldable **Signature** ```ts export declare const Foldable: foldable.Foldable ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Monad **Signature** ```ts export declare const Monad: monad.Monad ``` Added in v1.0.0 ## Of **Signature** ```ts export declare const Of: of_.Of ``` Added in v1.0.0 ## Pointed **Signature** ```ts export declare const Pointed: pointed.Pointed ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiAlternative **Signature** ```ts export declare const SemiAlternative: semiAlternative.SemiAlternative ``` Added in v1.0.0 ## SemiApplicative **Signature** ```ts export declare const SemiApplicative: semiApplicative.SemiApplicative ``` Added in v1.0.0 ## SemiCoproduct **Signature** ```ts export declare const SemiCoproduct: semiCoproduct.SemiCoproduct ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## Traversable **Signature** ```ts export declare const Traversable: traversable.Traversable ``` Added in v1.0.0 # interop ## getOrThrow Extracts the value of a `These` or throws if the `These` is `Left`. The thrown error is a default error. To configure the error thrown, see {@link getOrThrowWith}. **Signature** ```ts export declare const getOrThrow: (self: These) => A ``` **Example** ```ts import * as T from '@fp-ts/core/These' assert.deepStrictEqual(T.getOrThrow(T.right(1)), 1) assert.deepStrictEqual(T.getOrThrow(T.both('warning', 1)), 1) assert.throws(() => T.getOrThrow(T.left('error'))) ``` Added in v1.0.0 ## getOrThrowWith Extracts the value of a `These` or throws if the `These` is `Left`. If a default error is sufficient for your use case and you don't need to configure the thrown error, see {@link getOrThrow}. **Signature** ```ts export declare const getOrThrowWith: { (onLeft: (e: E) => unknown): (self: These) => A (self: These, onLeft: (e: E) => unknown): A } ``` **Example** ```ts import * as E from '@fp-ts/core/These' assert.deepStrictEqual( E.getOrThrowWith(E.right(1), () => new Error('Unexpected Left')), 1 ) assert.deepStrictEqual( E.getOrThrowWith(E.both('warning', 1), () => new Error('Unexpected Left')), 1 ) assert.throws(() => E.getOrThrowWith(E.left('error'), () => new Error('Unexpected Left'))) ``` Added in v1.0.0 ## getRightOnlyOrThrow Extracts the value of a `These` or throws if the `These` is not a `Right`. The thrown error is a default error. To configure the error thrown, see {@link getRightOnlyOrThrowWith}. **Signature** ```ts export declare const getRightOnlyOrThrow: (self: These) => A ``` **Example** ```ts import * as T from '@fp-ts/core/These' assert.deepStrictEqual(T.getRightOnlyOrThrow(T.right(1)), 1) assert.throws(() => T.getRightOnlyOrThrow(T.both('error', 1))) assert.throws(() => T.getRightOnlyOrThrow(T.left('error'))) ``` Added in v1.0.0 ## getRightOnlyOrThrowWith Extracts the value of a `These` or throws if the `These` is `Left`. If a default error is sufficient for your use case and you don't need to configure the thrown error, see {@link getOrThrow}. **Signature** ```ts export declare const getRightOnlyOrThrowWith: { (onLeftOrBoth: (e: E) => unknown): (self: These) => A (self: These, onLeftOrBoth: (e: E) => unknown): A } ``` **Example** ```ts import * as E from '@fp-ts/core/These' assert.deepStrictEqual( E.getRightOnlyOrThrowWith(E.right(1), () => new Error('Unexpected Left or Both')), 1 ) assert.throws(() => E.getRightOnlyOrThrowWith(E.both('warning', 1), () => new Error('Unexpected Left or Both'))) assert.throws(() => E.getRightOnlyOrThrowWith(E.left('error'), () => new Error('Unexpected Left or Both'))) ``` Added in v1.0.0 ## liftThrowable Lifts a function that may throw to one returning a `These`. **Signature** ```ts export declare const liftThrowable: ( f: (...a: A) => B, onThrow: (error: unknown) => E ) => (...a: A) => These ``` Added in v1.0.0 # lifting ## lift2 Lifts a binary function into `These`. **Signature** ```ts export declare const lift2: ( f: (a: A, b: B) => C ) => { (self: These, that: These): These< readonly [E1 | E2, ...(E1 | E2)[]], C > (that: These): ( self: These ) => These } ``` Added in v1.0.0 ## liftEither **Signature** ```ts export declare const liftEither: ( f: (...a: A) => Either ) => (...a: A) => These ``` Added in v1.0.0 ## liftNullable **Signature** ```ts export declare const liftNullable: ( f: (...a: A) => B | null | undefined, onNullable: (...a: A) => E ) => (...a: A) => These> ``` Added in v1.0.0 ## liftOption **Signature** ```ts export declare const liftOption: ( f: (...a: A) => O.Option, onNone: (...a: A) => E ) => (...a: A) => These ``` Added in v1.0.0 ## liftPredicate **Signature** ```ts export declare const liftPredicate: { (refinement: Refinement, onFalse: (c: C) => E): (c: C) => These (predicate: Predicate, onFalse: (b: B) => E): (b: B) => These } ``` Added in v1.0.0 ## liftThese **Signature** ```ts export declare const liftThese: ( f: (...a: A) => These ) => (...a: A) => These ``` Added in v1.0.0 # mapping ## as Maps the right value of this effect to the specified constant value. **Signature** ```ts export declare const as: { (self: These, b: B): These (b: B): (self: These) => These } ``` Added in v1.0.0 ## asUnit Returns the effect resulting from mapping the right of this effect to unit. **Signature** ```ts export declare const asUnit: (self: These) => These ``` Added in v1.0.0 ## bimap **Signature** ```ts export declare const bimap: { (f: (e: E1) => E2, g: (a: A) => B): (self: These) => These (self: These, f: (e: E1) => E2, g: (a: A) => B): These } ``` Added in v1.0.0 ## flap **Signature** ```ts export declare const flap: { (a: A, self: These B>): These (self: These B>): (a: A) => These } ``` Added in v1.0.0 ## map Maps the `Right` side of an `These` value to a new `These` value. **Signature** ```ts export declare const map: { (self: These, f: (a: A) => B): These (f: (a: A) => B): (self: These) => These } ``` Added in v1.0.0 ## tupled **Signature** ```ts export declare const tupled: (self: These) => These ``` Added in v1.0.0 # math ## divide **Signature** ```ts export declare const divide: { (self: These, that: These): These< readonly [E1 | E2, ...(E1 | E2)[]], number > (that: These): ( self: These ) => These } ``` Added in v1.0.0 ## multiply **Signature** ```ts export declare const multiply: { (self: These, that: These): These< readonly [E1 | E2, ...(E1 | E2)[]], number > (that: These): ( self: These ) => These } ``` Added in v1.0.0 ## subtract **Signature** ```ts export declare const subtract: { (self: These, that: These): These< readonly [E1 | E2, ...(E1 | E2)[]], number > (that: These): ( self: These ) => These } ``` Added in v1.0.0 ## sum **Signature** ```ts export declare const sum: { (self: These, that: These): These< readonly [E1 | E2, ...(E1 | E2)[]], number > (that: These): ( self: These ) => These } ``` Added in v1.0.0 # model ## Both (interface) **Signature** ```ts export interface Both { readonly _tag: 'Both' readonly left: E readonly right: A } ``` Added in v1.0.0 ## These (type alias) **Signature** ```ts export type These = Either | Both ``` Added in v1.0.0 ## Validated (type alias) **Signature** ```ts export type Validated = These, A> ``` Added in v1.0.0 # pattern matching ## match **Signature** ```ts export declare const match: { (onLeft: (e: E) => B, onRight: (a: A) => C, onBoth: (e: E, a: A) => D): ( self: These ) => B | C | D (self: These, onLeft: (e: E) => B, onRight: (a: A) => C, onBoth: (e: E, a: A) => D): | B | C | D } ``` Added in v1.0.0 # predicates ## exists **Signature** ```ts export declare const exists: { (predicate: Predicate): (self: These) => boolean (self: These, predicate: Predicate): boolean } ``` Added in v1.0.0 # traversing ## sequence **Signature** ```ts export declare const sequence: ( F: applicative.Applicative ) => (self: These>) => Kind> ``` Added in v1.0.0 ## traverse **Signature** ```ts export declare const traverse: ( F: applicative.Applicative ) => { (f: (a: A) => Kind): (self: These) => Kind> (self: These, f: (a: A) => Kind): Kind> } ``` Added in v1.0.0 ## traverseTap **Signature** ```ts export declare const traverseTap: ( F: applicative.Applicative ) => { (self: These, f: (a: A) => Kind): Kind> (f: (a: A) => Kind): (self: These) => Kind> } ``` Added in v1.0.0 # type lambdas ## TheseTypeLambda (interface) **Signature** ```ts export interface TheseTypeLambda extends TypeLambda { readonly type: These } ``` Added in v1.0.0 ## ValidatedTypeLambda (interface) **Signature** ```ts export interface ValidatedTypeLambda extends TypeLambda { readonly type: Validated } ``` Added in v3.0.0 # utils ## andThen **Signature** ```ts export declare const andThen: { (self: These, that: These): These< readonly [E1 | E2, ...(E1 | E2)[]], B > (that: These): ( self: These ) => These } ``` Added in v1.0.0 ## ap **Signature** ```ts export declare const ap: { (self: These B>, that: These): These< readonly [E1 | E2, ...(E1 | E2)[]], B > (that: These): ( self: These B> ) => These } ``` Added in v1.0.0 ## appendElement Appends an element to the end of a tuple. **Signature** ```ts export declare const appendElement: { ( self: These, that: These ): These (that: These): ( self: These ) => These } ``` Added in v1.0.0 ## composeKleisliArrow **Signature** ```ts export declare const composeKleisliArrow: { (afb: (a: A) => These, bfc: (b: B) => These): ( a: A ) => These (bfc: (b: B) => These): ( afb: (a: A) => These ) => (a: A) => These } ``` Added in v1.0.0 ## contains Returns a function that checks if a `These` contains a given value using a provided `equivalence` function. **Signature** ```ts export declare const contains: (isEquivalent: (self: A, that: A) => boolean) => { (a: A): (self: These) => boolean (self: These, a: A): boolean } ``` Added in v1.0.0 ## flatten **Signature** ```ts export declare const flatten: ( self: These> ) => These ``` Added in v1.0.0 ## reverse **Signature** ```ts export declare const reverse: (self: These) => These ``` Added in v1.0.0 ## struct **Signature** ```ts export declare const struct: >>( r: R ) => These< readonly [ [R[keyof R]] extends [These] ? E : never, ...([R[keyof R]] extends [These] ? E : never)[] ], { [K in keyof R]: [R[K]] extends [These] ? A : never } > ``` Added in v1.0.0 ## tuple Similar to `Promise.all` but operates on `These`s. ``` [These, These, ...] -> These ``` **Signature** ```ts export declare const tuple: []>( ...tuple: T ) => These< readonly [ [T[number]] extends [These] ? E : never, ...([T[number]] extends [These] ? E : never)[] ], { [I in keyof T]: [T[I]] extends [These] ? A : never } > ``` Added in v1.0.0 ## unit **Signature** ```ts export declare const unit: These ``` Added in v1.0.0 ================================================ FILE: docs/modules/Tuple.ts.md ================================================ --- title: Tuple.ts nav_order: 18 parent: Modules --- ## Tuple overview This module provides utility functions for working with tuples in TypeScript. Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [getEquivalence](#getequivalence) - [getMonoid](#getmonoid) - [getOrder](#getorder) - [getSemigroup](#getsemigroup) - [constructors](#constructors) - [tuple](#tuple) - [getters](#getters) - [getFirst](#getfirst) - [getSecond](#getsecond) - [instances](#instances) - [Bicovariant](#bicovariant) - [mapping](#mapping) - [bimap](#bimap) - [mapFirst](#mapfirst) - [mapSecond](#mapsecond) - [type lambdas](#type-lambdas) - [TupleTypeLambda (interface)](#tupletypelambda-interface) - [utils](#utils) - [appendElement](#appendelement) - [swap](#swap) --- # combinators ## getEquivalence Given a tuple of `Equivalence`s returns a new `Equivalence` that compares values of a tuple by applying each `Equivalence` to the corresponding element of the tuple. **Signature** ```ts export declare const getEquivalence: []>( ...predicates: T ) => equivalence.Equivalence< Readonly<{ [I in keyof T]: [T[I]] extends [equivalence.Equivalence] ? A : never }> > ``` Added in v1.0.0 ## getMonoid This function creates and returns a new `Monoid` for a tuple of values based on the given `Monoid`s for each element in the tuple. The returned `Monoid` combines two tuples of the same type by applying the corresponding `Monoid` passed as arguments to each element in the tuple. The `empty` value of the returned `Monoid` is the tuple of `empty` values of the input `Monoid`s. It is useful when you need to combine two tuples of the same type and you have a specific way of combining each element of the tuple. **Signature** ```ts export declare const getMonoid: []>( ...elements: T ) => monoid.Monoid<{ readonly [I in keyof T]: [T[I]] extends [monoid.Monoid] ? A : never }> ``` Added in v1.0.0 ## getOrder This function creates and returns a new `Order` for a tuple of values based on the given `Order`s for each element in the tuple. The returned `Order` compares two tuples of the same type by applying the corresponding `Order` to each element in the tuple. It is useful when you need to compare two tuples of the same type and you have a specific way of comparing each element of the tuple. **Signature** ```ts export declare const getOrder: []>( ...elements: T ) => order.Order<{ [I in keyof T]: [T[I]] extends [order.Order] ? A : never }> ``` Added in v1.0.0 ## getSemigroup This function creates and returns a new `Semigroup` for a tuple of values based on the given `Semigroup`s for each element in the tuple. The returned `Semigroup` combines two tuples of the same type by applying the corresponding `Semigroup` passed as arguments to each element in the tuple. It is useful when you need to combine two tuples of the same type and you have a specific way of combining each element of the tuple. **Signature** ```ts export declare const getSemigroup: []>( ...elements: T ) => semigroup.Semigroup<{ readonly [I in keyof T]: [T[I]] extends [semigroup.Semigroup] ? A : never }> ``` Added in v1.0.0 # constructors ## tuple Constructs a new tuple from the provided values. **Signature** ```ts export declare const tuple:
(...elements: A) => A ``` **Example** ```ts import { tuple } from '@fp-ts/core/Tuple' assert.deepStrictEqual(tuple(1, 'hello', true), [1, 'hello', true]) ``` Added in v1.0.0 # getters ## getFirst Return the first element of a tuple. **Signature** ```ts export declare const getFirst: (self: readonly [L, R]) => L ``` **Example** ```ts import { getFirst } from '@fp-ts/core/Tuple' assert.deepStrictEqual(getFirst(['hello', 42]), 'hello') ``` Added in v1.0.0 ## getSecond Return the second element of a tuple. **Signature** ```ts export declare const getSecond: (self: readonly [L, R]) => R ``` **Example** ```ts import { getSecond } from '@fp-ts/core/Tuple' assert.deepStrictEqual(getSecond(['hello', 42]), 42) ``` Added in v1.0.0 # instances ## Bicovariant **Signature** ```ts export declare const Bicovariant: bicovariant.Bicovariant ``` Added in v1.0.0 # mapping ## bimap Transforms both elements of a tuple using the given functions. **Signature** ```ts export declare const bimap: { (f: (e: L1) => L2, g: (a: R1) => R2): (self: readonly [L1, R1]) => [L2, R2] (self: readonly [L1, R1], f: (e: L1) => L2, g: (a: R1) => R2): [L2, R2] } ``` **Example** ```ts import { bimap } from '@fp-ts/core/Tuple' assert.deepStrictEqual( bimap( ['hello', 42], (s) => s.toUpperCase(), (n) => n.toString() ), ['HELLO', '42'] ) ``` Added in v1.0.0 ## mapFirst Transforms the first component of a tuple using a given function. **Signature** ```ts export declare const mapFirst: { (f: (left: L1) => L2): (self: readonly [L1, R]) => [L2, R] (self: readonly [L1, R], f: (left: L1) => L2): [L2, R] } ``` **Example** ```ts import { mapFirst } from '@fp-ts/core/Tuple' assert.deepStrictEqual( mapFirst(['hello', 42], (s) => s.toUpperCase()), ['HELLO', 42] ) ``` Added in v1.0.0 ## mapSecond Transforms the second component of a tuple using a given function. **Signature** ```ts export declare const mapSecond: { (f: (right: R1) => R2): (self: readonly [L, R1]) => [L, R2] (self: readonly [L, R1], f: (right: R1) => R2): [L, R2] } ``` **Example** ```ts import { mapSecond } from '@fp-ts/core/Tuple' assert.deepStrictEqual( mapSecond(['hello', 42], (n) => n.toString()), ['hello', '42'] ) ``` Added in v1.0.0 # type lambdas ## TupleTypeLambda (interface) **Signature** ```ts export interface TupleTypeLambda extends TypeLambda { readonly type: [this['Out1'], this['Target']] } ``` Added in v1.0.0 # utils ## appendElement Appends an element to the end of a tuple. **Signature** ```ts export declare const appendElement: { (that: B): (self: A) => [...A, B] (self: A, that: B): [...A, B] } ``` Added in v1.0.0 ## swap Swaps the two elements of a tuple. **Signature** ```ts export declare const swap: (self: readonly [L, R]) => [R, L] ``` **Example** ```ts import { swap } from '@fp-ts/core/Tuple' assert.deepStrictEqual(swap(['hello', 42]), [42, 'hello']) ``` Added in v1.0.0 ================================================ FILE: docs/modules/index.md ================================================ --- title: Modules has_children: true permalink: /docs/modules nav_order: 2 --- ================================================ FILE: docs/modules/index.ts.md ================================================ --- title: index.ts nav_order: 7 parent: Modules --- ## index overview Added in v1.0.0 ---

Table of contents

- [typeclass](#typeclass) - [alternative](#alternative) - [applicative](#applicative) - [bicovariant](#bicovariant) - [bounded](#bounded) - [chainable](#chainable) - [contravariant](#contravariant) - [coproduct](#coproduct) - [covariant](#covariant) - [equivalence](#equivalence) - [filterable](#filterable) - [flatMap](#flatmap) - [foldable](#foldable) - [invariant](#invariant) - [monad](#monad) - [monoid](#monoid) - [of](#of) - [order](#order) - [pointed](#pointed) - [product](#product) - [semiAlternative](#semialternative) - [semiApplicative](#semiapplicative) - [semiCoproduct](#semicoproduct) - [semiProduct](#semiproduct) - [semigroup](#semigroup) - [traversable](#traversable) - [traversableFilterable](#traversablefilterable) - [utils](#utils) - [bigint](#bigint) - [boolean](#boolean) - [either](#either) - [function](#function) - [hkt](#hkt) - [identity](#identity) - [number](#number) - [option](#option) - [ordering](#ordering) - [predicate](#predicate) - [readonlyArray](#readonlyarray) - [readonlyRecord](#readonlyrecord) - [string](#string) - [struct](#struct) - [symbol](#symbol) - [these](#these) - [tuple](#tuple) --- # typeclass ## alternative **Signature** ```ts export declare const alternative: typeof alternative ``` Added in v1.0.0 ## applicative **Signature** ```ts export declare const applicative: typeof applicative ``` Added in v1.0.0 ## bicovariant **Signature** ```ts export declare const bicovariant: typeof bicovariant ``` Added in v1.0.0 ## bounded **Signature** ```ts export declare const bounded: typeof bounded ``` Added in v1.0.0 ## chainable **Signature** ```ts export declare const chainable: typeof chainable ``` Added in v1.0.0 ## contravariant **Signature** ```ts export declare const contravariant: typeof contravariant ``` Added in v1.0.0 ## coproduct **Signature** ```ts export declare const coproduct: typeof coproduct ``` Added in v1.0.0 ## covariant **Signature** ```ts export declare const covariant: typeof covariant ``` Added in v1.0.0 ## equivalence **Signature** ```ts export declare const equivalence: typeof equivalence ``` Added in v1.0.0 ## filterable **Signature** ```ts export declare const filterable: typeof filterable ``` Added in v1.0.0 ## flatMap **Signature** ```ts export declare const flatMap: typeof flatMap ``` Added in v1.0.0 ## foldable **Signature** ```ts export declare const foldable: typeof foldable ``` Added in v1.0.0 ## invariant **Signature** ```ts export declare const invariant: typeof invariant ``` Added in v1.0.0 ## monad **Signature** ```ts export declare const monad: typeof monad ``` Added in v1.0.0 ## monoid **Signature** ```ts export declare const monoid: typeof monoid ``` Added in v1.0.0 ## of **Signature** ```ts export declare const of: typeof of ``` Added in v1.0.0 ## order **Signature** ```ts export declare const order: typeof order ``` Added in v1.0.0 ## pointed **Signature** ```ts export declare const pointed: typeof pointed ``` Added in v1.0.0 ## product **Signature** ```ts export declare const product: typeof product ``` Added in v1.0.0 ## semiAlternative **Signature** ```ts export declare const semiAlternative: typeof semiAlternative ``` Added in v1.0.0 ## semiApplicative **Signature** ```ts export declare const semiApplicative: typeof semiApplicative ``` Added in v1.0.0 ## semiCoproduct **Signature** ```ts export declare const semiCoproduct: typeof semiCoproduct ``` Added in v1.0.0 ## semiProduct **Signature** ```ts export declare const semiProduct: typeof semiProduct ``` Added in v1.0.0 ## semigroup **Signature** ```ts export declare const semigroup: typeof semigroup ``` Added in v1.0.0 ## traversable **Signature** ```ts export declare const traversable: typeof traversable ``` Added in v1.0.0 ## traversableFilterable **Signature** ```ts export declare const traversableFilterable: typeof traversableFilterable ``` Added in v1.0.0 # utils ## bigint **Signature** ```ts export declare const bigint: typeof bigint ``` Added in v1.0.0 ## boolean **Signature** ```ts export declare const boolean: typeof boolean ``` Added in v1.0.0 ## either **Signature** ```ts export declare const either: typeof either ``` Added in v1.0.0 ## function **Signature** ```ts export declare const function: typeof _function ``` Added in v1.0.0 ## hkt **Signature** ```ts export declare const hkt: typeof hkt ``` Added in v1.0.0 ## identity **Signature** ```ts export declare const identity: typeof identity ``` Added in v1.0.0 ## number **Signature** ```ts export declare const number: typeof number ``` Added in v1.0.0 ## option **Signature** ```ts export declare const option: typeof option ``` Added in v1.0.0 ## ordering **Signature** ```ts export declare const ordering: typeof ordering ``` Added in v1.0.0 ## predicate **Signature** ```ts export declare const predicate: typeof predicate ``` Added in v1.0.0 ## readonlyArray **Signature** ```ts export declare const readonlyArray: typeof readonlyArray ``` Added in v1.0.0 ## readonlyRecord **Signature** ```ts export declare const readonlyRecord: typeof readonlyRecord ``` Added in v1.0.0 ## string **Signature** ```ts export declare const string: typeof string ``` Added in v1.0.0 ## struct **Signature** ```ts export declare const struct: typeof struct ``` Added in v1.0.0 ## symbol **Signature** ```ts export declare const symbol: typeof symbol ``` Added in v1.0.0 ## these **Signature** ```ts export declare const these: typeof these ``` Added in v1.0.0 ## tuple **Signature** ```ts export declare const tuple: typeof tuple ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Alternative.ts.md ================================================ --- title: typeclass/Alternative.ts nav_order: 19 parent: Modules --- ## Alternative overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Alternative (interface)](#alternative-interface) --- # type class ## Alternative (interface) **Signature** ```ts export interface Alternative extends SemiAlternative, Coproduct {} ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Applicative.ts.md ================================================ --- title: typeclass/Applicative.ts nav_order: 20 parent: Modules --- ## Applicative overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Applicative (interface)](#applicative-interface) - [utils](#utils) - [getMonoid](#getmonoid) --- # type class ## Applicative (interface) **Signature** ```ts export interface Applicative extends SemiApplicative, Product {} ``` Added in v1.0.0 # utils ## getMonoid Lift a `Monoid` into `F`, combining the inner values using the provided `Monoid`: - `combine` is provided by {@link semiApplicative.getSemigroup}. - `empty` is `F.of(M.empty)` **Signature** ```ts export declare const getMonoid: ( F: Applicative ) => (M: Monoid
) => Monoid> ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Bicovariant.ts.md ================================================ --- title: typeclass/Bicovariant.ts nav_order: 21 parent: Modules --- ## Bicovariant overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Bicovariant (interface)](#bicovariant-interface) - [utils](#utils) - [bimapComposition](#bimapcomposition) - [map](#map) - [mapLeft](#mapleft) --- # type class ## Bicovariant (interface) **Signature** ```ts export interface Bicovariant extends TypeClass { readonly bimap: { (f: (e: E1) => E2, g: (a: A) => B): (self: Kind) => Kind (self: Kind, f: (e: E1) => E2, g: (a: A) => B): Kind } } ``` Added in v1.0.0 # utils ## bimapComposition Returns a default ternary `bimap` composition. **Signature** ```ts export declare const bimapComposition: ( CovariantF: Covariant, BicovariantG: Bicovariant ) => ( self: Kind>, f: (e: E1) => E2, g: (a: A) => B ) => Kind> ``` Added in v1.0.0 ## map Returns a default `map` implementation. **Signature** ```ts export declare const map: ( F: Bicovariant ) => { (f: (a: A) => B): (self: Kind) => Kind (self: Kind, f: (a: A) => B): Kind } ``` Added in v1.0.0 ## mapLeft Returns a default `mapLeft` implementation. **Signature** ```ts export declare const mapLeft: ( F: Bicovariant ) => { (f: (e: E) => G): (self: Kind) => Kind (self: Kind, f: (e: E) => G): Kind } ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Bounded.ts.md ================================================ --- title: typeclass/Bounded.ts nav_order: 22 parent: Modules --- ## Bounded overview Added in v1.0.0 ---

Table of contents

- [constructors](#constructors) - [max](#max) - [min](#min) - [instances](#instances) - [number](#number) - [type class](#type-class) - [Bounded (interface)](#bounded-interface) - [type lambdas](#type-lambdas) - [BoundedTypeLambda (interface)](#boundedtypelambda-interface) - [utils](#utils) - [clamp](#clamp) - [reverse](#reverse) --- # constructors ## max `Monoid` that returns last maximum of elements. **Signature** ```ts export declare const max:
(B: Bounded) => Monoid ``` Added in v1.0.0 ## min `Monoid` that returns last minimum of elements. **Signature** ```ts export declare const min: (B: Bounded) => Monoid ``` Added in v1.0.0 # instances ## number **Signature** ```ts export declare const number: Bounded ``` Added in v1.0.0 # type class ## Bounded (interface) **Signature** ```ts export interface Bounded extends Order { readonly maxBound: A readonly minBound: A } ``` Added in v1.0.0 # type lambdas ## BoundedTypeLambda (interface) **Signature** ```ts export interface BoundedTypeLambda extends TypeLambda { readonly type: Bounded } ``` Added in v1.0.0 # utils ## clamp Clamp a value between `minBound` and `maxBound` values. **Signature** ```ts export declare const clamp: (B: Bounded) => (a: A) => A ``` Added in v1.0.0 ## reverse Reverses the `Order` of a `Bounded` and flips `maxBound` and `minBound` values. **Signature** ```ts export declare const reverse: (B: Bounded) => Bounded ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Chainable.ts.md ================================================ --- title: typeclass/Chainable.ts nav_order: 23 parent: Modules --- ## Chainable overview Added in v1.0.0 ---

Table of contents

- [combining](#combining) - [andThenDiscard](#andthendiscard) - [do notation](#do-notation) - [bind](#bind) - [type class](#type-class) - [Chainable (interface)](#chainable-interface) - [utils](#utils) - [tap](#tap) --- # combining ## andThenDiscard Sequences the specified effect after this effect, but ignores the value produced by the effect. **Signature** ```ts export declare const andThenDiscard: ( F: Chainable ) => { (that: Kind): ( self: Kind ) => Kind (self: Kind, that: Kind): Kind< F, R1 & R2, O1 | O2, E1 | E2, A > } ``` Added in v1.0.0 # do notation ## bind **Signature** ```ts export declare const bind: ( F: Chainable ) => { (name: Exclude, f: (a: A) => Kind): < R1, O1, E1 >( self: Kind ) => Kind ( self: Kind, name: Exclude, f: (a: A) => Kind ): Kind } ``` Added in v1.0.0 # type class ## Chainable (interface) **Signature** ```ts export interface Chainable extends FlatMap, Covariant {} ``` Added in v1.0.0 # utils ## tap Returns an effect that effectfully "peeks" at the success of this effect. **Signature** ```ts export declare const tap: ( F: Chainable ) => { (f: (a: A) => Kind): ( self: Kind ) => Kind (self: Kind, f: (a: A) => Kind): Kind< F, R1 & R2, O1 | O2, E1 | E2, A > } ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Contravariant.ts.md ================================================ --- title: typeclass/Contravariant.ts nav_order: 24 parent: Modules --- ## Contravariant overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Contravariant (interface)](#contravariant-interface) - [utils](#utils) - [contramapComposition](#contramapcomposition) - [imap](#imap) --- # type class ## Contravariant (interface) **Signature** ```ts export interface Contravariant extends Invariant { readonly contramap: { (f: (b: B) => A): (self: Kind) => Kind (self: Kind, f: (b: B) => A): Kind } } ``` Added in v1.0.0 # utils ## contramapComposition Composing two contravariant functors yields a Covariant functor. Returns a default binary `map` composition. **Signature** ```ts export declare const contramapComposition: ( F: Contravariant, G: Contravariant ) => ( self: Kind>, f: (a: A) => B ) => Kind> ``` Added in v1.0.0 ## imap Returns a default `imap` implementation. **Signature** ```ts export declare const imap: ( contramap: (self: Kind, f: (b: B) => A) => Kind ) => { (to: (a: A) => B, from: (b: B) => A): (self: Kind) => Kind (self: Kind, to: (a: A) => B, from: (b: B) => A): Kind } ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Coproduct.ts.md ================================================ --- title: typeclass/Coproduct.ts nav_order: 25 parent: Modules --- ## Coproduct overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Coproduct (interface)](#coproduct-interface) - [utils](#utils) - [getMonoid](#getmonoid) --- # type class ## Coproduct (interface) **Signature** ```ts export interface Coproduct extends SemiCoproduct { readonly zero:
() => Kind readonly coproductAll: (collection: Iterable>) => Kind } ``` Added in v1.0.0 # utils ## getMonoid **Signature** ```ts export declare const getMonoid: (F: Coproduct) => () => Monoid> ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Covariant.ts.md ================================================ --- title: typeclass/Covariant.ts nav_order: 26 parent: Modules --- ## Covariant overview Added in v1.0.0 ---

Table of contents

- [do notation](#do-notation) - [let](#let) - [mapping](#mapping) - [as](#as) - [asUnit](#asunit) - [flap](#flap) - [type class](#type-class) - [Covariant (interface)](#covariant-interface) - [utils](#utils) - [imap](#imap) - [mapComposition](#mapcomposition) --- # do notation ## let **Signature** ```ts export declare const let: ( F: Covariant ) => { (name: Exclude, f: (a: A) => B): ( self: Kind ) => Kind ( self: Kind, name: Exclude, f: (a: A) => B ): Kind } ``` Added in v1.0.0 # mapping ## as **Signature** ```ts export declare const as: ( F: Covariant ) => { (b: B): (self: Kind) => Kind (self: Kind, b: B): Kind } ``` Added in v1.0.0 ## asUnit **Signature** ```ts export declare const asUnit: ( F: Covariant ) => (self: Kind) => Kind ``` Added in v1.0.0 ## flap **Signature** ```ts export declare const flap: ( F: Covariant ) => { (self: Kind B>): (a: A) => Kind (a: A, self: Kind B>): Kind } ``` Added in v1.0.0 # type class ## Covariant (interface) **Signature** ```ts export interface Covariant extends Invariant { readonly map: { (f: (a: A) => B): (self: Kind) => Kind (self: Kind, f: (a: A) => B): Kind } } ``` Added in v1.0.0 # utils ## imap Returns a default `imap` implementation. **Signature** ```ts export declare const imap: ( map: (self: Kind, f: (a: A) => B) => Kind ) => { (to: (a: A) => B, from: (b: B) => A): (self: Kind) => Kind (self: Kind, to: (a: A) => B, from: (b: B) => A): Kind } ``` Added in v1.0.0 ## mapComposition Returns a default `map` composition. **Signature** ```ts export declare const mapComposition: ( F: Covariant, G: Covariant ) => ( self: Kind>, f: (a: A) => B ) => Kind> ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Equivalence.ts.md ================================================ --- title: typeclass/Equivalence.ts nav_order: 27 parent: Modules --- ## Equivalence overview This module provides an implementation of the `Equivalence` type class, which defines a binary relation that is reflexive, symmetric, and transitive. In other words, it defines a notion of equivalence between values of a certain type. These properties are also known in mathematics as an "equivalence relation". Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [contramap](#contramap) - [struct](#struct) - [tuple](#tuple) - [constructors](#constructors) - [make](#make) - [strict](#strict) - [instances](#instances) - [Contravariant](#contravariant) - [Invariant](#invariant) - [Product](#product) - [SemiProduct](#semiproduct) - [bigint](#bigint) - [boolean](#boolean) - [getMonoid](#getmonoid) - [getSemigroup](#getsemigroup) - [number](#number) - [string](#string) - [symbol](#symbol) - [type class](#type-class) - [Equivalence (interface)](#equivalence-interface) - [type lambdas](#type-lambdas) - [EquivalenceTypeLambda (interface)](#equivalencetypelambda-interface) --- # combinators ## contramap **Signature** ```ts export declare const contramap: { (f: (b: B) => A): (self: Equivalence
) => Equivalence (self: Equivalence, f: (b: B) => A): Equivalence } ``` Added in v1.0.0 ## struct Given a struct of `Equivalence`s returns a new `Equivalence` that compares values of a struct by applying each `Equivalence` to the corresponding property of the struct. **Signature** ```ts export declare const struct: >>( predicates: R ) => Equivalence<{ readonly [K in keyof R]: [R[K]] extends [Equivalence] ? A : never }> ``` Added in v1.0.0 ## tuple Similar to `Promise.all` but operates on `Equivalence`s. ``` [Equivalence, Equivalence, ...] -> Equivalence<[A, B, ...]> ``` Given a tuple of `Equivalence`s returns a new `Equivalence` that compares values of a tuple by applying each `Equivalence` to the corresponding element of the tuple. **Signature** ```ts export declare const tuple: []>( ...predicates: T ) => Equivalence] ? A : never }>> ``` Added in v1.0.0 # constructors ## make **Signature** ```ts export declare const make: (isEquivalent: (self: A, that: A) => boolean) => Equivalence ``` Added in v1.0.0 ## strict Return an `Equivalence` that uses strict equality (===) to compare values. **Signature** ```ts export declare const strict: () => Equivalence ``` Added in v1.0.0 # instances ## Contravariant **Signature** ```ts export declare const Contravariant: contravariant.Contravariant ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## bigint **Signature** ```ts export declare const bigint: Equivalence ``` Added in v1.0.0 ## boolean **Signature** ```ts export declare const boolean: Equivalence ``` Added in v1.0.0 ## getMonoid **Signature** ```ts export declare const getMonoid: () => Monoid> ``` Added in v1.0.0 ## getSemigroup **Signature** ```ts export declare const getSemigroup: () => Semigroup> ``` Added in v1.0.0 ## number **Signature** ```ts export declare const number: Equivalence ``` Added in v1.0.0 ## string **Signature** ```ts export declare const string: Equivalence ``` Added in v1.0.0 ## symbol **Signature** ```ts export declare const symbol: Equivalence ``` Added in v1.0.0 # type class ## Equivalence (interface) **Signature** ```ts export interface Equivalence { (self: A, that: A): boolean } ``` Added in v1.0.0 # type lambdas ## EquivalenceTypeLambda (interface) **Signature** ```ts export interface EquivalenceTypeLambda extends TypeLambda { readonly type: Equivalence } ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Filterable.ts.md ================================================ --- title: typeclass/Filterable.ts nav_order: 28 parent: Modules --- ## Filterable overview `Filterable` represents data structures which can be _partitioned_/_filtered_. Added in v1.0.0 ---

Table of contents

- [models](#models) - [Filterable (interface)](#filterable-interface) - [utils](#utils) - [compact](#compact) - [filter](#filter) - [filterMapComposition](#filtermapcomposition) - [partition](#partition) - [partitionMapComposition](#partitionmapcomposition) - [separate](#separate) --- # models ## Filterable (interface) **Signature** ```ts export interface Filterable extends TypeClass { readonly partitionMap: { (f: (a: A) => Either): ( self: Kind ) => [Kind, Kind] (self: Kind, f: (a: A) => Either): [Kind, Kind] } readonly filterMap: { (f: (a: A) => Option): (self: Kind) => Kind (self: Kind, f: (a: A) => Option): Kind } } ``` Added in v1.0.0 # utils ## compact **Signature** ```ts export declare const compact: ( F: Filterable ) => (self: Kind>) => Kind ``` Added in v1.0.0 ## filter **Signature** ```ts export declare const filter: ( F: Filterable ) => { (refinement: (a: A) => a is B): ( self: Kind ) => Kind (predicate: (a: A) => boolean): (self: Kind) => Kind (self: Kind, refinement: (a: A) => a is B): Kind< F, R, O, E, B > (self: Kind, predicate: (a: A) => boolean): Kind } ``` Added in v1.0.0 ## filterMapComposition Returns a default binary `filterMap` composition. **Signature** ```ts export declare const filterMapComposition: ( F: Covariant, G: Filterable ) => ( self: Kind>, f: (a: A) => Option ) => Kind> ``` Added in v1.0.0 ## partition **Signature** ```ts export declare const partition: ( F: Filterable ) => { (refinement: (a: A) => a is B): ( self: Kind ) => [Kind, Kind] (predicate: (a: A) => boolean): ( self: Kind ) => [Kind, Kind] (self: Kind, refinement: (a: A) => a is B): [ Kind, Kind ] (self: Kind, predicate: (a: A) => boolean): [ Kind, Kind ] } ``` Added in v1.0.0 ## partitionMapComposition Returns a default binary `partitionMap` composition. **Signature** ```ts export declare const partitionMapComposition: ( F: Covariant, G: Filterable ) => ( self: Kind>, f: (a: A) => Either ) => [Kind>, Kind>] ``` Added in v1.0.0 ## separate **Signature** ```ts export declare const separate: ( F: Filterable ) => (self: Kind>) => [Kind, Kind] ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/FlatMap.ts.md ================================================ --- title: typeclass/FlatMap.ts nav_order: 29 parent: Modules --- ## FlatMap overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [FlatMap (interface)](#flatmap-interface) - [utils](#utils) - [andThen](#andthen) - [composeKleisliArrow](#composekleisliarrow) - [flatten](#flatten) --- # type class ## FlatMap (interface) **Signature** ```ts export interface FlatMap extends TypeClass { readonly flatMap: { (f: (a: A) => Kind): ( self: Kind ) => Kind (self: Kind, f: (a: A) => Kind): Kind< F, R1 & R2, O1 | O2, E1 | E2, B > } } ``` Added in v1.0.0 # utils ## andThen A variant of `flatMap` that ignores the value produced by this effect. **Signature** ```ts export declare const andThen: ( F: FlatMap ) => { (that: Kind): ( self: Kind ) => Kind (self: Kind, that: Kind): Kind< F, R1 & R2, O1 | O2, E1 | E2, B > } ``` Added in v1.0.0 ## composeKleisliArrow **Signature** ```ts export declare const composeKleisliArrow: ( F: FlatMap ) => { (bfc: (b: B) => Kind): ( afb: (a: A) => Kind ) => (a: A) => Kind (afb: (a: A) => Kind, bfc: (b: B) => Kind): ( a: A ) => Kind } ``` Added in v1.0.0 ## flatten **Signature** ```ts export declare const flatten: ( F: FlatMap ) => ( self: Kind> ) => Kind ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Foldable.ts.md ================================================ --- title: typeclass/Foldable.ts nav_order: 30 parent: Modules --- ## Foldable overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Foldable (interface)](#foldable-interface) - [utils](#utils) - [combineMap](#combinemap) - [coproductMapKind](#coproductmapkind) - [reduceComposition](#reducecomposition) - [reduceKind](#reducekind) - [toArray](#toarray) - [toArrayMap](#toarraymap) --- # type class ## Foldable (interface) **Signature** ```ts export interface Foldable extends TypeClass { readonly reduce: { (b: B, f: (b: B, a: A) => B): (self: Kind) => B (self: Kind, b: B, f: (b: B, a: A) => B): B } } ``` Added in v1.0.0 # utils ## combineMap **Signature** ```ts export declare const combineMap: ( F: Foldable ) => (M: Monoid) => {
(f: (a: A) => M): (self: Kind) => M (self: Kind, f: (a: A) => M): M } ``` Added in v1.0.0 ## coproductMapKind **Signature** ```ts export declare const coproductMapKind: ( F: Foldable ) => ( G: Coproduct ) => { (f: (a: A) => Kind): (self: Kind) => Kind (self: Kind, f: (a: A) => Kind): Kind } ``` Added in v1.0.0 ## reduceComposition Returns a default ternary `reduce` composition. **Signature** ```ts export declare const reduceComposition: ( F: Foldable, G: Foldable ) => (self: Kind>, b: B, f: (b: B, a: A) => B) => B ``` Added in v1.0.0 ## reduceKind **Signature** ```ts export declare const reduceKind: ( F: Foldable ) => ( G: Monad ) => { (b: B, f: (b: B, a: A) => Kind): ( self: Kind ) => Kind (self: Kind, b: B, f: (b: B, a: A) => Kind): Kind< G, R, O, E, B > } ``` Added in v1.0.0 ## toArray **Signature** ```ts export declare const toArray: (F: Foldable) => (self: Kind) => A[] ``` Added in v1.0.0 ## toArrayMap **Signature** ```ts export declare const toArrayMap: ( F: Foldable ) => { (f: (a: A) => B): (self: Kind) => B[] (self: Kind, f: (a: A) => B): B[] } ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Invariant.ts.md ================================================ --- title: typeclass/Invariant.ts nav_order: 31 parent: Modules --- ## Invariant overview The `Invariant` typeclass is a higher-order abstraction over types that allow mapping the contents of a type in both directions. It is similar to the `Covariant` typeclass but provides an `imap` opration, which allows transforming a value in both directions. This typeclass is useful when dealing with data types that can be converted to and from some other types. The `imap` operation provides a way to convert such data types to other types that they can interact with while preserving their invariants. Added in v1.0.0 ---

Table of contents

- [do notation](#do-notation) - [bindTo](#bindto) - [type class](#type-class) - [Invariant (interface)](#invariant-interface) - [utils](#utils) - [imapComposition](#imapcomposition) - [tupled](#tupled) --- # do notation ## bindTo **Signature** ```ts export declare const bindTo: ( F: Invariant ) => { (name: N): (self: Kind) => Kind (self: Kind, name: N): Kind } ``` Added in v1.0.0 # type class ## Invariant (interface) **Signature** ```ts export interface Invariant extends TypeClass { readonly imap: { (to: (a: A) => B, from: (b: B) => A): (self: Kind) => Kind (self: Kind, to: (a: A) => B, from: (b: B) => A): Kind } } ``` Added in v1.0.0 # utils ## imapComposition Returns a default ternary `imap` composition. **Signature** ```ts export declare const imapComposition: ( F: Invariant, G: Invariant ) => ( self: Kind>, to: (a: A) => B, from: (b: B) => A ) => Kind> ``` Added in v1.0.0 ## tupled Convert a value in a singleton array in a given effect. **Signature** ```ts export declare const tupled: ( F: Invariant ) => (self: Kind) => Kind ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Monad.ts.md ================================================ --- title: typeclass/Monad.ts nav_order: 32 parent: Modules --- ## Monad overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Monad (interface)](#monad-interface) --- # type class ## Monad (interface) **Signature** ```ts export interface Monad extends FlatMap, Pointed {} ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Monoid.ts.md ================================================ --- title: typeclass/Monoid.ts nav_order: 33 parent: Modules --- ## Monoid overview Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [array](#array) - [reverse](#reverse) - [struct](#struct) - [tuple](#tuple) - [constructors](#constructors) - [fromSemigroup](#fromsemigroup) - [max](#max) - [min](#min) - [instances](#instances) - [bigintMultiply](#bigintmultiply) - [bigintSum](#bigintsum) - [booleanAll](#booleanall) - [booleanAny](#booleanany) - [booleanEqv](#booleaneqv) - [booleanXor](#booleanxor) - [numberMultiply](#numbermultiply) - [numberSum](#numbersum) - [string](#string) - [type class](#type-class) - [Monoid (interface)](#monoid-interface) --- # combinators ## array Given a type `A`, this function creates and returns a `Semigroup` for `ReadonlyArray
`. The `empty` value is the empty array. **Signature** ```ts export declare const array: () => Monoid ``` Added in v1.0.0 ## reverse The dual of a `Monoid`, obtained by swapping the arguments of `combine`. **Signature** ```ts export declare const reverse: (M: Monoid) => Monoid ``` Added in v1.0.0 ## struct This function creates and returns a new `Monoid` for a struct of values based on the given `Monoid`s for each property in the struct. The returned `Monoid` combines two structs of the same type by applying the corresponding `Monoid` passed as arguments to each property in the struct. The `empty` value of the returned `Monoid` is a struct where each property is the `empty` value of the corresponding `Monoid` in the input `monoids` object. It is useful when you need to combine two structs of the same type and you have a specific way of combining each property of the struct. **Signature** ```ts export declare const struct: }>( fields: R ) => Monoid<{ readonly [K in keyof R]: [R[K]] extends [Monoid] ? A : never }> ``` Added in v1.0.0 ## tuple Similar to `Promise.all` but operates on `Monoid`s. ``` [Monoid, Monoid, ...] -> Monoid<[A, B, ...]> ``` This function creates and returns a new `Monoid` for a tuple of values based on the given `Monoid`s for each element in the tuple. The returned `Monoid` combines two tuples of the same type by applying the corresponding `Monoid` passed as arguments to each element in the tuple. The `empty` value of the returned `Monoid` is the tuple of `empty` values of the input `Monoid`s. It is useful when you need to combine two tuples of the same type and you have a specific way of combining each element of the tuple. **Signature** ```ts export declare const tuple: []>( ...elements: T ) => Monoid<{ readonly [I in keyof T]: [T[I]] extends [Monoid] ? A : never }> ``` Added in v1.0.0 # constructors ## fromSemigroup **Signature** ```ts export declare const fromSemigroup: (S: Semigroup, empty: A) => Monoid ``` Added in v1.0.0 ## max Get a monoid where `combine` will return the maximum, based on the provided bounded order. The `empty` value is the `minimum` value. **Signature** ```ts export declare const max: (B: Bounded) => Monoid ``` Added in v1.0.0 ## min Get a monoid where `combine` will return the minimum, based on the provided bounded order. The `empty` value is the `maxBound` value. **Signature** ```ts export declare const min: (B: Bounded) => Monoid ``` Added in v1.0.0 # instances ## bigintMultiply `bigint` monoid under multiplication. The `empty` value is `1n`. **Signature** ```ts export declare const bigintMultiply: Monoid ``` Added in v1.0.0 ## bigintSum `number` monoid under addition. The `bigint` value is `0n`. **Signature** ```ts export declare const bigintSum: Monoid ``` Added in v1.0.0 ## booleanAll `boolean` monoid under conjunction. The `empty` value is `true`. **Signature** ```ts export declare const booleanAll: Monoid ``` Added in v1.0.0 ## booleanAny `boolean` monoid under disjunction. The `empty` value is `false`. **Signature** ```ts export declare const booleanAny: Monoid ``` Added in v1.0.0 ## booleanEqv `boolean` monoid under equivalence. The `empty` value is `true`. **Signature** ```ts export declare const booleanEqv: Monoid ``` Added in v1.0.0 ## booleanXor `boolean` monoid under exclusive disjunction. The `empty` value is `false`. **Signature** ```ts export declare const booleanXor: Monoid ``` Added in v1.0.0 ## numberMultiply `number` monoid under multiplication. The `empty` value is `1`. **Signature** ```ts export declare const numberMultiply: Monoid ``` Added in v1.0.0 ## numberSum `number` monoid under addition. The `empty` value is `0`. **Signature** ```ts export declare const numberSum: Monoid ``` Added in v1.0.0 ## string **Signature** ```ts export declare const string: Monoid ``` Added in v1.0.0 # type class ## Monoid (interface) **Signature** ```ts export interface Monoid extends Semigroup { readonly empty: A readonly combineAll: (collection: Iterable) => A } ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Of.ts.md ================================================ --- title: typeclass/Of.ts nav_order: 34 parent: Modules --- ## Of overview Added in v1.0.0 ---

Table of contents

- [do notation](#do-notation) - [Do](#do) - [type class](#type-class) - [Of (interface)](#of-interface) - [utils](#utils) - [ofComposition](#ofcomposition) - [unit](#unit) --- # do notation ## Do **Signature** ```ts export declare const Do: (F: Of) => Kind ``` Added in v1.0.0 # type class ## Of (interface) **Signature** ```ts export interface Of extends TypeClass { readonly of:
(a: A) => Kind } ``` Added in v1.0.0 # utils ## ofComposition Returns a default `of` composition. **Signature** ```ts export declare const ofComposition: ( F: Of, G: Of ) => (a: A) => Kind> ``` Added in v1.0.0 ## unit **Signature** ```ts export declare const unit: (F: Of) => Kind ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Order.ts.md ================================================ --- title: typeclass/Order.ts nav_order: 35 parent: Modules --- ## Order overview Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [array](#array) - [contramap](#contramap) - [struct](#struct) - [tuple](#tuple) - [constructors](#constructors) - [make](#make) - [instances](#instances) - [Contravariant](#contravariant) - [Invariant](#invariant) - [Product](#product) - [SemiProduct](#semiproduct) - [bigint](#bigint) - [boolean](#boolean) - [getMonoid](#getmonoid) - [getSemigroup](#getsemigroup) - [number](#number) - [string](#string) - [type class](#type-class) - [Order (interface)](#order-interface) - [type lambdas](#type-lambdas) - [OrderTypeLambda (interface)](#ordertypelambda-interface) - [utils](#utils) - [between](#between) - [clamp](#clamp) - [greaterThan](#greaterthan) - [greaterThanOrEqualTo](#greaterthanorequalto) - [lessThan](#lessthan) - [lessThanOrEqualTo](#lessthanorequalto) - [max](#max) - [min](#min) - [reverse](#reverse) --- # combinators ## array This function creates and returns a new `Order` for an array of values based on a given `Order` for the elements of the array. The returned `Order` compares two arrays by applying the given `Order` to each element in the arrays. If all elements are equal, the arrays are then compared based on their length. It is useful when you need to compare two arrays of the same type and you have a specific way of comparing each element of the array. **Signature** ```ts export declare const array:
(O: Order) => Order ``` Added in v1.0.0 ## contramap **Signature** ```ts export declare const contramap: { (f: (b: B) => A): (self: Order) => Order (self: Order, f: (b: B) => A): Order } ``` Added in v1.0.0 ## struct This function creates and returns a new `Order` for a struct of values based on the given `Order`s for each property in the struct. **Signature** ```ts export declare const struct: }>( fields: R ) => Order<{ [K in keyof R]: [R[K]] extends [Order] ? A : never }> ``` Added in v1.0.0 ## tuple Similar to `Promise.all` but operates on `Order`s. ``` [Order, Order, ...] -> Order<[A, B, ...]> ``` This function creates and returns a new `Order` for a tuple of values based on the given `Order`s for each element in the tuple. The returned `Order` compares two tuples of the same type by applying the corresponding `Order` to each element in the tuple. It is useful when you need to compare two tuples of the same type and you have a specific way of comparing each element of the tuple. **Signature** ```ts export declare const tuple: []>( ...elements: T ) => Order<{ [I in keyof T]: [T[I]] extends [Order] ? A : never }> ``` Added in v1.0.0 # constructors ## make **Signature** ```ts export declare const make: (compare: (self: A, that: A) => 0 | 1 | -1) => Order ``` Added in v1.0.0 # instances ## Contravariant **Signature** ```ts export declare const Contravariant: contravariant.Contravariant ``` Added in v1.0.0 ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## bigint **Signature** ```ts export declare const bigint: Order ``` Added in v1.0.0 ## boolean **Signature** ```ts export declare const boolean: Order ``` Added in v1.0.0 ## getMonoid **Signature** ```ts export declare const getMonoid: () => Monoid> ``` Added in v1.0.0 ## getSemigroup **Signature** ```ts export declare const getSemigroup: () => Semigroup> ``` Added in v1.0.0 ## number **Signature** ```ts export declare const number: Order ``` Added in v1.0.0 ## string **Signature** ```ts export declare const string: Order ``` Added in v1.0.0 # type class ## Order (interface) **Signature** ```ts export interface Order { readonly compare: (self: A, that: A) => -1 | 0 | 1 } ``` Added in v1.0.0 # type lambdas ## OrderTypeLambda (interface) **Signature** ```ts export interface OrderTypeLambda extends TypeLambda { readonly type: Order } ``` Added in v1.0.0 # utils ## between Test whether a value is between a minimum and a maximum (inclusive). **Signature** ```ts export declare const between: (O: Order) => { (minimum: A, maximum: A): (self: A) => boolean (self: A, minimum: A, maximum: A): boolean } ``` Added in v1.0.0 ## clamp Clamp a value between a minimum and a maximum. **Signature** ```ts export declare const clamp: (O: Order) => { (minimum: A, maximum: A): (self: A) => A (self: A, minimum: A, maximum: A): A } ``` Added in v1.0.0 ## greaterThan Test whether one value is _strictly greater than_ another. **Signature** ```ts export declare const greaterThan: (O: Order) => { (that: A): (self: A) => boolean; (self: A, that: A): boolean } ``` Added in v1.0.0 ## greaterThanOrEqualTo Test whether one value is _non-strictly greater than_ another. **Signature** ```ts export declare const greaterThanOrEqualTo: (O: Order) => { (that: A): (self: A) => boolean (self: A, that: A): boolean } ``` Added in v1.0.0 ## lessThan Test whether one value is _strictly less than_ another. **Signature** ```ts export declare const lessThan: (O: Order) => { (that: A): (self: A) => boolean; (self: A, that: A): boolean } ``` Added in v1.0.0 ## lessThanOrEqualTo Test whether one value is _non-strictly less than_ another. **Signature** ```ts export declare const lessThanOrEqualTo: (O: Order) => { (that: A): (self: A) => boolean (self: A, that: A): boolean } ``` Added in v1.0.0 ## max Take the maximum of two values. If they are considered equal, the first argument is chosen. **Signature** ```ts export declare const max: (O: Order) => { (that: A): (self: A) => A; (self: A, that: A): A } ``` Added in v1.0.0 ## min Take the minimum of two values. If they are considered equal, the first argument is chosen. **Signature** ```ts export declare const min: (O: Order) => { (that: A): (self: A) => A; (self: A, that: A): A } ``` Added in v1.0.0 ## reverse **Signature** ```ts export declare const reverse: (O: Order) => Order ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Pointed.ts.md ================================================ --- title: typeclass/Pointed.ts nav_order: 36 parent: Modules --- ## Pointed overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Pointed (interface)](#pointed-interface) --- # type class ## Pointed (interface) **Signature** ```ts export interface Pointed extends Covariant, Of {} ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Product.ts.md ================================================ --- title: typeclass/Product.ts nav_order: 37 parent: Modules --- ## Product overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Product (interface)](#product-interface) - [utils](#utils) - [struct](#struct) - [tuple](#tuple) --- # type class ## Product (interface) **Signature** ```ts export interface Product extends SemiProduct, Of { readonly productAll: (collection: Iterable>) => Kind> } ``` Added in v1.0.0 # utils ## struct **Signature** ```ts export declare const struct: ( F: Product ) => }>( fields: R ) => Kind< F, [R[keyof R]] extends [Kind] ? R : never, [R[keyof R]] extends [Kind] ? O : never, [R[keyof R]] extends [Kind] ? E : never, { [K in keyof R]: [R[K]] extends [Kind] ? A : never } > ``` Added in v1.0.0 ## tuple **Signature** ```ts export declare const tuple: ( F: Product ) => []>( ...elements: T ) => Kind< F, [T[number]] extends [Kind] ? R : never, [T[number]] extends [Kind] ? O : never, [T[number]] extends [Kind] ? E : never, { [I in keyof T]: [T[I]] extends [Kind] ? A : never } > ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/SemiAlternative.ts.md ================================================ --- title: typeclass/SemiAlternative.ts nav_order: 38 parent: Modules --- ## SemiAlternative overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [SemiAlternative (interface)](#semialternative-interface) --- # type class ## SemiAlternative (interface) **Signature** ```ts export interface SemiAlternative extends SemiCoproduct, Covariant {} ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/SemiApplicative.ts.md ================================================ --- title: typeclass/SemiApplicative.ts nav_order: 39 parent: Modules --- ## SemiApplicative overview Added in v1.0.0 ---

Table of contents

- [lifting](#lifting) - [getSemigroup](#getsemigroup) - [lift2](#lift2) - [type class](#type-class) - [SemiApplicative (interface)](#semiapplicative-interface) - [utils](#utils) - [andThen](#andthen) - [andThenDiscard](#andthendiscard) - [ap](#ap) - [zipWith](#zipwith) --- # lifting ## getSemigroup Lift a `Semigroup` into 'F', the inner values are combined using the provided `Semigroup`. **Signature** ```ts export declare const getSemigroup: ( F: SemiApplicative ) => (S: Semigroup
) => Semigroup> ``` Added in v1.0.0 ## lift2 Lifts a binary function into `F`. **Signature** ```ts export declare const lift2: ( F: SemiApplicative ) => ( f: (a: A, b: B) => C ) => { (that: Kind): ( self: Kind ) => Kind (self: Kind, that: Kind): Kind< F, R1 & R2, O1 | O2, E1 | E2, C > } ``` Added in v1.0.0 # type class ## SemiApplicative (interface) **Signature** ```ts export interface SemiApplicative extends SemiProduct, Covariant {} ``` Added in v1.0.0 # utils ## andThen **Signature** ```ts export declare const andThen: ( F: SemiApplicative ) => { (that: Kind): ( self: Kind ) => Kind (self: Kind, that: Kind): Kind< F, R1 & R2, O1 | O2, E1 | E2, B > } ``` Added in v1.0.0 ## andThenDiscard **Signature** ```ts export declare const andThenDiscard: ( F: SemiApplicative ) => { (that: Kind): ( self: Kind ) => Kind (self: Kind, that: Kind): Kind< F, R1 & R2, O1 | O2, E1 | E2, A > } ``` Added in v1.0.0 ## ap **Signature** ```ts export declare const ap: ( F: SemiApplicative ) => { (that: Kind): ( self: Kind B> ) => Kind (self: Kind B>, that: Kind): Kind< F, R1 & R2, O1 | O2, E1 | E2, B > } ``` Added in v1.0.0 ## zipWith Zips two `F` values together using a provided function, returning a new `F` of the result. **Signature** ```ts export declare const zipWith: ( F: SemiApplicative ) => { (that: Kind, f: (a: A, b: B) => C): ( self: Kind ) => Kind ( self: Kind, that: Kind, f: (a: A, b: B) => C ): Kind } ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/SemiCoproduct.ts.md ================================================ --- title: typeclass/SemiCoproduct.ts nav_order: 40 parent: Modules --- ## SemiCoproduct overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [SemiCoproduct (interface)](#semicoproduct-interface) - [utils](#utils) - [getSemigroup](#getsemigroup) --- # type class ## SemiCoproduct (interface) **Signature** ```ts export interface SemiCoproduct extends Invariant { readonly coproduct: ( self: Kind, that: Kind ) => Kind readonly coproductMany: ( self: Kind, collection: Iterable> ) => Kind } ``` Added in v1.0.0 # utils ## getSemigroup **Signature** ```ts export declare const getSemigroup: ( F: SemiCoproduct ) => () => Semigroup> ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/SemiProduct.ts.md ================================================ --- title: typeclass/SemiProduct.ts nav_order: 42 parent: Modules --- ## SemiProduct overview Added in v1.0.0 ---

Table of contents

- [constructors](#constructors) - [productMany](#productmany) - [do notation](#do-notation) - [andThenBind](#andthenbind) - [type class](#type-class) - [SemiProduct (interface)](#semiproduct-interface) - [utils](#utils) - [appendElement](#appendelement) - [nonEmptyStruct](#nonemptystruct) - [nonEmptyTuple](#nonemptytuple) - [productComposition](#productcomposition) - [productManyComposition](#productmanycomposition) --- # constructors ## productMany Returns a default `productMany` implementation. **Signature** ```ts export declare const productMany: ( map: { (f: (a: A) => B): (self: Kind) => Kind (self: Kind, f: (a: A) => B): Kind }, product: ( self: Kind, that: Kind ) => Kind ) => (self: Kind, collection: Iterable>) => Kind ``` Added in v1.0.0 # do notation ## andThenBind **Signature** ```ts export declare const andThenBind: ( F: SemiProduct ) => { (name: Exclude, that: Kind): < R1, O1, E1 >( self: Kind ) => Kind ( self: Kind, name: Exclude, that: Kind ): Kind } ``` Added in v1.0.0 # type class ## SemiProduct (interface) **Signature** ```ts export interface SemiProduct extends Invariant { readonly product: ( self: Kind, that: Kind ) => Kind readonly productMany: ( self: Kind, collection: Iterable> ) => Kind]> } ``` Added in v1.0.0 # utils ## appendElement Appends an element to the end of a tuple. **Signature** ```ts export declare const appendElement: ( F: SemiProduct ) => { (that: Kind): ( self: Kind ) => Kind ( self: Kind, that: Kind ): Kind } ``` Added in v1.0.0 ## nonEmptyStruct **Signature** ```ts export declare const nonEmptyStruct: ( F: SemiProduct ) => }>( fields: EnforceNonEmptyRecord & { readonly [x: string]: Kind } ) => Kind< F, [R[keyof R]] extends [Kind] ? R : never, [R[keyof R]] extends [Kind] ? O : never, [R[keyof R]] extends [Kind] ? E : never, { [K in keyof R]: [R[K]] extends [Kind] ? A : never } > ``` Added in v1.0.0 ## nonEmptyTuple **Signature** ```ts export declare const nonEmptyTuple: ( F: SemiProduct ) => , ...Kind[]]>( ...elements: T ) => Kind< F, [T[number]] extends [Kind] ? R : never, [T[number]] extends [Kind] ? O : never, [T[number]] extends [Kind] ? E : never, { [I in keyof T]: [T[I]] extends [Kind] ? A : never } > ``` Added in v1.0.0 ## productComposition Returns a default `product` composition. **Signature** ```ts export declare const productComposition: ( F: SemiApplicative, G: SemiProduct ) => ( self: Kind>, that: Kind> ) => Kind> ``` Added in v1.0.0 ## productManyComposition Returns a default `productMany` composition. **Signature** ```ts export declare const productManyComposition: ( F: SemiApplicative, G: SemiProduct ) => ( self: Kind>, collection: Iterable>> ) => Kind> ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Semigroup.ts.md ================================================ --- title: typeclass/Semigroup.ts nav_order: 41 parent: Modules --- ## Semigroup overview Added in v1.0.0 ---

Table of contents

- [combinators](#combinators) - [array](#array) - [struct](#struct) - [tuple](#tuple) - [constructors](#constructors) - [constant](#constant) - [make](#make) - [max](#max) - [min](#min) - [instances](#instances) - [Invariant](#invariant) - [Product](#product) - [SemiProduct](#semiproduct) - [bigintMultiply](#bigintmultiply) - [bigintSum](#bigintsum) - [booleanAll](#booleanall) - [booleanAny](#booleanany) - [booleanEqv](#booleaneqv) - [booleanXor](#booleanxor) - [first](#first) - [last](#last) - [numberMultiply](#numbermultiply) - [numberSum](#numbersum) - [string](#string) - [type class](#type-class) - [Semigroup (interface)](#semigroup-interface) - [type lambdas](#type-lambdas) - [SemigroupTypeLambda (interface)](#semigrouptypelambda-interface) - [utils](#utils) - [imap](#imap) - [intercalate](#intercalate) - [reverse](#reverse) --- # combinators ## array Given a type `A`, this function creates and returns a `Semigroup` for `ReadonlyArray
`. The returned `Semigroup` combines two arrays by concatenating them. **Signature** ```ts export declare const array: () => Semigroup ``` Added in v1.0.0 ## struct This function creates and returns a new `Semigroup` for a struct of values based on the given `Semigroup`s for each property in the struct. The returned `Semigroup` combines two structs of the same type by applying the corresponding `Semigroup` passed as arguments to each property in the struct. It is useful when you need to combine two structs of the same type and you have a specific way of combining each property of the struct. **Signature** ```ts export declare const struct: }>( fields: R ) => Semigroup<{ readonly [K in keyof R]: [R[K]] extends [Semigroup] ? A : never }> ``` Added in v1.0.0 ## tuple Similar to `Promise.all` but operates on `Semigroup`s. ``` [Semigroup, Semigroup, ...] -> Semigroup<[A, B, ...]> ``` This function creates and returns a new `Semigroup` for a tuple of values based on the given `Semigroup`s for each element in the tuple. The returned `Semigroup` combines two tuples of the same type by applying the corresponding `Semigroup` passed as arguments to each element in the tuple. It is useful when you need to combine two tuples of the same type and you have a specific way of combining each element of the tuple. **Signature** ```ts export declare const tuple: []>( ...elements: T ) => Semigroup<{ readonly [I in keyof T]: [T[I]] extends [Semigroup] ? A : never }> ``` Added in v1.0.0 # constructors ## constant **Signature** ```ts export declare const constant: (a: A) => Semigroup ``` Added in v1.0.0 ## make **Signature** ```ts export declare const make: ( combine: (self: A, that: A) => A, combineMany?: (self: A, collection: Iterable) => A ) => Semigroup ``` Added in v1.0.0 ## max `Semigroup` that returns last maximum of elements. **Signature** ```ts export declare const max: (O: Order) => Semigroup ``` Added in v1.0.0 ## min `Semigroup` that returns last minimum of elements. **Signature** ```ts export declare const min: (O: Order) => Semigroup ``` Added in v1.0.0 # instances ## Invariant **Signature** ```ts export declare const Invariant: invariant.Invariant ``` Added in v1.0.0 ## Product **Signature** ```ts export declare const Product: product_.Product ``` Added in v1.0.0 ## SemiProduct **Signature** ```ts export declare const SemiProduct: semiProduct.SemiProduct ``` Added in v1.0.0 ## bigintMultiply `bigint` semigroup under multiplication. **Signature** ```ts export declare const bigintMultiply: Semigroup ``` Added in v1.0.0 ## bigintSum `bigint` semigroup under addition. **Signature** ```ts export declare const bigintSum: Semigroup ``` Added in v1.0.0 ## booleanAll `boolean` semigroup under conjunction. **Signature** ```ts export declare const booleanAll: Semigroup ``` Added in v1.0.0 ## booleanAny `boolean` semigroup under disjunction. **Signature** ```ts export declare const booleanAny: Semigroup ``` Added in v1.0.0 ## booleanEqv `boolean` semigroup under equivalence. **Signature** ```ts export declare const booleanEqv: Semigroup ``` Added in v1.0.0 ## booleanXor `boolean` semigroup under exclusive disjunction. **Signature** ```ts export declare const booleanXor: Semigroup ``` Added in v1.0.0 ## first Always return the first argument. **Signature** ```ts export declare const first: () => Semigroup ``` Added in v1.0.0 ## last Always return the last argument. **Signature** ```ts export declare const last: () => Semigroup ``` Added in v1.0.0 ## numberMultiply `number` semigroup under multiplication. **Signature** ```ts export declare const numberMultiply: Semigroup ``` Added in v1.0.0 ## numberSum `number` semigroup under addition. **Signature** ```ts export declare const numberSum: Semigroup ``` Added in v1.0.0 ## string **Signature** ```ts export declare const string: Semigroup ``` Added in v1.0.0 # type class ## Semigroup (interface) **Signature** ```ts export interface Semigroup { readonly combine: (self: A, that: A) => A readonly combineMany: (self: A, collection: Iterable) => A } ``` Added in v1.0.0 # type lambdas ## SemigroupTypeLambda (interface) **Signature** ```ts export interface SemigroupTypeLambda extends TypeLambda { readonly type: Semigroup } ``` Added in v1.0.0 # utils ## imap **Signature** ```ts export declare const imap: { (to: (a: A) => B, from: (b: B) => A): (self: Semigroup) => Semigroup (self: Semigroup, to: (a: A) => B, from: (b: B) => A): Semigroup } ``` Added in v1.0.0 ## intercalate **Signature** ```ts export declare const intercalate: { (separator: A): (S: Semigroup) => Semigroup (S: Semigroup, separator: A): Semigroup } ``` Added in v1.0.0 ## reverse The dual of a `Semigroup`, obtained by flipping the arguments of `combine`. **Signature** ```ts export declare const reverse: (S: Semigroup) => Semigroup ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/Traversable.ts.md ================================================ --- title: typeclass/Traversable.ts nav_order: 43 parent: Modules --- ## Traversable overview Added in v1.0.0 ---

Table of contents

- [type class](#type-class) - [Traversable (interface)](#traversable-interface) - [utils](#utils) - [sequence](#sequence) - [traverseComposition](#traversecomposition) - [traverseTap](#traversetap) --- # type class ## Traversable (interface) **Signature** ```ts export interface Traversable extends TypeClass { readonly traverse: ( F: Applicative ) => { (f: (a: A) => Kind): ( self: Kind ) => Kind> (self: Kind, f: (a: A) => Kind): Kind< F, R, O, E, Kind > } } ``` Added in v1.0.0 # utils ## sequence Returns a default `sequence` implementation. **Signature** ```ts export declare const sequence: ( T: Traversable ) => ( F: Applicative ) => ( self: Kind> ) => Kind> ``` Added in v1.0.0 ## traverseComposition Returns a default binary `traverse` composition. **Signature** ```ts export declare const traverseComposition: ( T: Traversable, G: Traversable ) => ( F: Applicative ) => ( self: Kind>, f: (a: A) => Kind ) => Kind>> ``` Added in v1.0.0 ## traverseTap Given a function which returns a `F` effect, thread this effect through the running of this function on all the values in `T`, returning an `T
` in a `F` context, ignoring the values returned by the provided function. **Signature** ```ts export declare const traverseTap: ( T: Traversable ) => ( F: Applicative ) => { (f: (a: A) => Kind): ( self: Kind ) => Kind> (self: Kind, f: (a: A) => Kind): Kind< F, R, O, E, Kind > } ``` Added in v1.0.0 ================================================ FILE: docs/modules/typeclass/TraversableFilterable.ts.md ================================================ --- title: typeclass/TraversableFilterable.ts nav_order: 44 parent: Modules --- ## TraversableFilterable overview `TraversableFilterable` represents data structures which can be _partitioned_ with effects in some `Applicative` functor. Added in v1.0.0 ---

Table of contents

- [models](#models) - [TraversableFilterable (interface)](#traversablefilterable-interface) - [utils](#utils) - [traverseFilter](#traversefilter) - [traverseFilterMap](#traversefiltermap) - [traversePartition](#traversepartition) - [traversePartitionMap](#traversepartitionmap) --- # models ## TraversableFilterable (interface) **Signature** ```ts export interface TraversableFilterable extends TypeClass { readonly traversePartitionMap: ( F: Applicative ) => { (f: (a: A) => Kind>): ( self: Kind ) => Kind, Kind]> (self: Kind, f: (a: A) => Kind>): Kind< F, R, O, E, [Kind, Kind] > } readonly traverseFilterMap: ( F: Applicative ) => { (f: (a: A) => Kind>): ( self: Kind ) => Kind> (self: Kind, f: (a: A) => Kind>): Kind< F, R, O, E, Kind > } } ``` Added in v1.0.0 # utils ## traverseFilter **Signature** ```ts export declare const traverseFilter: ( T: TraversableFilterable ) => ( F: Applicative ) => { (predicate: (a: A) => Kind): ( self: Kind ) => Kind> ( self: Kind, predicate: (a: A) => Kind ): Kind> } ``` Added in v1.0.0 ## traverseFilterMap Returns a default binary `traverseFilterMap` implementation. **Signature** ```ts export declare const traverseFilterMap: ( T: Traversable & filterable.Filterable ) => ( F: Applicative ) => ( self: Kind, f: (a: A) => Kind> ) => Kind> ``` Added in v1.0.0 ## traversePartition **Signature** ```ts export declare const traversePartition: ( T: TraversableFilterable ) => ( F: Applicative ) => { (predicate: (a: A) => Kind): ( self: Kind ) => Kind, Kind]> ( self: Kind, predicate: (a: A) => Kind ): Kind, Kind]> } ``` Added in v1.0.0 ## traversePartitionMap Returns a default binary `traversePartitionMap` implementation. **Signature** ```ts export declare const traversePartitionMap: ( T: Traversable & Covariant & filterable.Filterable ) => ( F: Applicative ) => ( self: Kind, f: (a: A) => Kind> ) => Kind, Kind]> ``` Added in v1.0.0 ================================================ FILE: docs-ts.json ================================================ { "exclude": ["src/internal/**/*.ts"], "theme": "mikearnaldi/just-the-docs" } ================================================ FILE: dtslint/index.d.ts ================================================ // TypeScript Version: 4.8 ================================================ FILE: dtslint/ts4.8/FlatMap.ts ================================================ import * as _ from "@fp-ts/core/typeclass/FlatMap" import type { TypeLambda } from "@fp-ts/core/HKT" import { pipe } from "@fp-ts/core/Function" interface RAW { (r: R): () => Promise } interface RAWTypeLambda extends TypeLambda { readonly type: RAW } declare const FlatMap: _.FlatMap declare const ffa: RAW<{ a: string }, string, RAW<{ b: number }, number, 'a'>> // $ExpectType RAW<{ b: number; } & { a: string; }, string | number, "a"> pipe(ffa, _.flatten(FlatMap)) ================================================ FILE: dtslint/ts4.8/Monoid.ts ================================================ import * as _ from "@fp-ts/core/typeclass/Monoid" import * as Number from "@fp-ts/core/Number" import * as String from "@fp-ts/core/String" // // tuple // // $ExpectType Monoid _.tuple( String.Monoid, Number.MonoidSum ) // // struct // // $ExpectType Monoid<{ readonly a: string; readonly b: number; }> _.struct({ a: String.Monoid, b: Number.MonoidSum }) ================================================ FILE: dtslint/ts4.8/Option.ts ================================================ import { pipe } from '@fp-ts/core/Function' import * as _ from '@fp-ts/core/Option' declare const n: number declare const sn: string | number declare const isString: (u: unknown) => u is string declare const predicate: (sn: string | number) => boolean declare const on: _.Option declare const osn: _.Option // ------------------------------------------------------------------------------------- // liftPredicate // ------------------------------------------------------------------------------------- // $ExpectType Option pipe(sn, _.liftPredicate(isString)) pipe( sn, _.liftPredicate( ( n // $ExpectType string | number ): n is number => typeof n === 'number' ) ) // $ExpectType Option pipe(sn, _.liftPredicate(predicate)) // $ExpectType Option pipe(n, _.liftPredicate(predicate)) // $ExpectType Option pipe( n, _.liftPredicate( ( _n // $ExpectType number ) => true ) ) // ------------------------------------------------------------------------------------- // getOrElse // ------------------------------------------------------------------------------------- // $ExpectType string | null pipe(_.some('a'), _.getOrElse(() => null)) // ------------------------------------------------------------------------------------- // do notation // ------------------------------------------------------------------------------------- // $ExpectType Option<{ a1: number; a2: string; }> pipe( _.Do, _.bind('a1', () => _.some(1)), _.bind('a2', () => _.some('b')) ) // ------------------------------------------------------------------------------------- // filter // ------------------------------------------------------------------------------------- // $ExpectType Option pipe(on, _.filter(predicate)) // $ExpectType Option _.filter(on, predicate) // $ExpectType Option pipe(osn, _.filter(isString)) // $ExpectType Option _.filter(osn, isString) // $ExpectType Option pipe( on, _.filter( ( x // $ExpectType number ): x is number => true ) ) // $ExpectType Option pipe( on, _.filter( ( _x // $ExpectType number ) => true ) ) ================================================ FILE: dtslint/ts4.8/Predicate.ts ================================================ import * as _ from '@fp-ts/core/Predicate' declare const u: unknown declare const anys: Array declare const unknowns: Array declare const numberOrNull: Array declare const numberOrUndefined: Array declare const numberOrNullOrUndefined: Array // ------------------------------------------------------------------------------------- // isString // ------------------------------------------------------------------------------------- // $ExpectType string[] unknowns.filter(_.isString) // ------------------------------------------------------------------------------------- // isNumber // ------------------------------------------------------------------------------------- // $ExpectType number[] unknowns.filter(_.isNumber) // ------------------------------------------------------------------------------------- // isBoolean // ------------------------------------------------------------------------------------- // $ExpectType boolean[] unknowns.filter(_.isBoolean) // ------------------------------------------------------------------------------------- // isBigint // ------------------------------------------------------------------------------------- // $ExpectType bigint[] unknowns.filter(_.isBigint) // ------------------------------------------------------------------------------------- // isSymbol // ------------------------------------------------------------------------------------- // $ExpectType symbol[] unknowns.filter(_.isSymbol) // ------------------------------------------------------------------------------------- // isUndefined // ------------------------------------------------------------------------------------- // $ExpectType undefined[] unknowns.filter(_.isUndefined) // ------------------------------------------------------------------------------------- // isNotUndefined // ------------------------------------------------------------------------------------- // $ExpectType number[] numberOrUndefined.filter(_.isNotUndefined) // $ExpectType (number | null)[] numberOrNullOrUndefined.filter(_.isNotUndefined) // ------------------------------------------------------------------------------------- // isUndefined // ------------------------------------------------------------------------------------- // $ExpectType null[] unknowns.filter(_.isNull) // ------------------------------------------------------------------------------------- // isNotUndefined // ------------------------------------------------------------------------------------- // $ExpectType number[] numberOrNull.filter(_.isNotNull) // $ExpectType (number | undefined)[] numberOrNullOrUndefined.filter(_.isNotNull) // ------------------------------------------------------------------------------------- // isNever // ------------------------------------------------------------------------------------- // $ExpectType never[] unknowns.filter(_.isNever) // ------------------------------------------------------------------------------------- // isUnknown // ------------------------------------------------------------------------------------- // $ExpectType unknown[] anys.filter(_.isUnknown) // ------------------------------------------------------------------------------------- // isObject // ------------------------------------------------------------------------------------- // $ExpectType object[] anys.filter(_.isObject) // ------------------------------------------------------------------------------------- // isNullable // ------------------------------------------------------------------------------------- // $ExpectType null[] numberOrNull.filter(_.isNullable) // $ExpectType undefined[] numberOrUndefined.filter(_.isNullable) // $ExpectType (null | undefined)[] numberOrNullOrUndefined.filter(_.isNullable) if (_.isNullable(u)) { // $ExpectType never u } // ------------------------------------------------------------------------------------- // isNotNullable // ------------------------------------------------------------------------------------- // $ExpectType number[] numberOrNull.filter(_.isNotNullable) // $ExpectType number[] numberOrUndefined.filter(_.isNotNullable) // $ExpectType number[] numberOrNullOrUndefined.filter(_.isNotNullable) if (_.isNotNullable(u)) { // $ExpectType {} u } // ------------------------------------------------------------------------------------- // isError // ------------------------------------------------------------------------------------- // $ExpectType Error[] unknowns.filter(_.isError) // ------------------------------------------------------------------------------------- // isDate // ------------------------------------------------------------------------------------- // $ExpectType Date[] unknowns.filter(_.isDate) // ------------------------------------------------------------------------------------- // isRecord // ------------------------------------------------------------------------------------- // $ExpectType { [x: string]: unknown; [x: symbol]: unknown; }[] unknowns.filter(_.isRecord) // ------------------------------------------------------------------------------------- // isReadonlyRecord // ------------------------------------------------------------------------------------- // $ExpectType { readonly [x: string]: unknown; readonly [x: symbol]: unknown; }[] unknowns.filter(_.isReadonlyRecord) ================================================ FILE: dtslint/ts4.8/Product.ts ================================================ import * as _ from "@fp-ts/core/typeclass/Product" import type { TypeLambda } from "@fp-ts/core/HKT" interface RAW { (r: R): () => Promise } interface RAWTypeLambda extends TypeLambda { readonly type: RAW } declare const fa: RAW<{ a: string }, "a", string> declare const fb: RAW<{ b: number }, "b", number> declare const fc: RAW<{ c: boolean }, "c", boolean> export declare const Product: _.Product // $ExpectType RAW<{ a: string; } & { b: number; } & { c: boolean; }, "a" | "b" | "c", [string, number, boolean]> _.tuple(Product)(fa, fb, fc) // $ExpectType RAW<{ a: string; } & { b: number; } & { c: boolean; }, "a" | "b" | "c", { fa: string; fb: number; fc: boolean; }> _.struct(Product)({ fa, fb, fc }) _.tuple(Product)() // should allow empty tuple _.struct(Product)({}) // should allow empty structs ================================================ FILE: dtslint/ts4.8/ReadonlyArray.ts ================================================ import { pipe } from '@fp-ts/core/Function' import * as RA from '@fp-ts/core/ReadonlyArray' import * as O from '@fp-ts/core/Option' declare const neras: RA.NonEmptyReadonlyArray declare const neas: RA.NonEmptyArray declare const ras: ReadonlyArray declare const as: Array // ------------------------------------------------------------------------------------- // isEmpty // ------------------------------------------------------------------------------------- if (RA.isEmpty(ras)) { // $ExpectType readonly [] ras } // $ExpectType
(c: readonly A[]) => Option O.liftPredicate(RA.isEmpty) // ------------------------------------------------------------------------------------- // isEmptyArray // ------------------------------------------------------------------------------------- if (RA.isEmptyArray(as)) { // $ExpectType [] as } // $ExpectType (c: A[]) => Option<[]> O.liftPredicate(RA.isEmptyArray) // ------------------------------------------------------------------------------------- // isNonEmpty // ------------------------------------------------------------------------------------- if (RA.isNonEmpty(ras)) { // $ExpectType readonly [number, ...number[]] ras } // $ExpectType (c: readonly A[]) => Option O.liftPredicate(RA.isNonEmpty) // ------------------------------------------------------------------------------------- // isNonEmptyArray // ------------------------------------------------------------------------------------- if (RA.isNonEmptyArray(as)) { // $ExpectType [number, ...number[]] as } // $ExpectType (c: A[]) => Option<[A, ...A[]]> O.liftPredicate(RA.isNonEmptyArray) // ------------------------------------------------------------------------------------- // map // ------------------------------------------------------------------------------------- // $ExpectType number[] RA.map(ras, n => n + 1) // $ExpectType number[] pipe(ras, RA.map(n => n + 1)) // $ExpectType number[] RA.map(as, n => n + 1) // $ExpectType number[] pipe(as, RA.map(n => n + 1)) // ------------------------------------------------------------------------------------- // mapNonEmpty // ------------------------------------------------------------------------------------- // $ExpectType [number, ...number[]] RA.mapNonEmpty(neras, n => n + 1) // $ExpectType [number, ...number[]] pipe(neras, RA.mapNonEmpty(n => n + 1)) // $ExpectType [number, ...number[]] RA.mapNonEmpty(neas, n => n + 1) // $ExpectType [number, ...number[]] pipe(neas, RA.mapNonEmpty(n => n + 1)) ================================================ FILE: dtslint/ts4.8/ReadonlyRecord.ts ================================================ import { pipe } from '@fp-ts/core/Function' import * as RR from '@fp-ts/core/ReadonlyRecord' declare const r: Record declare const struct: Record<'a' | 'b', number> // // map // // $ExpectType Record RR.map(r, ( value, // $ExpectType number _key, // $ExpectType string ) => value > 0) // $ExpectType Record pipe(r, RR.map(( value, // $ExpectType number _key, // $ExpectType string ) => value > 0)) // $ExpectType Record<"a" | "b", boolean> RR.map(struct, ( value, // $ExpectType number _key, // $ExpectType "a" | "b" ) => value > 0) // $ExpectType Record<"a" | "b", boolean> pipe(struct, RR.map(( value, // $ExpectType number _key, // $ExpectType "a" | "b" ) => value > 0)) const constStruct = { a: 1, b: 2 } as const; function mapToBoolean(): { [K in keyof typeof constStruct]: boolean } { return RR.map(constStruct, () => true); } // $ExpectType { readonly a: boolean; readonly b: boolean; } mapToBoolean() // // get // // $ExpectType Option pipe(r, RR.get('a')) // // replaceOption // // $ExpectType Option> pipe(r, RR.replaceOption('a', 2)) // $ExpectType Option> pipe(r, RR.replaceOption('a', true)) // // modifyOption // // $ExpectType Option> pipe(r, RR.modifyOption('a', () => 2)) // $ExpectType Option> pipe(r, RR.modifyOption('a', () => true)) ================================================ FILE: dtslint/ts4.8/SemiAlternative.ts ================================================ import * as _ from "@fp-ts/core/typeclass/SemiAlternative" import type { TypeLambda } from "@fp-ts/core/HKT" import { pipe } from "@fp-ts/core/Function" interface RAW { (r: R): () => Promise } interface RAWTypeLambda extends TypeLambda { readonly type: RAW } declare const fa: RAW<{ a: string }, string, "fa"> declare const fb: RAW<{ b: number }, number, "fb"> declare const SemiAlternative: _.SemiAlternative // $ExpectType RAW<{ a: string; } & { b: number; }, string | number, "fa" | "fb"> SemiAlternative.coproduct(fa, fb) ================================================ FILE: dtslint/ts4.8/SemiProduct.ts ================================================ import { OptionTypeLambda } from "@fp-ts/core/Option" import * as _ from "@fp-ts/core/typeclass/SemiProduct" export declare const SemiProduct: _.SemiProduct // $ExpectError _.nonEmptyTuple(SemiProduct)() // should not allow empty tuples // $ExpectError _.nonEmptyStruct(SemiProduct)({}) // should not allow empty structs ================================================ FILE: dtslint/ts4.8/Semigroup.ts ================================================ import * as _ from "@fp-ts/core/typeclass/Semigroup" import * as Number from "@fp-ts/core/Number" import * as String from "@fp-ts/core/String" // // tuple // // $ExpectType Semigroup _.tuple( String.Semigroup, Number.SemigroupSum ) // // struct // // $ExpectType Semigroup<{ readonly a: string; readonly b: number; }> _.struct({ a: String.Semigroup, b: Number.SemigroupSum }) ================================================ FILE: dtslint/ts4.8/Tuple.ts ================================================ import * as T from '@fp-ts/core/Tuple' import { pipe } from '@fp-ts/core/Function' // // tuple // // $ExpectType [string, number, boolean] T.tuple('a', 1, true) // // appendElement // // $ExpectType [string, number, boolean] pipe(T.tuple('a', 1), T.appendElement(true)) ================================================ FILE: dtslint/ts4.8/index.d.ts ================================================ ================================================ FILE: dtslint/ts4.8/index.ts ================================================ import * as _ from '../../src/HKT' // issue #536 function testIssue536( x: _.Kind ): _.Kind { // $ExpectError return x } ================================================ FILE: dtslint/ts4.8/tsconfig.json ================================================ { "compilerOptions": { "noEmit": true, "strict": true, "noImplicitAny": false, "noImplicitThis": true, "strictNullChecks": true, "strictFunctionTypes": true, "noImplicitReturns": false, "noUnusedLocals": false, "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", "target": "ES2021", "lib": ["ES2021"], "paths": { "@fp-ts/core": ["../../src/index.ts"], "@fp-ts/core/test/*": ["../../test/*"], "@fp-ts/core/examples/*": ["../../examples/*"], "@fp-ts/core/*": ["../../src/*"] } } } ================================================ FILE: dtslint/ts4.8/tslint.json ================================================ { "extends": "dtslint/dtslint.json", "rules": { "no-duplicate-imports": false, "semicolon": false, "array-type": false, "no-unnecessary-generics": false, "member-access": false, "no-empty-interface": false, "no-arg": false, "no-object-literal-type-assertion": false, "no-unnecessary-class": false, "radix": false, "no-angle-bracket-type-assertion": false, "object-literal-shorthand": false, "prefer-object-spread": false, "whitespace": false, "use-default-type-parameter": false, "no-relative-import-in-test": false, "no-null-undefined-union": false, "invalid-void": false, "max-line-length": false, "no-useless-files": false } } ================================================ FILE: guides/Either.md ================================================ # The `Either` data type The `Either` data type is a powerful and flexible tool for handling potentially failed computations in functional programming. It can be found in the `@fp-ts/core/Either` module, and it has two variants, `Left` and `Right`, which can be used to represent different outcomes. The `Left` variant is used to represent a failure, and it can contain useful information such as an error message or a failure code. The `Right` variant, on the other hand, is used to represent a successful outcome, and it can contain the result of the computation. Unlike the `Option` type, `Either` allows you to attach additional information to the failure case, making it more informative. In this usage, `None` is replaced with a `Left` which can contain useful information. `Right` takes the place of `Some`. # Definition The `Either` data type is the union of two members: `Left` and `Right`. The way chosen by the `@fp-ts/core` library to model this union in TypeScript is to use a feature of the language called [Discriminating Unions](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions). > A common technique for working with unions is to have a single field which uses literal types which you can use to let TypeScript narrow down the possible current type By convention in `@fp-ts/core`, this single field which uses literal types is named "\_tag" (but you can use any name when defining your unions). Furthermore, `Either` is a "polymorphic" data type, that is, it makes use of a feature of TypeScript named ["Generics"](https://www.typescriptlang.org/docs/handbook/2/generics.html), meaning that the `Either` data type is a container that can hold any type. Here's the complete definition of the `Either` type: ```ts // Holds the information for a failure case export type Left = { // Discriminating field used to identify the variant readonly _tag: "Left"; // The actual error readonly left: E; }; // Holds the result of a successful computation export type Right = { // Discriminating field used to identify the variant readonly _tag: "Right"; // The actual value readonly right: A; }; export type Either = Left | Right; ``` The `Either` data type is defined as a union of two other types, `Left` and `Right`, that represent the two possible outcomes of a computation: a failure or a success. The type parameters `E` and `A` are used to specify the type of the failure value and the success value that the `Either` holds respectively. The `_tag` field is used to distinguish between the two variants, `Left` and `Right`. # Using `Either` To create an instance of `Either`, you can use the `right` and `left` constructors, which construct a new `Either` holding a `Right` or `Left` value respectively. ```ts import { left, right } from "@fp-ts/core/Either"; const success: Either = right(1); const failure: Either = left("error message"); ``` Let's summarize the two cases in a table: **Cheat sheet** (constructors) | Name | Given | To | | ------- | ----- | ------------------ | | `right` | `A` | `Either` | | `left` | `E` | `Either` | # Conversions You can also use the `fromOption` function to convert an `Option` to an `Either`. ```ts import { Either, fromOption } from "@fp-ts/core/Either"; import { none, some } from "@fp-ts/core/Option"; const success: Either = fromOption( some(1), () => "error message" ); const failure: Either = fromOption( none(), () => "error message" ); ``` The `fromOption` function requires a second argument because it needs to know what value to use for the `Left` variant of the `Either` type when given a `None`. In the example, the argument "error message" is used as the value for the `Left` variant when `None` is encountered. This allows `Either` to provide more information about why a failure occurred. **Cheat sheet** (conversions) | Name | Given | To | Note | | -------------- | ------------------------------------ | ------------------ | ------------------- | | `fromOption` | `Option`, `onNone: LazyArg` | `Either` | | | `toOption` | `Either` | `Option` | | | `getRight` | `Either` | `Option` | alias of `toOption` | | `getLeft` | `Either` | `Option` | | | `toRefinement` | `A => Either` | `Refinement` | | | `fromIterable` | `Iterable`, `onEmpty: LazyArg` | `Either` | | | `toArray` | `Either` | `Array` | | # Working with `Either` Once you have an instance of `Either`, you can use the various functions provided in the `@fp-ts/core/Either` module to work with it. The `map` function can be used to transform the `Right` values: ```ts import { pipe } from "@fp-ts/core/Function"; import { Either, right, map } from "@fp-ts/core/Either"; const success: Either = pipe( right(1), map((x) => x + 1) ); // right(2) ``` As you can see you can transform the result of your computation without unwrapping and wrapping the underlying value of `Either`. What is very convenient about `Either` is how the absence of value (i.e. a `Left`) is handled. See the example below: ```ts import { pipe } from "@fp-ts/core/Function"; import { Either, left, map } from "@fp-ts/core/Either"; const failure: Either = pipe( left("error"), // tries to map the value inside the `Right`, but it does not exist, resulting in `Left` map((x) => x + 1) ); ``` As you can see, even though we started with a `Left` value, we can still operate on our `Either`. No errors are thrown or shown to the user, unless we do it intentionally. What happens is that when the `Either` is `Left`, the mapping doesn't even happen and the `Left` value representing the failed computation is returned unchanged. In case you want to map the value contained in the `Left`, for example to change the type of error you want to express, you can use the `mapLeft` API which acts like `map` but this time on the `Left` part of an `Either`: ```ts import { pipe } from "@fp-ts/core/Function"; import { Either, left, mapLeft } from "@fp-ts/core/Either"; const failure: Either = pipe( left("error message"), mapLeft((x) => x + "!") ); // left("error message!") ``` # Handling failing computations Let's see how to use the `Either` data type to model a computation that can fail, such as a function that can throw an exception based on certain conditions. Let's take the case of the following function: ```ts function parseNumber(s: string): number { const n = parseFloat(s); if (isNaN(n)) { throw new Error(`Cannot parse '${s}' as a number`); } return n; } ``` An alternative to throwing an exception is to always return a value, but this value will be of type `Either` instead of `number`, with the following interpretation: - if `parseNumber` returns a `Left` value, it means that the computation failed, and the `Left` contains an error message or other information about the failure - if the result is instead a `Right` value, it means that the computation succeeded and the computed value is wrapped inside the `Right` Let's see how we can rewrite the `parseNumber` function without throwing exceptions and using the `Either` data type instead: ```ts import { Either, left, right } from "@fp-ts/core/Either"; function parseNumber(s: string): Either { const n = parseFloat(s); return isNaN(n) ? left(`Cannot parse '${s}' as a number`) : right(n); } console.log(parseNumber("2")); // right(2) console.log(parseNumber("Not a number")); // left("Cannot parse 'Not a number' as a number") ``` What happens if we add a call to the `parseNumber` function to a pipeline that already involves an `Either`? ```ts const result = pipe( right("2"), map((s) => parseNumber(s)), map((n) => n2) // type-checker error! ); ``` There's something wrong, we received an error from the type checker, what happened? The problem is that in the second `map` the parameter `n` is of type `Either` and not `number`. ```ts const result = pipe( right("2"), map((s) => parseNumber(s)), map((x: Either) => ...) ); ``` Fortunately, the fix is simple, when adding a computation that returns an `Either` to our pipeline we should use the `flatMap` function instead of the `map` function: ```ts import { pipe } from "@fp-ts/core/Function"; import { right, flatMap, map } from "@fp-ts/core/Either"; const result = pipe( right("2"), flatMap((s) => parseNumber(s)), map((n) => n2) // ok! now `n` has type `number` ); ``` Let's summarize the two cases in a table: **Cheat sheet** (sequencing) | Name | Given | To | | --------- | -------------------------------------- | --------------------- | | `map` | `Either`, `A => B` | `Either` | | `flatMap` | `Either`, `E1 => Either` | `Either` | The `flatMap` function offers the same convenience as the `map` function, which only continues with the computations contained in the pipeline if a `Left` value is **not** encountered: **Happy path, starting with a valid input** ```ts import { pipe } from "@fp-ts/core/Function"; import { Either, right, flatMap, map } from "@fp-ts/core/Either"; const success: Either = pipe( right("2"), flatMap((s) => parseNumber(s)), // parse the input to number map((x) => x2), // double the parsed number map((x) => x - 3) // subtract 3 ); // right(1) ``` **Error path, starting with an invalid input** ```ts import { pipe } from "@fp-ts/core/Function"; import { Either, right, flatMap, map } from "@fp-ts/core/Either"; const failure: Either = pipe( right("Not a number"), flatMap((s) => parseNumber(s)), // parse the input to number map((x) => x2), // This will not be executed because parseNumber will return Left map((x) => x - 3) // This will not be executed ); // left("Cannot parse 'Not a number' as a number") ``` **Error path, starting with None** ```ts import { pipe } from "@fp-ts/core/Function"; import { Either, left, flatMap, map } from "@fp-ts/core/Either"; const leftStart: Either = pipe( left("error message"), flatMap((s) => parseNumber(s)), // This will not be executed because it starts with Left map((x) => x2), // This will not be executed map((x) => x - 3) // This will not be executed ); // left("error message") ``` When using this approach, the **desired outcome** is always in clear view while defining your pipeline. This allows you to focus on the expected result, while leaving it to `Either` to handle any potential errors that may arise seamlessly and transparently. You can focus on the successful scenario and let `Either` handle the tedious task of managing potential errors at every step of the pipeline, without the need for explicit handling. # Debugging At any time, it is possible to inspect what is happening in your pipeline using two utility functions: **Cheat sheet** (debugging) | Name | Given | To | Note | | -------------- | --------------------------- | -------------- | ------------------------------------- | | `inspectRight` | `Either`, `A => void` | `Either` | callback called if it is a `Right` | | `inspectLeft` | `Either`, `E => void` | `Either` | callback called if it is a `Left` | Let's see an example where both are in action: ```ts import { pipe } from "@fp-ts/core/Function"; import { Either, right, inspectRight, flatMap, inspectLeft, map, } from "@fp-ts/core/Option"; const failure: Either = pipe( right("Not a number"), inspectRight(console.log), flatMap((s) => parseNumber(s)), inspectLeft(console.error), map((x) => x2), map((x) => x - 3) ); // "Not a number" // "Cannot parse 'Not a number' as a number" ``` Please note that these two functions should only be used for debugging purposes and it is not recommended to use them for performing side effects or encoding business logic. # Pattern matching and error handling We have seen how easy and convenient it is to build pipelines involving the `Either` data type, leaving it to handle any errors that may occur at any step. However, at some point, you will be interested in manually handling the error to understand the overall result obtained from the pipeline and decide what to do accordingly. The fastest way to get the value wrapped in an `Either` is to call the `getOrThrow` function, but be aware that, as the name suggests, an exception will be thrown in case the `Either` you are querying is a `Left`: ```ts import { getOrThrow } from "@fp-ts/core/Either"; console.log(getOrThrow(right(10)); // 10 console.log(getOrThrow(left("error message")); // throws new Error("getOrThrow called on a Left") ``` A more safe alternative is using the `isRight` and `isLeft` guards: ```ts import { right, left, isRight, isLeft } from "@fp-ts/core/Either"; const success = some(1); // Use the `isRight` function to check if the `success` is an instance of `Right` if (isRight(success)) { console.log(`Either has a value: ${success.right}`); } else { console.log(`Either is a Left.`); } // Either has a value: 1 const failure = left("error message"); // Use the `isLeft` function to check if the `failure` is an instance of `Left` if (isLeft(failure)) { console.log(`Either has error: ${failure.left}`); } else { console.log(`Either is a Right.`); } // Either has error: error message ``` Another alternative is [pattern matching](https://github.com/gvergnaud/ts-pattern#what-is-pattern-matching) on the `Either`. The `match` function allows us to match on the `Left` and `Right` cases of an `Either` value and provide different actions for each. ```ts import { pipe } from "@fp-ts/core/Function"; import { right, match } from "@fp-ts/core/Either"; const either = right(1); /** * Use the `match` function to conditionally return a string based on whether the `Either` is `Left` or `Right`. * If the `Either` is `Left`, the `left` will be passed to the first function. * If the `Either` is `Right`, the `right` will be passed to the second function. */ const output = match( option, (left) => `Either has error. ${left}`, (right) => `Either has a value: ${right}` ); console.log(output); // Either has a value: 1 ``` One reason to use `match` instead of `isRight` or `isLeft` is that `match` is more expressive and provides a clear way to handle both cases of an `Either`. With `match`, you can directly provide two functions to handle the case of the `Either` being `Left` or `Right`, respectively. On the other hand, with `isRight` or `isLeft`, you would need to manually check the value and take separate actions based on whether it's `Right` or `Left`. With `match`, the code can be more concise and easy to understand. Additionally, if you have complex logic to handle both cases, using `match` can make the code easier to read and maintain. There are specializations of `match` to make working with code that does not use `Either` more convenient and faster, particularly `getOrNull` and `getOrUndefined`. ```ts import { getOrNull, getOrUndefined, right, left } from "@fp-ts/core/Either"; getOrNull(right(5)); // 5 getOrNull(left("error")); // null getOrUndefined(right(5)); // 5 getOrUndefined(left("error")); // undefined ``` For greater flexibility, there is also the `getOrElse` function which allows you to set what value corresponds to the `Left` case: ```ts import { getOrElse, right, left } from "@fp-ts/core/Either"; getOrElse(right(5), () => 0); // 5 getOrElse(left("error"), () => 0); // 0 ``` It often happens that the action you want to take when a computation returns `None` is to continue with another computation that returns an `Option`, in this case you can use the `orElse` API: ```ts import { pipe } from "@fp-ts/core/Function"; import { Either, some, none, orElse } from "@fp-ts/core/Either"; const fetchData = (): Either => { // Imagine we have a function that returns an `Either` of data return Math.random() < 0.5 ? right("Data fetched successfully") : left("Data fetched unsuccessfully"); }; const retryFetchData = (): Either => pipe( fetchData(), // Call the function for the first time orElse(() => fetchData()) // If it fails, call it again ); const result = retryFetchData(); ``` **Cheat sheet** (error handling) | Name | Given | To | | ---------------- | --------------------------------------------------- | -------------------- | | `match` | `Either`, `onLeft: E => B`, `onRight: A => C` | `B \| C` | | `getOrThrow` | `Either` | `A` (may throw) | | `getOrNull` | `Either` | `A \| null` | | `getOrUndefined` | `Either` | `A \| undefined` | | `getOrElse` | `Either`, `onLeft: E => B` | `A \| B` | | `orElse` | `Either`, `LazyArg>` | `Either` | | `firstRightOf` | `Either`, `Iterable>` | `Either` | # Interop A need that arises quickly when using the `Either` data type is the ability to interoperate with code that does not share the same style, in particular code that for example uses `undefined` or `null` to indicate that a value is optional, or code that throws exceptions. The `Either` data type offers a series of APIs to make this task easier, let's start with the first of the two cases, that is when the need is to interoperate with code that use a nullable type to indicate that a value is optional. It is possible to create an `Eitehr` from a nullable value using the `fromNullable` API, let's see an example: ```ts import { fromNullable, right, left } from "@fp-ts/core/Either"; console.log(fromNullable(null, () => "error")); // left("erro") console.log(fromNullable(undefined, () => "error")); // left("erro") console.log(fromNullable(1, () => "error")); // right(1) ``` Instead of a single value, we can also modify the definition of a function that returns a nullable value to a function that returns an `Either` (a process that goes by the name of "lifting"): ```ts import { liftNullable, left, right } from "@fp-ts/core/Either"; const parse = (s: string): number | undefined => { const n = parseFloat(s); return isNaN(n) ? undefined : n; }; // const parseEither: (s: string) => Either const parseEither = liftNullable( parse, (s) => `Cannot parse '${s}' as a number` ); console.log(parseEither("1")); // right(1) console.log(parseEither("not a number")); // left("Cannot parse 'not a number' as a number") ``` On the other hand, if we have a value of type `Either` and we want to convert it into a nullable value we have two possibilities: - convert `Left` to `null` - convert `Left` to `undefined` The two APIs `getOrNull` and `getOrUndefined` respectively achieve these two tasks: ```ts import { getOrNull, getOrUndefined, right, left } from "@fp-ts/core/Either"; console.log(getOrNull(right(1))); // 1 console.log(getOrNull(left("error message"))); // null console.log(getOrUndefined(right(1))); // 1 console.log(getOrUndefined(left("error message"))); // undefined ``` **Cheat sheet** (interop - nullable) | Name | Given | To | | ----------------- | ----------------------------------------------------------------- | --------------------------------------- | | `fromNullable` | `A`, `A => E` | `Either>` | | `liftNullable` | `(...a: A) => B \| null \| undefined`, `(...a: A) => E` | `(...a: A) => Either` | | `flatMapNullable` | `Either`, `(...a: A) => B \| null \| undefined`, `A => E2` | `Either>` | | `getOrNull` | `Either` | `A \| null` | | `getOrUndefined` | `Either` | `A \| undefined` | | `merge` | `Either` | `E \| A` | Now let's see the other case, that is when we need to interoperate with code that throws exceptions. In a previous section, we saw how to convert the following function that can throw exceptions: ```ts function parseNumber(s: string): number { const n = parseFloat(s); if (isNaN(n)) { throw new Error(`Cannot parse '${s}' as a number`); } return n; } ``` into a function that returns a `Option`: ```ts import { Either, left, right } from "@fp-ts/core/Either"; function parseNumber(s: string): Either { const n = parseFloat(s); return isNaN(n) ? left(`Cannot parse '${s}' as a number`) : right(n); } ``` However, this involves tedious, error-prone, and boilerplate-heavy work. It would be much more convenient not to have to rewrite the `parseNumber` function from scratch but only to transform it into the desired result in one step, and that's exactly what the `fromThrowable` API takes care of doing: ```ts import { liftThrowable } from "@fp-ts/core/Either"; const parse = liftThrowable(JSON.parse, () => "parse error"); console.log(parse("1")); // right(1) console.log(parse("")); // left("parse error") ``` On the other hand, if we have a value of type `Option` and want to get the wrapped value, accepting the fact that if the `Option` is a `None` we will get an exception, we can use the `getOrThrow` API: ```ts import { getOrThrow, right, left } from "@fp-ts/core/Either"; console.log(getOrThrow(right(10)); // 10 console.log(getOrThrow(left("error message")); // throws new Error("getOrThrow called on a Left") ``` **Cheat sheet** (interop - throwing) | Name | Given | To | | --------------- | -------------------------------------------- | --------------------------- | | `liftThrowable` | `(...a: A) => B` (may throw), `unknown => E` | `(...a: A) => Either` | | `getOrThrow` | `Either` | `A` (may throw) | # Combining two or more `Either`s The `zipWith` function allows you to combine two `Either`s using a provided function. The resulting value is a new `Either` that holds the combined value of both original `Either`s. Let's consider the following example where we have two `Either`s that hold values of two different types, `string` and `number`: ```ts import { Either, right } from "@fp-ts/core/Either"; const name: Either = right("John"); const age: Either = right(25); ``` If we want to combine these two `Either`s into a single `Either` that holds an object with properties `name` and `age`, we can use the `zipWith` function: ```ts import { zipWith } from "@fp-ts/core/Either"; const combine = zipWith(name, age, (n, a) => ({ name: n, age: a })); console.log(combine); // right({ name: 'John', age: 25 }) ``` The `zipWith` function takes three arguments: the two `Either`s that you want to combine, and a function that takes two arguments - the values held by the two `Either`s - and returns the combined value. If either of the two `Either`s is `Left`, the resulting `Either` will be `Left` as well: ```ts const name: Either = left("missing name"); const age: Either = right(25); const combine = zipWith(name, age, (n, a) => ({ name: n, age: a })); console.log(combine); // left("missing name") ``` This is because the `zipWith` function only combines the values if both `Either`s are `Right`. **Cheat sheet** (combining) | Name | Given | To | | --------------- | ----------------------------------------------- | ---------------------------------------------- | | `zipWith` | `Either`, `Either`, `(A, B) => C` | `Either` | | `tuple` | `[Either, Either, ...]` | `Either` | | `struct` | `{ a: Either, b: Either, ... }` | `Either` | | `all` | `Iterable>` | `Either` | | `appendElement` | `Either`, `Either` | `Either` | | `ap` | `Either B>`, `Either` | `Either` | For convenience, a series of algebraic operations such as sums and products are exported. ```ts import { right, left, sum } from "@fp-ts/core/Either"; const num1 = right(3); const num2 = right(4); const num3 = left("not a number"); // Summing two `Right` values will result in a `Right` with the sum of the values const sumOfRight = sum(num1, num2); console.log(sumOfRight); // right(7) // Summing a `Right` and a `Left` will result in a `Left` const sumOfRightAndLeft = sum(num1, num3); console.log(sumOfRightAndLeft); // left("not a number") ``` **Cheat sheet** (algebraic operations) | Name | Given | To | | ---------- | ------------------------------------------ | -------------------------- | | `sum` | `Either`, `Either` | `Either` | | `multiply` | `Either`, `Either` | `Either` | | `subtract` | `Either`, `Either` | `Either` | | `divide` | `Either`, `Either` | `Either` | # Validations Say you must implement a web form to signup for an account. The form contains two field: `username` and `password` and the following validation rules must hold: - `username` must not be empty - `username` can't have dashes in it - `password` needs to have at least 6 characters - `password` needs to have at least one capital letter - `password` needs to have at least one number The `Either` type represents a computation that might fail with an error of type `E` or succeed with a value of type `A`, so is a good candidate for implementing our validation rules. For example let's encode each `password` rule: ```ts import * as E from "@fp-ts/core/Either"; const minLength = (s: string): E.Either => s.length >= 6 ? E.right(s) : E.left("at least 6 characters"); const oneCapital = (s: string): E.Either => /[A-Z]/g.test(s) ? E.right(s) : E.left("at least one capital letter"); const oneNumber = (s: string): E.Either => /[0-9]/g.test(s) ? E.right(s) : E.left("at least one number"); ``` We can chain all the rules using `flatMap`: ```ts import { pipe } from "@fp-ts/core/Function"; const validatePassword = (s: string): E.Either => pipe(minLength(s), E.flatMap(oneCapital), E.flatMap(oneNumber)); ``` Because we are using `Either` the checks are **fail-fast**. That is, any failed check shortcircuits subsequent checks so we will only ever get one error. ```ts assert.deepStrictEqual(validatePassword("ab"), E.left("at least 6 characters")); assert.deepStrictEqual( validatePassword("abcdef"), E.left("at least one capital letter") ); assert.deepStrictEqual( validatePassword("Abcdef"), E.left("at least one number") ); ``` However this could lead to a bad UX, it would be nice to have all of these errors be reported simultaneously. The `Validated` abstraction may help here. ## Validated Validations are similar to `Either`, where they represent a computation that may fail with an error of type `E` or succeed with a value of type `A`. Unlike typical computations involving `Either`, however, validations are capable of **accumulating multiple failures**. For this to be possible, the `Validated` data type must have the ability to combine two or more values of type `E` and the simplest way is to wrap them in a (non-empty) `ReadonlyArray`. This is the definition of the `Validated` data type: ```ts /** * Represents a computation that may fail with one or more errors of type `E` * or succeed with a value of type `A`. */ export type Validated = Either, A>; ``` To proceed, we must first modify all the rules so that they return a `Validated` value. Instead of having to rewrite all previous functions, which can be cumbersome, we can use the `liftEither` helper. This helper converts a check that outputs an `Either` into a check that outputs a `Validate`. ```ts const minLengthValidated = E.liftEither(minLength); // ^? const minLengthValidated: (s: string) => E.Validated const oneCapitalValidated = E.liftEither(oneCapital); // ^? const oneCapitalValidated: (s: string) => E.Validated const oneNumberValidated = E.liftEither(oneNumber); // ^? const oneNumberValidated: (s: string) => E.Validated ``` Let's bring it all together. The `validatePassword` function takes a string `s` as input, and uses the `tupleValidated` helper to perform all three validation checks, returning a `Validated` value that collects all the validation error messages. If all the checks pass, the function returns the original string s as a successful `Validated` value: ```ts const validatePassword = (s: string): E.Validated => pipe( E.tupleValidated( minLengthValidated(s), oneCapitalValidated(s), oneNumberValidated(s) ), E.map(() => s) ); assert.deepStrictEqual( validatePassword("ab"), E.left([ "at least 6 characters", "at least one capital letter", "at least one number", ]) ); assert.deepStrictEqual(validatePassword("Abcde6"), E.right("Abcde6")); ``` ================================================ FILE: guides/FAQ.md ================================================ # FAQ ## HKT implementation **What’s that second branch of conditional type in `Kind` type?** That's to enforce variance. For example let's say we define the following typeclass ```ts import { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT"; export interface Zippable extends TypeClass { readonly zip: ( first: Kind, second: Kind ) => Kind; } ``` and then derive a `pipe`-able version of `zip` ```ts export const zip = (Zippable: Zippable) => (that: Kind) => ( self: Kind ): Kind => Zippable.zip(self, that); ``` Now let's say we make a mistake while typing the return type of `zip` (`R1` instead of `R1 & R2`) ```diff - ): Kind => + ): Kind => ``` It doesn't type check with the following error ``` Type 'Kind' is not assignable to type 'Kind'. Type '(F & { readonly InOut1: S; readonly In1: R1 & R2; readonly Out3: O2 | O1; readonly Out2: E2 | E1; readonly Out1: readonly [A, B]; })["type"] | { readonly F: F; ... 4 more ...; readonly Out1: () => readonly [...]; }' is not assignable to type 'Kind'. Type 'F["type"]' is not assignable to type 'Kind'. Type '{ readonly F: F; readonly InOut1: (_: S) => S; readonly In1: (_: R1 & R2) => void; readonly Out3: () => O2 | O1; readonly Out2: () => E2 | E1; readonly Out1: () => readonly [A, B]; }' is not assignable to type '{ readonly F: F; readonly InOut1: (_: S) => S; readonly In1: (_: R1) => void; readonly Out3: () => O2 | O1; readonly Out2: () => E2 | E1; readonly Out1: () => readonly [A, B]; }'. Types of property 'In1' are incompatible. Type '(_: R1 & R2) => void' is not assignable to type '(_: R1) => void'. Types of parameters '_' and '_' are incompatible. Type 'R1' is not assignable to type 'R1 & R2'. ``` ================================================ FILE: guides/Option.md ================================================ # The `Option` data type The `Option` data type represents an optional value: every `Option` is either `Some` and contains a value, or `None`, and does not. `Option` types are very common in functional programming, as they have a number of uses: - Initial values - Return values for functions that are not defined over their entire input range (partial functions) - Return value for otherwise reporting simple errors, where `None` is returned on error - Optional struct fields - Optional function arguments # Definition The `Option` data type is a union of two members: `None` and `Some`. The `@fp-ts/core` library models this union in TypeScript using a feature called [Discriminating Unions](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminatory-unions). A common approach for working with unions is to have a single field that uses literal types, which helps TypeScript narrow down the possible current type. In `@fp-ts/core`, this single field is named "\_tag" (but any name can be used when defining your own unions). The `Option` data type is a "polymorphic" data type, which makes use of a feature of TypeScript named ["Generics"](https://www.typescriptlang.org/docs/handbook/2/generics.html). This means that the `Option` data type is a container that can hold any type. Here is the complete definition of the `Option` data type: ```ts // Represents the absence of a value export type None = { // Discriminating field used to identify the variant readonly _tag: "None"; }; // Represents the presence of a value export type Some = { // Discriminatory field used to identify the variant readonly _tag: "Some"; // The actual value readonly value: A; }; // Define the `Option` data type as the union of `None` and `Some` export type Option = None | Some; ``` The type parameter `A` is used to specify the type of the `value` that the `Option` holds. The `_tag` field is used to distinguish between the two variants, `None` and `Some`. # Using `Option` The `Option` data type can be used to handle the presence or absence of a value in a safe and predictable manner. The `Option` data type has two constructors `some` and `none` that can be used to create a new instance of `Option` holding either a `Some` value or a `None` value, respectively. ## Constructing a `Some` value The `some` constructor takes a value of type `A` and returns an instance of `Option` that holds that value: ```ts import { some } from "@fp-ts/core/Option"; const value: Option = some(1); // an Option holding the number 1 ``` ## Constructing a `None` value The `none` constructor returns an instance of `Option representing the absence of a value: ```ts import { none } from "@fp-ts/core/Option"; const empty: Option = none(); // an Option holding no value ``` By default, `none` returns an instance of `Option`, which can be assigned to any `Option` regardless of the type `A`: ```ts const optionNumber: Option = none(); const optionString: Option = none(); const optionBoolean: Option = none(); ``` However, if you prefer, you can specify the desired type at the call site by explicitly indicating the type `A` you're interested in. In this case, you won't need to provide type annotations: ```ts const optionNumber = none(); const optionString = none(); const optionBoolean = none(); ``` Here's a quick reference guide for the two constructors: **Cheat sheet** (constructors) | **Function** | **Given input** | **Resulting Output** | | ------------ | --------------- | -------------------- | | `some` | `A` | `Option` | | `none` | | `Option` | With these two constructors, you can construct an `Option` holding either a `Some` value or a `None` value, depending on your needs. # Conversions The following table provides a quick reference for the various conversion functions available in this module: **Cheat sheet** (conversions) | **Function** | **Given input** | **Resulting Output** | | -------------- | --------------------------------- | -------------------- | --------------------- | | `fromEither` | `Either` | `Option` | | | `toEither` | `Option`, `onNone: LazyArg` | `Either` | | | `getRight` | `Either` | `Option` | alias of `fromEither` | | `getLeft` | `Either` | `Option` | | | `toRefinement` | `A => Option` | `Refinement` | | | `fromIterable` | `Iterable` | `Option` | | | `toArray` | `Option` | `Array` | | ## fromEither The `fromEither` function takes in an `Either` value and returns an `Option`. This is useful when you have a value that can either be of type `E` (an error) or `A` (the correct value), and you want to convert it to an `Option` discarding the error. Example: ```ts import * as O from "@fp-ts/core/Option"; import * as E from "@fp-ts/core/Either"; console.log(O.fromEither(E.right(1))); // some(1) console.log(O.fromEither(E.left("error message"))); // none() ``` In this example, `fromEither` is used to convert the `Either` value `E.right(1)` to an `Option`. The result is `some(1)`, which indicates that the input `Either` was of type `Right` and contained the value `1`. If the input `Either` was of type `Left` (`E.left("error message")` in this case), the result would be `none()`, which indicates that the input contained an error and no valid value was present. ## toEither The `toEither` function takes in an `Option` value and a `LazyArg` value and returns an `Either`. The `LazyArg` value is a lazy (or "deferred") argument that is only executed if the input `Option` is `None`. If the input `Option` is `None`, the `toEither` function returns an `Either` with the `Left` value being the result of the lazy argument. If the input `Option` is `Some`, the `toEither` function returns an `Either` with the `Right` value being the value contained in the `Some` case of the `Option`. Here's an example of how to use toEither: ```ts import { pipe } from "@fp-ts/core/Function"; import * as O from "@fp-ts/core/Option"; import * as E from "@fp-ts/core/Either"; const onNone = () => "error"; console.log(pipe(O.some(1), O.toEither(onNone))); // right(1) console.log(pipe(O.none(), O.toEither(onNone))); // left("error") ``` ## getRight The `getRight` function is an alias for `fromEither`, and is used to convert an `Either` value to an `Option`. See the explanation and example for `fromEither` for more information. ## getLeft The `getLeft` function is a utility function that is used to extract the `Left` value from an `Either` value. The function takes in a single argument - an `Either` value and returns an `Option` value. ```ts import * as O from "@fp-ts/core/Option"; import * as E from "@fp-ts/core/Either"; console.log(O.getLeft(E.right("ok"))); // none() console.log(O.getLeft(E.left("error"))); // some("error") ``` Note that the `Option` value returned by the `getLeft` function will be `Some(value)` if the input `Either` value is a `Left` value, and `None` if the input `Either` value is a `Right` value. ## toRefinement This function allows to convert a function `A => Option` into a `(a: A) => a is B`, which can be used as a predefined type guard. A type guard function is used to check if a value is of a certain type. The `toRefinement` ensures that a type guard definition is type-safe. Here is an example of using `toRefinement` to create a type guard for positive numbers: ```ts import * as O from "@fp-ts/core/Option"; // This function checks if a given number is positive const parsePositive = (n: number): O.Option => n > 0 ? O.some(n) : O.none(); // convert the `parsePositive` function into a type guard const isPositive = O.toRefinement(parsePositive); console.log(isPositive(1)); // true console.log(isPositive(-1)); // false ``` In this example, `parsePositive` is a function that takes in a number and returns an `Option`. If the number is positive, it returns `some(n)`, where `n` is the positive number. If the number is not positive, it returns `none()`. `toRefinement` takes in the `parsePositive` function and returns a type guard function `isPositive`. The `isPositive` function can be used to check if a value is a positive number and can be used in type refinement statements to provide type-safety for your code. ## fromIterable The `fromIterable` function takes an iterable (something you can loop over, for example arrays, sets, maps, etc.) and returns an `Option` value. If the iterable is not empty (i.e., it has at least one item), `fromIterable` returns the first value of the iterable wrapped in a `Some` value. If the iterable is empty, `fromIterable` returns `None`. Here are two examples to demonstrate the usage of `fromIterable`: ```ts import { fromIterable, some, none } from "@fp-ts/core/Option"; console.log(fromIterable([1, 2, 3])); // some(1) ``` In this example, `fromIterable` is passed an array with three values. Since the array is not empty, `fromIterable` returns the first value, `1`, wrapped in a `Some` value. ```ts console.log(fromIterable([])); // none() ``` In this example, `fromIterable` is passed an empty array. Since the array is empty, `fromIterable` returns `None`. ## toArray The `toArray` function takes in an `Option` value and returns an array. If the input is a `Some` value, the value inside the `Some` is wrapped in an array and returned. If the input is a `None` value, an empty array is returned. Here are two examples of how `toArray` can be used: ```ts import * as O from "@fp-ts/core/Option"; console.log(O.toArray(O.some(1))); // [1] ``` In this example, `some(1)` is passed as the argument to `toArray`, which returns an array with the value `1`. ```ts console.log(O.toArray(O.none())); // [] ``` In this example, `none()` is passed as the argument to `toArray`, which returns an empty array. # Modeling optional properties with `Option` Here is an example of a `User` model where the `email` field is of type `Option`. This means that the value of the `email` field may or may not be present and will be of type `string` when it is present. ```ts interface User { id: number; username: string; email: Option; } import { some, none } from "@fp-ts/core/Option"; // case with email const user1: User = { id: 1, username: "john_doe", email: some("john.doe@example.com"), }; // case without email const user2: User = { id: 2, username: "jane_doe", email: none(), }; ``` It's important to note that the optionality only concerns the **value** of the `email` field, while the key `"email"` will always be present in the object. # Working with `Option` Once you have an instance of `Option`, you can use the various functions provided in the `@fp-ts/core/Option` module to work with it. The `map` function can be used to transform the `Some` values: ```ts import { pipe } from "@fp-ts/core/Function"; import { Opiton, some, map } from "@fp-ts/core/Option"; const success: Option = pipe( some(1), // maps the value inside the Option, adding 1, resulting in some(2) map((x) => x + 1) ); ``` As you can see you can transform the result of your computation without unwrapping and wrapping the underlying value of `Option`. This allows for a safe and convenient way of transforming optional values. What is also convenient about `Option` is how the absence of value (i.e. a `None`) is handled. See the example below: ```ts import { pipe } from "@fp-ts/core/Function"; import { Option, none, map } from "@fp-ts/core/Option"; const failure: Option = pipe( none(), // tries to map the value inside the `Some`, but it does not exist, resulting in `None` map((x) => x + 1) ); ``` As you can see, even though we started with a `None` value, we can still operate on our `Option`. No errors are thrown or shown to the user, unless we do it intentionally. When the `Option` is `None, the mapping doesn't even occur, and the `None` value representing the absence of value is returned unchanged. # Handling failing computations In software development, there are times when a function can "fail" to produce a result, either because of invalid inputs, lack of data, or other reasons. The `Option` data type helps us to handle these cases in a clean and functional way. Here's an example of a function `parseNumber` that takes a `string` as input and returns either a `number` or `null` depending on the input: ```ts function parseNumber(s: string): number | null { const n = parseFloat(s); if (isNaN(n)) { return null; } return n; } ``` A better way to handle these types of computations is to use the `Option` data type. This data type offers a cleaner way to model the "success" or "failure" of a computation. With `Option`, we can eliminate the need to return a `null` value. Instead, we will always return a value, but this value will be of type `Option`. - if `parseNumber` returns a `None` value, it means that the computation "failed" - if the result is a `Some` value, it means that the computation "succeeded" and the computed value is wrapped inside the `Some` Here's how the `parseNumber` function would look using the `Option` data type: ```ts import { Option, none, some } from "@fp-ts/core/Option"; function parseNumber(s: string): Option { const n = parseFloat(s); return isNaN(n) ? none() : some(n); } console.log(parseNumber("2")); // some(2) console.log(parseNumber("Not a number")); // none() ``` Now, let's say we have a pipeline of computations that already involves the `Option` data type and we want to add a call to the `parseNumber` function. We might run into an issue with the following code: ```ts import { pipe } from "@fp-ts/core/Function"; import { some, map } from "@fp-ts/core/Option"; const result = pipe( some("2"), map((s) => parseNumber(s)), map((n) => n2) // type-checker error! ); ``` The code above generates a type-checker error. This happens because the second `map` function expects the input `n` to be of type `number`, but `n` is of type `Option`. ```ts const result = pipe( some("2"), map((s) => parseNumber(s)), map((x: Option) => ...) ); ``` To solve this issue, we need to use the `flatMap` function instead of the `map` function when adding a computation that returns an `Option` to our pipeline: ```ts import { pipe } from "@fp-ts/core/Function"; import { some, flatMap, map } from "@fp-ts/core/Option"; const result = pipe( some("2"), flatMap((s) => parseNumber(s)), map((n) => n2) // ok! now `n` has type `number` ); ``` Let's summarize the two cases in a table: **Cheat sheet** (sequencing) | **Function** | **Given input** | **Resulting Output** | | ------------ | ----------------------------- | -------------------- | | `map` | `Option`, `A => B` | `Option` | | `flatMap` | `Option`, `A => Option` | `Option` | The `flatMap` function works similarly to the `map` function, but with the added feature of only continuing with the computations if a `None` value is not encountered. Let's look at some code examples to understand how these functions work in practice. **Example 1: Successful Path with Valid Input** ```ts import { pipe } from "@fp-ts/core/Function"; import { Option, some, flatMap, map } from "@fp-ts/core/Option"; const success: Option = pipe( some("2"), flatMap((s) => parseNumber(s)), // parse the input to number map((x) => x2), // double the parsed number map((x) => x - 3) // subtract 3 ); // some(1) ``` In this example, the `pipe` function is used to chain together a series of computations, starting with a string value of `"2"`. This value is first passed to the `flatMap` function which applies the `parseNumber` function to parse the input string to a number. If the parsing is successful, the resulting number is then passed to the `map` function which doubles it. Finally, the resulting value is passed to another `map` function which subtracts `3` from it. The final output of the pipeline is the `Option` value of `some(1)`. **Example 2: Error Path with Invalid Input** ```ts import { pipe } from "@fp-ts/core/Function"; import { Option, some, flatMap, map } from "@fp-ts/core/Option"; const failure: Option = pipe( some("Not a number"), flatMap((s) => parseNumber(s)), // parse the input to number map((x) => x2), // This will not be executed because parseNumber will return None map((x) => x - 3) // This will not be executed ); // none() ``` In this example, the input to the pipeline is the string value of `"Not a number"`. When this value is passed to the `flatMap` function which applies the `parseNumber` function, it will return `None` as the string cannot be parsed to a number. This means that the following `map `functions will not be executed and the final output of the pipeline will be `None`. **Example 3: Error Path Starting with None** ```ts import { pipe } from "@fp-ts/core/Function"; import { Option, none, flatMap, map } from "@fp-ts/core/Option"; const noneStart: Option = pipe( none, flatMap((s) => parseNumber(s)), // This will not be executed because it starts with None map((x) => x2), // This will not be executed map((x) => x - 3) // This will not be executed ); // none() ``` In this example, we start the pipeline with the `None` value, which represents an absent or empty value. This means that the `flatMap` step will not be executed and any subsequent steps in the pipeline will not be executed either. The advantage of using this approach is that the desired outcome is always in clear view while defining your pipeline. This allows you to focus on the expected result, while leaving it to the `Option` type to handle any potential errors that may arise seamlessly and transparently. You can concentrate on the successful scenario and let `Option` handle the management of potential errors at every step of the pipeline, without the need for explicit error handling. # Debugging Debugging your code can be difficult, especially when you have multiple transformations happening in a pipeline. The `Option` module provides two utility functions, `inspectSome` and `inspectNone`, that can help you inspect what is happening in your code and diagnose issues. The `inspectSome` function returns the original `Option` value, but if it is a `Some`, the provided callback function is called with the value wrapped inside the `Some`. The `inspectNone` function returns the original `Option` value, but if it is a `None`, the provided callback function is called without any arguments. Here is an example of how you can use `inspectSome` and `inspectNone` to debug a pipeline: ```ts import { pipe } from "@fp-ts/core/Function"; import * as O from "@fp-ts/core/Option"; const failure: O.Option = pipe( O.some("Not a number"), // start with a Some containing the string "Not a number" O.inspectSome(console.log), // log the value if it is a Some O.flatMap((s) => parseNumber(s)), // attempt to parse the string as a number O.inspectNone(() => console.error("none")), // log an error if the parseNumber function returns None O.map((x) => x * 2), // double the number if it is a Some O.map((x) => x - 3) // subtract 3 from the number if it is a Some ); // logs "Not a number" to the console // logs "none" to the console (because the parseNumber function returns None) ``` It is important to note that `inspectSome` and `inspectNone` should only be used for debugging purposes, and it is not recommended to use them for performing side effects or encoding business logic. **Cheat sheet** (debugging) | **Function** | **Given input** | **Resulting Output** | **Note** | | ------------- | ------------------------- | -------------------- | ------------------------------------ | | `inspectSome` | `Option`, `A => void` | `Option` | callback called if it is a `Some` | | `inspectNone` | `Option`, `() => void` | `Option` | callback called if it is a `None` | # Pattern matching We have seen how easy and convenient it is to build pipelines involving the `Option` data type, leaving it to handle any errors that may occur at any step. However, at some point, you will be interested in manually handling the error to understand the overall result obtained from the pipeline and decide what to do accordingly. ## Getting the value from an `Option` To extract the value from an `Option`, you can use the `getOrThrow` function, which retrieves the value wrapped in an `Option`, or throws an error if the `Option` you are querying is a `None`. Here's an example of how you can use `getOrThrow`: ```ts import { getOrThrow, some, none } from "@fp-ts/core/Option"; console.log(getOrThrow(some(10)); // 10 console.log(getOrThrow(none()); // throws new Error("getOrThrow called on a None") ``` However, using `getOrThrow` can lead to exceptions being thrown in your code, which can lead to unexpected behavior and crashes. To avoid this, you can use the `isSome` and `isNone` guards: ```ts import { some, isSome } from "@fp-ts/core/Option"; const option = some(1); // Use the `isSome` function to check if the `option` is an instance of `Some` if (isSome(option)) { console.log(`Option has a value: ${option.value}`); } else { console.log(`Option is empty.`); } // Output: Option has a value: 1 ``` ## Pattern matching with `Option` An alternative way to handle the cases of an `Option` being `None` or `Some` is by using the `match` function. The `match` function allows you to provide different actions for each case of the `Option` value. ```ts import { pipe } from "@fp-ts/core/Function"; import { some, match } from "@fp-ts/core/Option"; const option = some(1); /** * Use the `match` function to conditionally return a string based on whether the `Option` is `None` or `Some`. * If the `Option` is `None`, the first function will be called with no arguments. * If the `Option` is `Some`, the `value` will be passed to the second function. */ const output = match( option, () => `Option is empty.`, (value) => `Option has a value: ${value}` ); console.log(output); // Output: Option has a value: 1 ``` Using `match` instead of `isSome` or `isNone` can be more expressive and provide a clear way to handle both cases of an `Option`. Additionally, if you have complex logic to handle both cases, using `match` can make your code easier to read and maintain. ## Other functions for extracting values from an `Option` To make working with code that does not use `Option` more convenient, there are specializations of `match` called `getOrNull` and `getOrUndefined`, which allow you to retrieve the value of an `Option` or `null` or `undefined`, respectively. Here's an example of how you can use `getOrNull` and `getOrUndefined`: ```ts import * as O from "@fp-ts/core/Option"; O.getOrNull(O.some(5)); // 5 O.getOrNull(O.none()); // null O.getOrUndefined(O.some(5)); // 5 O.getOrUndefined(O.none()); // undefined ``` `getOrElse` allows you to specify a default value that should be returned if the `Option` is `None`. Here's an example of how you can use `getOrElse`: ```ts import * as O from "@fp-ts/core/Option"; O.getOrElse(O.some(5), () => 0); // 5 O.getOrElse(O.none(), () => 0); // 0 ``` Sometimes, when a computation returns `None`, you may want to continue with another computation that returns an `Option`. In this case, you can use the `orElse` function. This is useful for implementing retry logic, for example, where you want to attempt a computation multiple times until you either succeed or exhaust all possible attempts. Here's an example: ```ts import { pipe } from "@fp-ts/core/Function"; import * as O from "@fp-ts/core/Option"; const tryToConnect = (): O.Option => { // Imagine we have a function that returns an `Option` of connection status return Math.random() < 0.5 ? O.some("Connected successfully") : O.none(); }; const retryConnect = (attemptsLeft: number): O.Option => pipe( tryToConnect(), // Try to connect for the first time O.orElse(() => { // If it fails, check if we still have attempts left if (attemptsLeft > 0) { return retryConnect(attemptsLeft - 1); // If we do, try again with one less attempt } return O.none(); // If we don't, return none }) ); const result = retryConnect(3); // Try to connect three times ``` In this example, the function `tryToConnect` returns an `Option` representing the connection status. We use `orElse` to implement retry logic by attempting the connection again if the first attempt fails (returns `None`) and we still have attempts left. If all attempts fail, `retryConnect` returns `None`. The `firstSomeOf` function is used to retrieve the first value that is present within an `Iterable` of `Option` values. The function takes an `Iterable` of `Option` values and returns the first `Option` value that is `Some`, or `None` if there are no `Some` values in the `Iterable`. Here is an example of how you can use `firstSomeOf`: ```ts import * as O from "@fp-ts/core/Option"; const arr = [O.none(), O.some(2), O.none(), O.some(3)]; const first = O.firstSomeOf(arr); // some(2) ``` **Cheat sheet** (pattern matching) | **Function** | **Given input** | **Resulting Output** | | ---------------- | --------------------------------------------------- | -------------------- | | `match` | `Option`, `onNone: LazyArg`, `onSome: A => C` | `B \| C` | | `getOrThrow` | `Option` | `A` (may throw) | | `getOrThrowWith` | `Option`, `onNone: () => unknown` | `A` (may throw) | | `getOrNull` | `Option` | `A \| null` | | `getOrUndefined` | `Option` | `A \| undefined` | | `getOrElse` | `Option`, `onNone: LazyArg` | `A \| B` | | `orElse` | `Option`, `LazyArg>` | `Option` | | `firstSomeOf` | `Iterable>` | `Option` | # Interop with Code Using Nullable Types When using the `Option` data type, you may need to interact with code that uses `undefined` or `null` to indicate optional values. The `Option` data type provides several APIs to make this task easier. ## Converting a Nullable Value to an Option You can create an `Option` from a nullable value using the `fromNullable` API. ```ts import * as O from "@fp-ts/core/Option"; console.log(O.fromNullable(null)); // none() console.log(O.fromNullable(undefined)); // none() console.log(O.fromNullable(1)); // some(1) ``` You can also modify a function that returns a nullable value to a function that returns an `Option` using the `liftNullable` API. This process is known as "lifting." ```ts import * as O from "@fp-ts/core/Option"; const parse = (s: string): number | undefined => { const n = parseFloat(s); return isNaN(n) ? undefined : n; }; // const parseOption: (s: string) => Option const parseOption = O.liftNullable(parse); console.log(parseOption("1")); // some(1) console.log(parseOption("not a number")); // none() ``` ## Converting an Option to a Nullable Value If you have a value of type `Option` and want to convert it to a nullable value, you have two options: - Convert `None` to `null` using the `getOrNull` API - Convert `None` to `undefined` using the `getOrUndefined` API ```ts import * as O from "@fp-ts/core/Option"; console.log(O.getOrNull(O.some(1))); // 1 console.log(O.getOrNull(O.none())); // null console.log(O.getOrUndefined(O.some(1))); // 1 console.log(O.getOrUndefined(O.none())); // undefined ``` **Cheat sheet** (interop - nullable) | **Function** | **Given input** | **Resulting Output** | | ----------------- | -------------------------------------------------- | ------------------------------------ | | `fromNullable` | `A` | `Option>` | | `liftNullable` | `(...a: A) => B \| null \| undefined` | `(...a: A) => Option` | | `flatMapNullable` | `Option`, `(...a: A) => B \| null \| undefined` | `Option>` | | `getOrNull` | `Option` | `A \| null` | | `getOrUndefined` | `Option` | `A \| undefined` | # Combining two or more `Option`s The `zipWith` function allows you to combine two `Option`s using a provided function. The resulting value is a new `Option` that holds the combined value of both original `Option`s. Let's consider the following example where we have two `Option`s that hold values of two different types, `string` and `number`: ```ts import { Option, some } from "@fp-ts/core/Option"; const name: Option = some("John"); const age: Option = some(25); ``` If we want to combine these two `Option`s into a single `Option` that holds an object with properties `name` and `age`, we can use the `zipWith` function: ```ts import { zipWith } from "@fp-ts/core/Option"; const combine = zipWith(name, age, (n, a) => ({ name: n, age: a })); console.log(combine); // some({ name: 'John', age: 25 }) ``` The `zipWith` function takes three arguments: - The first `Option` you want to combine - The second `Option` you want to combine - A function that takes two arguments, which are the values held by the two `Options`, and returns the combined value It's important to note that if either of the two `Option`s is `None`, the resulting `Option` will also be `None`. This is because the `zipWith` function only combines the values if both `Option`s are `Some`. For example: ```ts const name: Option = none(); const age: Option = some(25); const combine = zipWith(name, age, (n, a) => ({ name: n, age: a })); console.log(combine); // none() ``` **Cheat sheet** (combining) | **Function** | **Given input** | **Resulting Output** | | --------------- | --------------------------------------- | ----------------------------- | | `zipWith` | `Option`, `Option`, `(A, B) => C` | `Option` | | `tuple` | `[Option, Option, ...]` | `Option<[A, B, ...]>` | | `struct` | `{ a: Option, b: Option, ... }` | `Option<{ a: A, b: B, ... }>` | | `all` | `Iterable>` | `Option` | | `appendElement` | `Option<[A, B, ...]>`, `Option` | `Option<[A, B, ..., C]>` | | `ap` | `Option<(a: A) => B>`, `Option` | `Option` | ## Algebraic operations with `Option`s In addition to `zipWith`, a series of algebraic operations such as sums, products, subtractions, and divisions are exported to make it easier to work with `Option`s. For example, consider the following `Option`s holding numbers: ```ts import * as O from "@fp-ts/core/Option"; const num1 = O.some(3); const num2 = O.some(4); const num3 = O.none(); ``` Summing two `Some` values will result in a `Some` with the sum of the values: ```ts // Summing two `Some` values will result in a `Some` with the sum of the values const sumOfSome = sum(num1, num2); console.log(sumOfSome); // some(7) ``` Summing a `Some` and a `None` will result in a `None`: ```ts // Summing a `Some` and a `None` will result in a `None` const sumOfSomeAndNone = sum(num1, num3); console.log(sumOfSomeAndNone); // none() ``` **Cheat sheet** (algebraic operations) | **Function** | **Given input** | **Resulting Output** | | ------------ | ---------------------------------- | -------------------- | | `sum` | `Option`, `Option` | `Option` | | `multiply` | `Option`, `Option` | `Option` | | `subtract` | `Option`, `Option` | `Option` | | `divide` | `Option`, `Option` | `Option` | ================================================ FILE: guides/These.md ================================================ # The `These` data type ## A data structure providing "inclusive-or" as opposed to `Either`'s "exclusive-or". If you interpret `Either` as suggesting the computation may either fail or succeed (exclusively), then `These` may fail, succeed, or do both at the same time. There are a few ways to interpret the `Both` case: 1. You can think of a computation that has a non-fatal error. 2. You can think of a computation that went as far as it could before erroring. 3. You can think of a computation that keeps track of errors as it completes. Another way you can think of `These` is saying that we want to handle `E` kind of data, `A` kind of data, or both `E` and `A` kind of data at the same time. This is particularly useful when it comes to displaying UI's. ================================================ FILE: guides/ts-types.md ================================================ # Standard TypeScript types ## strings | Module | Name | Given | To | | ----------- | ----------- | ----- | ----------------------------- | | Equivalence | string | | `Equivalence` | | Order | string | | `Order` | | Semigroup | string | | `Semigroup` | | Monoid | string | | `Monoid` | | Predicate | isString | | `Refinement` | | String | Equivalence | | `Equivalence` | | String | Order | | `Order` | | String | Semigroup | | `Semigroup` | | String | Monoid | | `Monoid` | | String | isString | | `Refinement` | ## numbers | Module | Name | Given | To | | ----------- | ----------------- | ----- | ----------------------------- | | Equivalence | number | | `Equivalence` | | Order | number | | `Order` | | Bounded | number | | `Bounded` | | Semigroup | numberSum | | `Semigroup` | | Semigroup | numberMultiply | | `Semigroup` | | Monoid | numberSum | | `Monoid` | | Monoid | numberMultiply | | `Monoid` | | Predicate | isNumber | | `Refinement` | | Number | Equivalence | | `Equivalence` | | Number | Order | | `Order` | | Number | SemigroupSum | | `Semigroup` | | Number | SemigroupMultiply | | `Semigroup` | | Number | SemigroupMax | | `Semigroup` | | Number | SemigroupMin | | `Semigroup` | | Number | MonoidSum | | `Monoid` | | Number | MonoidMultiply | | `Monoid` | | Number | MonoidMax | | `Monoid` | | Number | MonoidMin | | `Monoid` | | Number | isNumber | | `Refinement` | ## booleans | Module | Name | Given | To | | ----------- | ----------- | ----- | ------------------------------ | | Equivalence | boolean | | `Equivalence` | | Order | boolean | | `Order` | | Semigroup | booleanAny | | `Semigroup` | | Semigroup | booleanAll | | `Semigroup` | | Monoid | booleanAny | | `Monoid` | | Monoid | booleanAll | | `Monoid` | | Predicate | isBoolean | | `Refinement` | | Boolean | Equivalence | | `Equivalence` | | Boolean | Order | | `Order` | | Boolean | booleanAny | | `Semigroup` | | Boolean | booleanAll | | `Semigroup` | | Boolean | booleanAny | | `Monoid` | | Boolean | booleanAll | | `Monoid` | | Boolean | isBoolean | | `Refinement` | ## bigints | Module | Name | Given | To | | ----------- | ----------------- | ----- | ----------------------------- | | Equivalence | bigint | | `Equivalence` | | Order | bigint | | `Order` | | Semigroup | bigintSum | | `Semigroup` | | Semigroup | bigintMultiply | | `Semigroup` | | Monoid | bigintSum | | `Monoid` | | Monoid | bigintMultiply | | `Monoid` | | Predicate | isBigint | | `Refinement` | | Bigint | Equivalence | | `Equivalence` | | Bigint | Order | | `Order` | | Bigint | SemigroupSum | | `Semigroup` | | Bigint | SemigroupMultiply | | `Semigroup` | | Bigint | MonoidSum | | `Monoid` | | Bigint | MonoidMultiply | | `Monoid` | | Bigint | isBigint | | `Refinement` | ## symbols | Module | Name | Given | To | | ----------- | -------- | ----- | ----------------------------- | | Equivalence | symbol | | `Equivalence` | | Predicate | isSymbol | | `Refinement` | | Symbol | isSymbol | | `Refinement` | ## tuples This section covers the various modules and combinators that work with tuples. | Module | Name | Given | To | | ----------- | --------------- | --------------------------------------- | -------------------------------------- | | Equivalence | tuple | `[Equivalence, Equivalence, ...]` | `Equivalence` | | Order | tuple | `[Order, Order, ...]` | `Order` | | Semigroup | tuple | `[Semigroup, Semigroup, ...]` | `Semigroup<[A, B, ...]>` | | Monoid | tuple | `[Monoid, Monoid, ...]` | `Monoid<[A, B, ...]>` | | SemiProduct | nonEmptyTuple | `[F, F, ...]` (cannot be empty) | `F<[A, B, ...]>` | | Product | tuple | `[F, F, ...]` | `F<[A, B, ...]>` | | Either | tuple | `[Either, Either, ...]` | `Either` | | Option | tuple | `[Option, Option, ...]` | `Option<[A, B, ...]>` | | Predicate | tuple | `[Predicate, Predicate, ...]` | `Predicate` | | These | tuple | `[These, These, ...]` | `These` | | Tuple | getEquivalence | `[Equivalence, Equivalence, ...]` | `Equivalence` | | Tuple | getOrder | `[Order, Order, ...]` | `Order` | | Tuple | getSemigroup | `[Semigroup, Semigroup, ...]` | `Semigroup<[A, B, ...]>` | | Tuple | getMonoid | `[Monoid, Monoid, ...]` | `Monoid<[A, B, ...]>` | | Tuple | nonEmptyProduct | `[F, F, ...]` (cannot be empty) | `F<[A, B, ...]>` | | Tuple | product | `[F, F, ...]` | `F<[A, B, ...]>` | ## arrays This section covers the various modules and combinators that work with arrays. | Module | Name | Given | To | | ------------- | ------------- | ---------------- | ------------------------------- | | Equivalence | array | `Equivalence` | `Equivalence>` | | Order | array | `Order` | `Order>` | | Semigroup | array | `A` | `Semigroup>` | | Semigroup | readonlyArray | `A` | `Semigroup>` | | Monoid | array | `A` | `Monoid>` | | Monoid | readonlyArray | `A` | `Monoid>` | | ReadonlyArray | getSemigroup | `A` | `Semigroup>` | | ReadonlyArray | getMonoid | `A` | `Monoid>` | ## structs This section covers the various modules and combinators that work with structs. | Module | Name | Given | To | | ----------- | --------------- | ----------------------------------------------- | ----------------------------------------- | | Equivalence | struct | `{ a: Equivalence, b: Equivalence, ... }` | `Equivalence<{ a: A, b: B, ... }>` | | Order | struct | `{ a: Order, b: Order, ... }` | `Order<{ a: A, b: B, ... }>` | | Semigroup | struct | `{ a: Semigroup, b: Semigroup, ... }` | `Semigroup<{ a: A, b: B, ... }>` | | Monoid | struct | `{ a: Monoid, b: Monoid, ... }` | `Monoid<{ a: A, b: B, ... }>` | | SemiProduct | nonEmptyStruct | `{ a: F, b: F, ... }` (cannot be empty) | `F<{ a: A, b: B, ... }>` | | Product | struct | `{ a: F, b: F, ... }` | `F<{ a: A, b: B, ... }>` | | Either | struct | `{ a: Either, b: Either, ... }` | `Either` | | Option | struct | `{ a: Option, b: Option, ... }` | `Option<{ a: A, b: B }>` | | Predicate | struct | `{ a: Predicate, b: Predicate, ... }` | `Predicate>` | | These | struct | `{ a: These, b: These, ... }` | `These` | | Struct | getEquivalence | `{ a: Equivalence, b: Equivalence, ... }` | `Equivalence<{ a: A, b: B, ... }>` | | Struct | getOrder | `{ a: Order, b: Order, ... }` | `Order<{ a: A, b: B, ... }>` | | Struct | getSemigroup | `{ a: Semigroup, b: Semigroup, ... }` | `Semigroup<{ a: A, b: B, ... }>` | | Struct | getMonoid | `{ a: Monoid, b: Monoid, ... }` | `Monoid<{ a: A, b: B, ... }>` | | Struct | nonEmptyProduct | `{ a: F, b: F, ... }` (cannot be empty) | `F<{ a: A, b: B, ... }>` | | Struct | product | `{ a: F, b: F, ... }` | `F<{ a: A, b: B, ... }>` | ## records This section covers the various modules and combinators that work with records. | Module | Name | Given | To | | -------------- | ------------- | -------------------------------------------- | -------------------------------- | | Equivalence | record | `Equivalence` | `Equivalence>` | | ReadonlyRecord | get | `key: string`, `ReadonlyRecord` | `Option` | | ReadonlyRecord | replaceOption | `key: string`, `B`, `ReadonlyRecord` | `Option>` | | ReadonlyRecord | modifyOption | `key: string`, `A => B`, `ReadonlyRecord` | `Option>` | ================================================ FILE: guides/typeclass.md ================================================ # Introduction The functional abstractions in `@fp-ts/core` can be broadly divided into two categories. - Abstractions For Concrete Types - These abstractions define properties of concrete types, such as `number` and `string`, as well as ways of combining those values. - Abstractions For Parameterized Types - These abstractions define properties of parameterized types such as `ReadonlyArray` and `Option` and ways of combining them. # Concrete Types ## Members and derived functions Note: members are in bold. ### Bounded A type class used to name the lower limit and the upper limit of a type. Extends: - `Order` | Name | Given | To | | ------------ | ------------ | ------------ | | **maxBound** | | `A` | | **minBound** | | `A` | | reverse | `Bounded` | `Bounded` | | clamp | `A` | `A` | ### Equivalence `Equivalence` defines a binary relation that is reflexive, symmetric, and transitive. In other words, it defines a notion of equivalence between values of a certain type. These properties are also known in mathematics as an "equivalence relation". | Name | Given | To | | ------------ | ----------------------------------------------- | ------------------------------------------ | | strict | `A` | `Equivalence` | | tuple | `[Equivalence, Equivalence, ...]` | `Equivalence<[A, B, ...]>` | | array | `Equivalence` | `Equivalence` | | struct | `{ a: Equivalence, b: Equivalence, ... }` | `Equivalence<{ a: A, b: B, ... }>` | | record | `Equivalence` | `Equivalence<{ readonly [x: string]: A }>` | | getSemigroup | `A` | `Semigroup>` | | getMonoid | `A` | `Monoid>` | | contramap | `Equivalence`, `B => A` | `Equivalence` | ### Monoid A `Monoid` is a `Semigroup` with an identity. A `Monoid` is a specialization of a `Semigroup`, so its operation must be associative. Additionally, `x |> combine(empty) == empty |> combine(x) == x`. For example, if we have `Monoid`, with `combine` as string concatenation, then `empty = ""`. Extends: - `Semigroup` | Name | Given | To | | -------------- | ------------------------------------- | ----------------------------- | | **empty** | | `A` | | **combineAll** | `Iterable` | `A` | | reverse | `Monoid` | `Monoid` | | tuple | `[Monoid, Monoid, ...]` | `Monoid<[A, B, ...]>` | | struct | `{ a: Monoid, b: Monoid, ... }` | `Monoid<{ a: A, b: B, ... }>` | | min | `Bounded` | `Monoid` | | max | `Bounded` | `Monoid` | ### Order The `Order` type class is used to define a total ordering on some type `A`. An order is defined by a relation `<=`, which obeys the following laws: - either `x <= y` or `y <= x` (totality) - if `x <= y` and `y <= x`, then `x == y` (antisymmetry) - if `x <= y` and `y <= z`, then `x <= z` (transitivity) The truth table for compare is defined as follows: | `x <= y` | `x >= y` | Ordering | | | -------- | -------- | -------- | --------------------- | | `true` | `true` | `0` | corresponds to x == y | | `true` | `false` | `< 0` | corresponds to x < y | | `false` | `true` | `> 0` | corresponds to x > y | By the totality law, `x <= y` and `y <= x` cannot be both `false`. | Name | Given | To | | -------------------- | --------------------------- | --------------------- | | **compare** | `A`, `A` | `Ordering` | | reverse | `Order` | `Order` | | contramap | `Order`, `B => A` | `Order` | | getSemigroup | | `Semigroup>` | | getMonoid | | `Monoid>` | | tuple | `[Order, Order, ...]` | `Order<[A, B, ...]>` | | lessThan | `A`, `A` | `boolean` | | greaterThan | `A`, `A` | `boolean` | | lessThanOrEqualTo | `A`, `A` | `boolean` | | greaterThanOrEqualTo | `A`, `A` | `boolean` | | min | `A`, `A` | `boolean` | | max | `A`, `A` | `boolean` | | clamp | `A`, `A` | `A` | | between | `A` | `boolean` | ### Semigroup A `Semigroup` is any set `A` with an associative operation (`combine`): `x |> combine(y) |> combine(z) == x |> combine(y |> combine(z))` | Name | Given | To | | --------------- | ------------------------------------------- | -------------------------------- | | **combine** | `A`, `A` | `A` | | **combineMany** | `A`, `Iterable` | `A` | | reverse | `Semigroup` | `Semigroup` | | tuple | `[Semigroup, Semigroup, ...]` | `Semigroup<[A, B, ...]>` | | struct | `{ a: Semigroup, b: Semigroup, ... }` | `Semigroup<{ a: A, b: B, ... }>` | | min | `Order` | `Semigroup` | | max | `Order` | `Semigroup` | | constant | `A` | `Semigroup` | | intercalate | `A`, `Semigroup` | `Semigroup` | | first | | `Semigroup` | | last | | `Semigroup` | # Parameterized Types **Parameterized Types Hierarchy** ```mermaid flowchart TD Alternative --> SemiAlternative Alternative --> Coproduct Applicative --> Product Coproduct --> SemiCoproduct SemiAlternative --> Covariant SemiAlternative --> SemiCoproduct SemiApplicative --> SemiProduct SemiApplicative --> Covariant Applicative --> SemiApplicative Chainable --> FlatMap Chainable ---> Covariant Monad --> FlatMap Monad --> Pointed Pointed --> Of Pointed --> Covariant Product --> SemiProduct Product --> Of SemiProduct --> Invariant Covariant --> Invariant SemiCoproduct --> Invariant ``` ## Members and derived functions Note: members are in bold. ### Alternative Extends: - `SemiAlternative` - `Coproduct` ### Applicative Extends: - `SemiApplicative` - `Product` | Name | Given | To | | ---------- | ----------- | -------------- | | liftMonoid | `Monoid` | `Monoid>` | ### Bicovariant A type class of types which give rise to two independent, covariant functors. | Name | Given | To | | --------- | -------------------------------- | ---------- | | **bimap** | `F`, `E1 => E2`, `A => B` | `F` | | mapLeft | `F`, `E1 => E2` | `F` | | map | `F`, `A => B` | `F` | ### Chainable Extends: - `FlatMap` - `Covariant` | Name | Given | To | | -------------- | ----------------------------------- | ---------------------- | | tap | `F`, `A => F` | `F` | | andThenDiscard | `F`, `F` | `F` | | bind | `F`, `name: string`, `A => F` | `F` | ### Contravariant Contravariant functors. Extends: - `Invariant` | Name | Given | To | | -------------------- | ------------------- | --------- | | **contramap** | `F`, `B => A` | `F` | | contramapComposition | `F>`, `A => B` | `F>` | | imap | `contramap` | `imap` | ### Coproduct `Coproduct` is a universal monoid which operates on kinds. This type class is useful when its type parameter `F<_>` has a structure that can be combined for any particular type, and which also has a "zero" representation. Thus, `Coproduct` is like a `Monoid` for kinds (i.e. parametrized types). A `Coproduct` can produce a `Monoid>` for any type `A`. Here's how to distinguish `Monoid` and `Coproduct`: - `Monoid` allows `A` values to be combined, and also means there is an "empty" `A` value that functions as an identity. - `Coproduct` allows two `F` values to be combined, for any `A`. It also means that for any `A`, there is an "zero" `F` value. The combination operation and zero value just depend on the structure of `F`, but not on the structure of `A`. Extends: - `SemiCoproduct` | Name | Given | To | | ---------------- | ---------------- | -------------- | | **zero** | | `F` | | **coproductAll** | `Iterable>` | `F` | | getMonoid | | `Monoid>` | ### Covariant Covariant functors. Extends: - `Invariant` | Name | Given | To | | -------------- | ------------------- | --------- | | **map** | `F`, `A => B` | `F` | | mapComposition | `F>`, `A => B` | `F>` | | imap | `map` | `imap` | | flap | `A`, `F B>` | `F` | | as | `F`, `B` | `F` | | asUnit | `F` | `F` | ### Filterable `Filterable` allows you to `map` and filter out elements simultaneously. | Name | Given | To | | ----------------------- | ------------------------------ | -------------------- | | **partitionMap** | `F`, `A => Either` | `[F, F]` | | **filterMap** | `F`, `A => Option` | `F` | | compact | `F>` | `F` | | separate | `F>` | `[F, F]` | | filter | `F`, `A => boolean` | `F` | | partition | `F`, `A => boolean` | `[F, F]` | | partitionMapComposition | `F>`, `A => Either` | `[F>, F>]` | | filterMapComposition | `F>`, `A => Option` | `F>` | ### FlatMap | Name | Given | To | | ------------------- | ------------------------ | ----------- | | **flatMap** | `F`, `A => F` | `F` | | flatten | `F>` | `F` | | andThen | `F`, `F` | `F` | | composeKleisliArrow | `A => F`, `B => F` | `A => F` | ### Foldable Data structures that can be folded to a summary value. In the case of a collection (such as `ReadonlyArray`), these methods will fold together (combine) the values contained in the collection to produce a single result. Most collection types have `reduce` methods, which will usually be used by the associated `Foldable` instance. | Name | Given | To | | ------------------- | ----------------------------------------- | ------------------ | | **reduce** | `F`, `B`, `(B, A) => B` | `B` | | reduceComposition | `F>`, `B`, `(B, A) => B` | `B` | | reduceRight | `F`, `B`, `(B, A) => B` | `B` | | foldMap | `F`, `Monoid`, `A => M` | `M` | | toReadonlyArray | `F` | `ReadonlyArray` | | toReadonlyArrayWith | `F`, `A => B` | `ReadonlyArray` | | reduceKind | `Monad`, `F`, `B`, `(B, A) => G` | `G` | | reduceRightKind | `Monad`, `F`, `B`, `(B, A) => G` | `G` | | foldMapKind | `Coproduct`, `F`, `(A) => G` | `G` | ### Invariant Invariant functors. | Name | Given | To | | --------------- | ----------------------------- | ------------------ | | **imap** | `F`, `A => B`, `B => A` | `F` | | imapComposition | `F>`, `A => B`, `B => A` | `F>` | | bindTo | `F`, `name: string` | `F<{ [name]: A }>` | | tupled | `F` | `F<[A]>` | ### Monad Allows composition of dependent effectful functions. Extends: - `FlatMap` - `Pointed` ### Of | Name | Given | To | | ------------- | ----- | --------- | | **of** | `A` | `F` | | ofComposition | `A` | `F>` | | unit | | `F` | | Do | | `F<{}>` | ### Pointed Extends: - `Covariant` - `Of` ### Product Extends: - `SemiProduct` - `Of` | Name | Given | To | | -------------- | --------------------------- | ------------------------ | | **productAll** | `Iterable>` | `F>` | | tuple | `[F, F, ...]` | `F<[A, B, ...]>` | | struct | `{ a: F, b: F, ... }` | `F<{ a: A, b: B, ... }>` | ### SemiAlternative Extends: - `SemiCoproduct` - `Covariant` ### SemiApplicative Extends: - `SemiProduct` - `Covariant` | Name | Given | To | | -------------- | ------------------- | ---------------------------- | | liftSemigroup | `Semigroup` | `Semigroup>` | | ap | `F B>`, `F` | `F` | | andThenDiscard | `F`, `F` | `F` | | andThen | `F`, `F` | `F` | | lift2 | `(A, B) => C` | `(F, F) => F` | | lift3 | `(A, B, C) => D` | `(F, F, F) => F` | ### SemiCoproduct `SemiCoproduct` is a universal semigroup which operates on kinds. This type class is useful when its type parameter `F<_>` has a structure that can be combined for any particular type. Thus, `SemiCoproduct` is like a `Semigroup` for kinds (i.e. parametrized types). A `SemiCoproduct` can produce a `Semigroup>` for any type A. Here's how to distinguish `Semigroup` and `SemiCoproduct`: - `Semigroup` allows two `A` values to be combined. - `SemiCoproduct` allows two `F` values to be combined, for any `A`. The combination operation just depends on the structure of `F`, but not the structure of `A`. Extends: - `Invariant` | Name | Given | To | | ----------------- | ---------------- | ----------------- | | **coproduct** | `F`, `F` | `F` | | **coproductMany** | `Iterable>` | `F` | | getSemigroup | | `Semigroup>` | | coproductEither | `F`, `F` | `F>` | ### SemiProduct Extends: - `Invariant` | Name | Given | To | | ---------------------- | ------------------------------ | -------------------------------- | | **product** | `F`, `F` | `F<[A, B]>` | | **productMany** | `F`, `Iterable>` | `F<[A, ...ReadonlyArray]>` | | productComposition | `F>`, `F>` | `F>` | | productManyComposition | `F>`, `Iterable>>` | `F]>>` | | nonEmptyTuple | `[F, F, ...]` | `F<[A, B, ...]>` | | nonEmptyStruct | `{ a: F, b: F, ... }` | `F<{ a: A, b: B, ... }>` | | andThenBind | `F`, `name: string`, `F` | `F` | | productFlatten | `F`, `F` | `F<[...A, B]>` | ### Traversable Traversal over a structure with an effect. | Name | Given | To | | ------------------- | ---------------------------------------- | ------------ | | **traverse** | `Applicative`, `T`, `A => F` | `F>` | | traverseComposition | `Applicative`, `T>`, `A => F` | `F>>` | | sequence | `Applicative`, `T>` | `F>` | | traverseTap | `Applicative`, `T`, `A => F` | `F>` | ### TraversableFilterable `TraversableFilterable`, also known as `Witherable`, represents list-like structures that can essentially have a `traverse` and a `filter` applied as a single combined operation (`traverseFilter`). | Name | Given | To | | ------------------------ | ------------------------------------------------ | ----------------- | | **traversePartitionMap** | `Applicative`, `T`, `A => F>` | `F<[T, T]>` | | **traverseFilterMap** | `Applicative`, `T`, `A => F>` | `F>` | | traverseFilter | `Applicative`, `T`, `A => F` | `F>` | | traversePartition | `Applicative`, `T`, `A => F` | `F<[T, T]>` | # Data Types Additionaly `@fp-ts/core` exports a few data types (types only, implementations are in `@fp-ts/data`) - `Either` - `Option` --- Adapted from: - [cats](https://github.com/typelevel/cats) - [zio-prelude](https://github.com/zio/zio-prelude) - [zio-cheatsheet](https://github.com/ghostdogpr/zio-cheatsheet) ================================================ FILE: package.json ================================================ { "name": "@fp-ts/core", "version": "0.2.1", "publishConfig": { "access": "public", "directory": "dist" }, "repository": { "type": "git", "url": "https://github.com/fp-ts/core.git" }, "author": "Giulio Canti ", "license": "MIT", "bugs": { "url": "https://github.com/fp-ts/core/issues" }, "homepage": "https://github.com/fp-ts/core", "description": "Functional programming in TypeScript", "tags": [ "typescript", "algebraic-data-types", "functional-programming" ], "keywords": [ "typescript", "algebraic-data-types", "functional-programming" ], "scripts": { "version": "changeset version && pnpm install --no-frozen-lockfile && pnpm run docs-update", "release": "pnpm run build && changeset publish", "clean": "rimraf build tsbuildinfo dist .ultra.cache.json", "build": "pnpm build-all && pnpm build-pack", "build-cjs": "babel build/esm --config-file ./.babel.cjs.json --out-dir build/cjs --out-file-extension .js --source-maps", "build-mjs": "babel build/esm --config-file ./.babel.mjs.json --out-dir build/mjs --out-file-extension .mjs --source-maps", "build-post": "build-utils pack-v3", "build-pack": "concurrently \"pnpm build-cjs\" \"pnpm build-mjs\" && pnpm build-post", "build-all": "tsc -b tsconfig.json", "build-watch": "tsc -b tsconfig.json --watch", "dtslint": "dtslint dtslint", "lint": "eslint . --ext .ts,.tsx", "autofix": "pnpm lint --fix", "tc": "tsc --noEmit", "docs": "docs-ts", "docs-update": "git add --force --all docs/modules || true", "circular": "madge --ts-config ./tsconfig.madge.json --circular --no-color --no-spinner --warning build/esm", "test": "vitest", "test-all": "npm run circular && npm run dtslint && vitest run", "coverage": "vitest run --coverage" }, "exports": { ".": { "require": "./build/cjs/index.js" }, "./*": { "require": "./build/cjs/*.js" } }, "config": { "side": [], "modules": [], "global": [] }, "devDependencies": { "@babel/cli": "^7.18.6", "@babel/core": "^7.20.5", "@babel/plugin-transform-modules-commonjs": "^7.19.6", "@changesets/changelog-github": "^0.4.7", "@changesets/cli": "^2.25.2", "@effect-ts/build-utils": "0.40.3", "@effect-ts/core": "^0.60.2", "@effect/language-service": "^0.0.17", "@repo-tooling/eslint-plugin-dprint": "^0.0.4", "@types/benchmark": "^2.1.2", "@types/glob": "^8.0.0", "@types/jest": "^29.2.3", "@types/node": "^18.11.9", "@types/prettier": "2.7.1", "@types/rimraf": "^3.0.2", "@typescript-eslint/eslint-plugin": "^5.44.0", "@typescript-eslint/parser": "^5.44.0", "@vitest/coverage-c8": "^0.27.1", "babel-plugin-annotate-pure-calls": "^0.4.0", "benchmark": "^2.1.4", "c8": "^7.11.3", "concurrently": "^7.6.0", "cpx": "^1.5.0", "docs-ts": "0.6.10", "dtslint": "github:gcanti/dtslint", "eslint": "^8.28.0", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-codegen": "0.16.1", "eslint-plugin-deprecation": "^1.3.3", "eslint-plugin-import": "^2.26.0", "eslint-plugin-simple-import-sort": "^8.0.0", "eslint-plugin-sort-destructure-keys": "^1.4.0", "fast-check": "^3.3.0", "glob": "^8.0.3", "madge": "^5.0.1", "picocolors": "^1.0.0", "prettier": "^2.8.0", "rimraf": "^3.0.2", "ts-node": "^10.9.1", "tslint": "^6.1.3", "typescript": "^4.9.3", "ultra-runner": "^3.10.5", "vite": "^3.2.4", "vitest": "0.25.3" }, "pnpm": { "patchedDependencies": { "@effect-ts/build-utils@0.40.3": "patches/@effect-ts__build-utils@0.40.3.patch", "docs-ts@0.6.10": "patches/docs-ts@0.6.10.patch" } } } ================================================ FILE: patches/@effect-ts__build-utils@0.40.3.patch ================================================ diff --git a/pack-v3.js b/pack-v3.js index c12e36a7f85c59e8d219df0eec1001c495be4f64..129b8d678ff6796f9a3d78056da47b5f2d99895d 100644 --- a/pack-v3.js +++ b/pack-v3.js @@ -43,7 +43,7 @@ function carry(s, root, target) { } const writePackageJsonContent = (0, Function_1.pipe)(TE.do, TE.bind("content", () => loadPackageJson), TE.bind("modules", ({ content }) => getModules(content)), TE.bind("side", ({ content }) => getSide(content)), TE.bind("global", ({ content }) => getGlobal(content)), TE.tap(({ global }) => global._tag === "None" ? TE.unit - : TE.forEach_(global.value.filter((gi) => gi.startsWith("_src/")), (gi) => (0, _common_1.copy)(gi, "dist", { update: true }))), TE.map(({ content, global, modules, side }) => { + : TE.forEach_(global.value.filter((gi) => gi.startsWith("src/")), (gi) => (0, _common_1.copy)(gi, "dist", { update: true }))), TE.map(({ content, global, modules, side }) => { const packageJson = {}; carry("name", content, packageJson); carry("version", content, packageJson); @@ -60,7 +60,7 @@ const writePackageJsonContent = (0, Function_1.pipe)(TE.do, TE.bind("content", ( if (fs.existsSync(`./build/mjs/index.mjs`)) { mainExports["import"] = { types: `./index.d.ts`, - default: `./_mjs/index.mjs` + default: `./mjs/index.mjs` }; } if (fs.existsSync(`./build/cjs/index.js`)) { @@ -80,14 +80,14 @@ const writePackageJsonContent = (0, Function_1.pipe)(TE.do, TE.bind("content", ( } if (global._tag === "Some") { global.value - .filter((gi) => gi.startsWith("_src/")) + .filter((gi) => gi.startsWith("src/")) .forEach((gi) => { - exports[`./${gi.replace("_src/", "").replace(".d.ts", "")}`] = { + exports[`./${gi.replace("src/", "").replace(".d.ts", "")}`] = { import: { - types: `./${gi.replace("_src/", "")}` + types: `./${gi.replace("src/", "")}` }, require: { - types: `./${gi.replace("_src/", "")}` + types: `./${gi.replace("src/", "")}` } }; }); @@ -97,7 +97,7 @@ const writePackageJsonContent = (0, Function_1.pipe)(TE.do, TE.bind("content", ( if (fs.existsSync(`./build/mjs/${m}/index.mjs`)) { exports[`./${m}`]["import"] = { types: `./${m}/index.d.ts`, - default: `./_mjs/${m}/index.mjs` + default: `./mjs/${m}/index.mjs` }; } if (fs.existsSync(`./build/cjs/${m}/index.js`)) { @@ -113,7 +113,7 @@ const writePackageJsonContent = (0, Function_1.pipe)(TE.do, TE.bind("content", ( exports["./*"] = { import: { types: "./*.d.ts", - default: "./_mjs/*.mjs" + default: "./mjs/*.mjs" }, require: { types: "./*.d.ts", @@ -131,7 +131,7 @@ const writePackageJsonContent = (0, Function_1.pipe)(TE.do, TE.bind("content", ( map.push(`./${m}/index.js`); } if (fs.existsSync(`./build/mjs/${m}/index.mjs`)) { - map.push(`./_mjs/${m}/index.mjs`); + map.push(`./mjs/${m}/index.mjs`); } return map; }), @@ -141,13 +141,13 @@ const writePackageJsonContent = (0, Function_1.pipe)(TE.do, TE.bind("content", ( const MAP_GLOB_PATTERN = "dist/**/*.map"; const replaceString = (path) => { const dir = path_1.posix.dirname(path); - const patch = path.startsWith("dist/_mjs/") - ? (x) => x.replace(/(.*)\.\.\/_src(.*)/gm, "$1_src$2") - : (x) => x.replace(/(.*)\.\.\/\.\.\/_src(.*)/gm, "$1_src$2"); + const patch = path.startsWith("dist/mjs/") + ? (x) => x.replace(/(.*)\.\.\/src(.*)/gm, "$1src$2") + : (x) => x.replace(/(.*)\.\.\/\.\.\/src(.*)/gm, "$1src$2"); return (0, Function_1.flow)(patch, (x) => path_1.posix.relative(dir, path_1.posix.join(dir, x)), (x) => (x.startsWith(".") ? x : "./" + x)); }; const replace = (content, path) => JSON.stringify((0, Function_1.pipe)(Object.entries(JSON.parse(content)), A.map(([k, v]) => k === "sources" ? [k, A.map_(v, replaceString(path))] : [k, v]), A.reduce({}, (acc, [k, v]) => ({ ...acc, [k]: v })))); -(0, Function_1.pipe)((0, _common_1.exec)("rm -rf build/dist"), TE.tap(() => (0, _common_1.exec)("mkdir -p dist")), TE.tap(() => TE.when(() => fs.existsSync(`./_src`))((0, _common_1.exec)(`mkdir -p ./dist/_src && cp -r ./_src/* ./dist/_src`))), TE.tap(() => TE.when(() => fs.existsSync(`./build/mjs`))((0, _common_1.exec)(`mkdir -p ./dist/_mjs && cp -r ./build/mjs/* ./dist/_mjs`))), TE.tap(() => TE.when(() => fs.existsSync(`./build/cjs`))((0, _common_1.exec)(`cp -r ./build/cjs/* ./dist`))), TE.tap(() => TE.when(() => fs.existsSync(`./build/dts`))((0, _common_1.exec)(`cp -r ./build/dts/* ./dist`))), TE.tap(() => writePackageJsonContent), TE.tap(() => copyReadme), TE.tap(() => (0, _common_1.modifyGlob)(replace)(MAP_GLOB_PATTERN)), TE.fold(_common_1.onLeft, (0, _common_1.onRight)("pack succeeded!")), _common_1.runMain); +(0, Function_1.pipe)((0, _common_1.exec)("rm -rf build/dist"), TE.tap(() => (0, _common_1.exec)("mkdir -p dist")), TE.tap(() => TE.when(() => fs.existsSync(`./src`))((0, _common_1.exec)(`mkdir -p ./dist/src && cp -r ./src/* ./dist/src`))), TE.tap(() => TE.when(() => fs.existsSync(`./build/mjs`))((0, _common_1.exec)(`mkdir -p ./dist/mjs && cp -r ./build/mjs/* ./dist/mjs`))), TE.tap(() => TE.when(() => fs.existsSync(`./build/cjs`))((0, _common_1.exec)(`cp -r ./build/cjs/* ./dist`))), TE.tap(() => TE.when(() => fs.existsSync(`./build/dts`))((0, _common_1.exec)(`cp -r ./build/dts/* ./dist`))), TE.tap(() => writePackageJsonContent), TE.tap(() => copyReadme), TE.tap(() => (0, _common_1.modifyGlob)(replace)(MAP_GLOB_PATTERN)), TE.fold(_common_1.onLeft, (0, _common_1.onRight)("pack succeeded!")), _common_1.runMain); //# sourceMappingURL=pack-v3.js.map ================================================ FILE: patches/docs-ts@0.6.10.patch ================================================ diff --git a/lib/Core.js b/lib/Core.js index c0f282ca9e3ddd93e44a62e1d05c1cc45b9f5c6a..616f7f6223459e0621522279ea7fc1cf1868abe8 100644 --- a/lib/Core.js +++ b/lib/Core.js @@ -167,7 +167,30 @@ var typeCheckExamples = function (modules) { return function_1.pipe(getExampleFiles(modules), RTE.chain(handleImports), RTE.chain(function (examples) { return examples.length === 0 ? cleanExamples - : function_1.pipe(writeExamples(examples), RTE.chain(function () { return spawnTsNode; }), RTE.chain(function () { return cleanExamples; })); + : function_1.pipe(writeExamples(examples), RTE.chain(function () { return writeFile({"path": "./docs/examples/tsconfig.json", "content": JSON.stringify({ + "compilerOptions": { + "noEmit": true, + "strict": true, + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noImplicitReturns": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "target": "ES2021", + "lib": ["ES2021"], + "paths": { + "@fp-ts/core": ["../../src/index.ts"], + "@fp-ts/core/test/*": ["../../test/*"], + "@fp-ts/core/examples/*": ["../../examples/*"], + "@fp-ts/core/*": ["../../src/*"] + } + } + } + )}); }), RTE.chain(function () { return spawnTsNode; }), RTE.chain(function () { return cleanExamples; })); })); }; // ------------------------------------------------------------------------------------- diff --git a/lib/index.js b/lib/index.js index 51bdb346c4c33e8835bbda0c16aea71bc0c3115e..7d084d363efd3f8aad76051f4253b0b59cd0c5cd 100644 --- a/lib/index.js +++ b/lib/index.js @@ -33,7 +33,13 @@ exports.exit = TE.fold(onLeft, function () { return onRight; }); * @internal */ exports.compilerOptions = { - strict: true + strict: true, + paths: { + "@fp-ts/core": ["./src/index.ts"], + "@fp-ts/core/test/*": ["./test/*"], + "@fp-ts/core/examples/*": ["./examples/*"], + "@fp-ts/core/*": ["./src/*"] + } }; var capabilities = { example: Example_1.Example, ================================================ FILE: src/Bigint.ts ================================================ /** * This module provides utility functions and type class instances for working with the `bigint` type in TypeScript. * It includes functions for basic arithmetic operations, as well as type class instances for * `Equivalence`, `Order`, `Semigroup`, and `Monoid`. * * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { Ordering } from "@fp-ts/core/Ordering" import * as predicate from "@fp-ts/core/Predicate" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as order from "@fp-ts/core/typeclass/Order" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * Tests if a value is a `bigint`. * * @param input - The value to test. * * @example * import { isBigint } from "@fp-ts/core/Bigint" * * assert.deepStrictEqual(isBigint(1n), true) * assert.deepStrictEqual(isBigint(1), false) * * @category guards * @since 1.0.0 */ export const isBigint: (u: unknown) => u is bigint = predicate.isBigint /** * Provides an addition operation on `bigint`s. * * @param self - The first operand. * @param that - The second operand. * * @example * import { sum } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(sum(2n, 3n), 5n) * * @category math * @since 1.0.0 */ export const sum: { (that: bigint): (self: bigint) => bigint (self: bigint, that: bigint): bigint } = dual(2, semigroup.bigintSum.combine) /** * Provides a multiplication operation on `bigint`s. * * @param self - The first operand. * @param that - The second operand. * * @example * import { multiply } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(multiply(2n, 3n), 6n) * * @category math * @since 1.0.0 */ export const multiply: { (that: bigint): (self: bigint) => bigint (self: bigint, that: bigint): bigint } = dual(2, semigroup.bigintMultiply.combine) /** * Provides a subtraction operation on `bigint`s. * * @param self - The first operand. * @param that - The second operand. * * @example * import { subtract } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(subtract(2n, 3n), -1n) * * @category math * @since 1.0.0 */ export const subtract: { (that: bigint): (self: bigint) => bigint (self: bigint, that: bigint): bigint } = dual(2, (self: bigint, that: bigint): bigint => self - that) /** * Provides a division operation on `bigint`s. * * If the dividend is not a multiple of the divisor the result will be a `bigint` value * which represents the integer division rounded down to the nearest integer. * * @param self - The dividend operand. * @param that - The divisor operand. * * @example * import { divide } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(divide(6n, 3n), 2n) * assert.deepStrictEqual(divide(6n, 4n), 1n) * * @category math * @since 1.0.0 * @since 1.0.0 */ export const divide: { (that: bigint): (self: bigint) => bigint (self: bigint, that: bigint): bigint } = dual(2, (self: bigint, that: bigint): bigint => self / that) /** * Returns the result of adding `1n` to a given number. * * @param n - A `bigint` to be incremented. * * @example * import { increment } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(increment(2n), 3n) * * @category math * @since 1.0.0 */ export const increment = (n: bigint): bigint => n + 1n /** * Decrements a number by `1n`. * * @param n - A `bigint` to be decremented. * * @example * import { decrement } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(decrement(3n), 2n) * * @category math * @since 1.0.0 */ export const decrement = (n: bigint): bigint => n - 1n /** * @category instances * @since 1.0.0 */ export const Equivalence: equivalence.Equivalence = equivalence.bigint /** * @category instances * @since 1.0.0 */ export const Order: order.Order = order.bigint /** * Returns `true` if the first argument is less than the second, otherwise `false`. * * @param self - The first argument. * @param that - The second argument. * * @example * import { lessThan } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(lessThan(2n, 3n), true) * assert.deepStrictEqual(lessThan(3n, 3n), false) * assert.deepStrictEqual(lessThan(4n, 3n), false) * * @category predicates * @since 1.0.0 */ export const lessThan: { (that: bigint): (self: bigint) => boolean (self: bigint, that: bigint): boolean } = order.lessThan(Order) /** * Returns a function that checks if a given `bigint` is less than or equal to the provided one. * * @param self - The first `bigint` to compare with. * @param that - The second `bigint` to compare with. * * @example * import { lessThanOrEqualTo } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(lessThanOrEqualTo(2n, 3n), true) * assert.deepStrictEqual(lessThanOrEqualTo(3n, 3n), true) * assert.deepStrictEqual(lessThanOrEqualTo(4n, 3n), false) * * @category predicates * @since 1.0.0 */ export const lessThanOrEqualTo: { (that: bigint): (self: bigint) => boolean (self: bigint, that: bigint): boolean } = order.lessThanOrEqualTo(Order) /** * Returns `true` if the first argument is greater than the second, otherwise `false`. * * @param self - The first argument. * @param that - The second argument. * * @example * import { greaterThan } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(greaterThan(2n, 3n), false) * assert.deepStrictEqual(greaterThan(3n, 3n), false) * assert.deepStrictEqual(greaterThan(4n, 3n), true) * * @category predicates * @since 1.0.0 */ export const greaterThan: { (that: bigint): (self: bigint) => boolean (self: bigint, that: bigint): boolean } = order.greaterThan(Order) /** * Returns a function that checks if a given `bigint` is greater than or equal to the provided one. * * @param self - The first `bigint` to compare with. * @param that - The second `bigint` to compare with. * * @example * import { greaterThanOrEqualTo } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(greaterThanOrEqualTo(2n, 3n), false) * assert.deepStrictEqual(greaterThanOrEqualTo(3n, 3n), true) * assert.deepStrictEqual(greaterThanOrEqualTo(4n, 3n), true) * * @category predicates * @since 1.0.0 */ export const greaterThanOrEqualTo: { (that: bigint): (self: bigint) => boolean (self: bigint, that: bigint): boolean } = order.greaterThanOrEqualTo(Order) /** * Checks if a `bigint` is between a `minimum` and `maximum` value (inclusive). * * @param self - The `number` to check. * @param minimum - The `minimum` value to check. * @param maximum - The `maximum` value to check. * * @example * import { between } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(between(0n, 5n)(3n), true) * assert.deepStrictEqual(between(0n, 5n)(-1n), false) * assert.deepStrictEqual(between(0n, 5n)(6n), false) * * @category predicates * @since 1.0.0 */ export const between: { (minimum: bigint, maximum: bigint): (self: bigint) => boolean (self: bigint, minimum: bigint, maximum: bigint): boolean } = order.between(Order) /** * Restricts the given `bigint` to be within the range specified by the `minimum` and `maximum` values. * * - If the `bigint` is less than the `minimum` value, the function returns the `minimum` value. * - If the `bigint` is greater than the `maximum` value, the function returns the `maximum` value. * - Otherwise, it returns the original `bigint`. * * @param self - The `bigint` to be clamped. * @param minimum - The lower end of the range. * @param maximum - The upper end of the range. * * @example * import { clamp } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(clamp(0n, 5n)(3n), 3n) * assert.deepStrictEqual(clamp(0n, 5n)(-1n), 0n) * assert.deepStrictEqual(clamp(0n, 5n)(6n), 5n) * * @since 1.0.0 */ export const clamp: { (minimum: bigint, maximum: bigint): (self: bigint) => bigint (self: bigint, minimum: bigint, maximum: bigint): bigint } = order.clamp(Order) /** * Returns the minimum between two `bigint`s. * * @param self - The first `bigint`. * @param that - The second `bigint`. * * @example * import { min } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(min(2n, 3n), 2n) * * @since 1.0.0 */ export const min: { (that: bigint): (self: bigint) => bigint (self: bigint, that: bigint): bigint } = order.min(Order) /** * Returns the maximum between two `bigint`s. * * @param self - The first `bigint`. * @param that - The second `bigint`. * * @example * import { max } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(max(2n, 3n), 3n) * * @since 1.0.0 */ export const max: { (that: bigint): (self: bigint) => bigint (self: bigint, that: bigint): bigint } = order.max(Order) /** * `bigint` semigroup under addition. * * @example * import { SemigroupSum } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(SemigroupSum.combine(2n, 3n), 5n) * * @category instances * @since 1.0.0 */ export const SemigroupSum: semigroup.Semigroup = semigroup.bigintSum /** * `bigint` semigroup under multiplication. * * @category instances * @since 1.0.0 */ export const SemigroupMultiply: semigroup.Semigroup = semigroup.bigintMultiply /** * A `Semigroup` that uses the minimum between two values. * * @example * import { SemigroupMin } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(SemigroupMin.combine(2n, 3n), 2n) * * @category instances * @since 1.0.0 */ export const SemigroupMin: semigroup.Semigroup = semigroup.min(Order) /** * A `Semigroup` that uses the maximum between two values. * * @example * import { SemigroupMax } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(SemigroupMax.combine(2n, 3n), 3n) * * @category instances * @since 1.0.0 */ export const SemigroupMax: semigroup.Semigroup = semigroup.max(Order) /** * `bigint` monoid under addition. * * The `empty` value is `0n`. * * @example * import { MonoidSum } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(MonoidSum.combine(2n, 3n), 5n) * assert.deepStrictEqual(MonoidSum.combine(2n, MonoidSum.empty), 2n) * * @category instances * @since 1.0.0 */ export const MonoidSum: monoid.Monoid = monoid.bigintSum /** * `bigint` monoid under multiplication. * * The `empty` value is `1n`. * * @example * import { MonoidMultiply } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(MonoidMultiply.combine(2n, 3n), 6n) * assert.deepStrictEqual(MonoidMultiply.combine(2n, MonoidMultiply.empty), 2n) * * @category instances * @since 1.0.0 */ export const MonoidMultiply: monoid.Monoid = monoid.bigintMultiply /** * Determines the sign of a given `bigint`. * * @param n - The `bigint` to determine the sign of. * * @example * import { sign } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(sign(-5n), -1) * assert.deepStrictEqual(sign(0n), 0) * assert.deepStrictEqual(sign(5n), 1) * * @category math * @since 1.0.0 */ export const sign = (n: bigint): Ordering => Order.compare(n, 0n) /** * Takes an `Iterable` of `bigint`s and returns their sum as a single `bigint * * @param collection - The collection of `bigint`s to sum. * * @example * import { sumAll } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(sumAll([2n, 3n, 4n]), 9n) * * @category math * @since 1.0.0 */ export const sumAll: (collection: Iterable) => bigint = MonoidSum.combineAll /** * Takes an `Iterable` of `bigint`s and returns their multiplication as a single `number`. * * @param collection - The collection of `bigint`s to multiply. * * @example * import { multiplyAll } from '@fp-ts/core/Bigint' * * assert.deepStrictEqual(multiplyAll([2n, 3n, 4n]), 24n) * * @category math * @since 1.0.0 */ export const multiplyAll: (collection: Iterable) => bigint = MonoidMultiply.combineAll ================================================ FILE: src/Boolean.ts ================================================ /** * This module provides utility functions and type class instances for working with the `boolean` type in TypeScript. * It includes functions for basic boolean operations, as well as type class instances for * `Equivalence`, `Order`, `Semigroup`, and `Monoid`. * * @since 1.0.0 */ import type { LazyArg } from "@fp-ts/core/Function" import { dual, flow } from "@fp-ts/core/Function" import * as predicate from "@fp-ts/core/Predicate" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as order from "@fp-ts/core/typeclass/Order" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * Tests if a value is a `boolean`. * * @param input - The value to test. * * @example * import { isBoolean } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(isBoolean(true), true) * assert.deepStrictEqual(isBoolean("true"), false) * * @category guards * @since 1.0.0 */ export const isBoolean: (input: unknown) => input is boolean = predicate.isBoolean /** * This function returns the result of either of the given functions depending on the value of the boolean parameter. * It is useful when you have to run one of two functions depending on the boolean value. * * @param value - the boolean value that decides which function will be executed. * @param onFalse - a lazy evaluation function that will be executed when the `value` is `false`. * @param onTrue - a lazy evaluation function that will be executed when the `value` is `true`. * * @example * import * as B from "@fp-ts/core/Boolean" * * assert.deepStrictEqual( * B.match(true, () => "It's false!", () => "It's true!"), * "It's true!" * ) * * @category pattern matching * @since 1.0.0 */ export const match: { (onFalse: LazyArg, onTrue: LazyArg): (value: boolean) => A | B (value: boolean, onFalse: LazyArg, onTrue: LazyArg): A | B } = dual( 3, (value: boolean, onFalse: LazyArg, onTrue: LazyArg): A | B => value ? onTrue() : onFalse() ) /** * @category instances * @since 1.0.0 */ export const Equivalence: equivalence.Equivalence = equivalence.boolean /** * @category instances * @since 1.0.0 */ export const Order: order.Order = order.boolean /** * `boolean` semigroup under conjunction. * * @example * import { SemigroupAll } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(SemigroupAll.combine(true, true), true) * assert.deepStrictEqual(SemigroupAll.combine(true, false), false) * assert.deepStrictEqual(SemigroupAll.combine(false, true), false) * assert.deepStrictEqual(SemigroupAll.combine(false, false), false) * * @category instances * @since 1.0.0 */ export const SemigroupAll: semigroup.Semigroup = semigroup.booleanAll /** * `boolean` semigroup under disjunction. * * @example * import { SemigroupAny } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(SemigroupAny.combine(true, true), true) * assert.deepStrictEqual(SemigroupAny.combine(true, false), true) * assert.deepStrictEqual(SemigroupAny.combine(false, true), true) * assert.deepStrictEqual(SemigroupAny.combine(false, false), false) * * @category instances * @since 1.0.0 */ export const SemigroupAny: semigroup.Semigroup = semigroup.booleanAny /** * `boolean` semigroup under exclusive disjunction. * * @example * import { SemigroupXor } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(SemigroupXor.combine(true, true), false) * assert.deepStrictEqual(SemigroupXor.combine(true, false), true) * assert.deepStrictEqual(SemigroupXor.combine(false, true), true) * assert.deepStrictEqual(SemigroupXor.combine(false, false), false) * * @category instances * @since 1.0.0 */ export const SemigroupXor: semigroup.Semigroup = semigroup.booleanXor /** * `boolean` semigroup under equivalence. * * @example * import { SemigroupEqv } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(SemigroupEqv.combine(true, true), true) * assert.deepStrictEqual(SemigroupEqv.combine(true, false), false) * assert.deepStrictEqual(SemigroupEqv.combine(false, true), false) * assert.deepStrictEqual(SemigroupEqv.combine(false, false), true) * * @category instances * @since 1.0.0 */ export const SemigroupEqv: semigroup.Semigroup = semigroup.booleanEqv /** * `boolean` monoid under conjunction, see also {@link SemigroupAll}. * * The `empty` value is `true`. * * @category instances * @since 1.0.0 */ export const MonoidAll: monoid.Monoid = monoid.booleanAll /** * `boolean` monoid under disjunction, see also {@link SemigroupAny}. * * The `empty` value is `false`. * * @category instances * @since 1.0.0 */ export const MonoidAny: monoid.Monoid = monoid.booleanAny /** * `boolean` monoid under exclusive disjunction, see also {@link SemigroupXor}. * * The `empty` value is `false`. * * @category instances * @since 1.0.0 */ export const MonoidXor: monoid.Monoid = monoid.booleanXor /** * `boolean` monoid under equivalence. * * The `empty` value is `true`. * * @category instances * @since 1.0.0 */ export const MonoidEqv: monoid.Monoid = monoid.booleanEqv /** * Negates the given boolean: `!self` * * @example * import { not } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(not(true), false) * assert.deepStrictEqual(not(false), true) * * @category combinators * @since 1.0.0 */ export const not = (self: boolean): boolean => !self /** * Combines two boolean using AND: `self && that`. * * @example * import { and } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(and(true, true), true) * assert.deepStrictEqual(and(true, false), false) * assert.deepStrictEqual(and(false, true), false) * assert.deepStrictEqual(and(false, false), false) * * @category combinators * @since 1.0.0 */ export const and: { (that: boolean): (self: boolean) => boolean (self: boolean, that: boolean): boolean } = dual(2, semigroup.booleanAll.combine) /** * Combines two boolean using NAND: `!(self && that)`. * * @example * import { nand } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(nand(true, true), false) * assert.deepStrictEqual(nand(true, false), true) * assert.deepStrictEqual(nand(false, true), true) * assert.deepStrictEqual(nand(false, false), true) * * @category combinators * @since 1.0.0 */ export const nand: { (that: boolean): (self: boolean) => boolean (self: boolean, that: boolean): boolean } = dual(2, flow(semigroup.booleanAll.combine, not)) /** * Combines two boolean using OR: `self || that`. * * @example * import { or } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(or(true, true), true) * assert.deepStrictEqual(or(true, false), true) * assert.deepStrictEqual(or(false, true), true) * assert.deepStrictEqual(or(false, false), false) * * @category combinators * @since 1.0.0 */ export const or: { (that: boolean): (self: boolean) => boolean (self: boolean, that: boolean): boolean } = dual(2, semigroup.booleanAny.combine) /** * Combines two booleans using NOR: `!(self || that)`. * * @example * import { nor } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(nor(true, true), false) * assert.deepStrictEqual(nor(true, false), false) * assert.deepStrictEqual(nor(false, true), false) * assert.deepStrictEqual(nor(false, false), true) * * @category combinators * @since 1.0.0 */ export const nor: { (that: boolean): (self: boolean) => boolean (self: boolean, that: boolean): boolean } = dual(2, flow(semigroup.booleanAny.combine, not)) /** * Combines two booleans using XOR: `(!self && that) || (self && !that)`. * * @example * import { xor } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(xor(true, true), false) * assert.deepStrictEqual(xor(true, false), true) * assert.deepStrictEqual(xor(false, true), true) * assert.deepStrictEqual(xor(false, false), false) * * @category combinators * @since 1.0.0 */ export const xor: { (that: boolean): (self: boolean) => boolean (self: boolean, that: boolean): boolean } = dual(2, semigroup.booleanXor.combine) /** * Combines two booleans using EQV (aka XNOR): `!xor(self, that)`. * * @example * import { eqv } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(eqv(true, true), true) * assert.deepStrictEqual(eqv(true, false), false) * assert.deepStrictEqual(eqv(false, true), false) * assert.deepStrictEqual(eqv(false, false), true) * * @category combinators * @since 1.0.0 */ export const eqv: { (that: boolean): (self: boolean) => boolean (self: boolean, that: boolean): boolean } = dual(2, semigroup.booleanEqv.combine) /** * Combines two booleans using an implication: `(!self || that)`. * * @example * import { implies } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(implies(true, true), true) * assert.deepStrictEqual(implies(true, false), false) * assert.deepStrictEqual(implies(false, true), true) * assert.deepStrictEqual(implies(false, false), true) * * @category combinators * @since 1.0.0 */ export const implies: { (that: boolean): (self: boolean) => boolean (self: boolean, that: boolean): boolean } = dual(2, (self, that) => self ? that : true) /** * This utility function is used to check if all the elements in a collection of boolean values are `true`. * * @param collection - An iterable collection of booleans. * * @example * import { all } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(all([true, true, true]), true) * assert.deepStrictEqual(all([true, false, true]), false) * * @since 1.0.0 */ export const all: (collection: Iterable) => boolean = MonoidAll.combineAll /** * This utility function is used to check if at least one of the elements in a collection of boolean values is `true`. * * @param collection - An iterable collection of booleans. * * @example * import { any } from '@fp-ts/core/Boolean' * * assert.deepStrictEqual(any([true, false, true]), true) * assert.deepStrictEqual(any([false, false, false]), false) * * @since 1.0.0 */ export const any: (collection: Iterable) => boolean = MonoidAny.combineAll ================================================ FILE: src/Either.ts ================================================ /** * @since 1.0.0 */ import type { LazyArg } from "@fp-ts/core/Function" import { constNull, constUndefined, dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import { structural } from "@fp-ts/core/internal/effect" import * as either from "@fp-ts/core/internal/Either" import * as option from "@fp-ts/core/internal/Option" import * as N from "@fp-ts/core/Number" import type { Option } from "@fp-ts/core/Option" import type { Predicate, Refinement } from "@fp-ts/core/Predicate" import * as applicative from "@fp-ts/core/typeclass/Applicative" import * as bicovariant from "@fp-ts/core/typeclass/Bicovariant" import * as chainable from "@fp-ts/core/typeclass/Chainable" import * as covariant from "@fp-ts/core/typeclass/Covariant" import type { Equivalence } from "@fp-ts/core/typeclass/Equivalence" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as flatMap_ from "@fp-ts/core/typeclass/FlatMap" import * as foldable from "@fp-ts/core/typeclass/Foldable" import * as invariant from "@fp-ts/core/typeclass/Invariant" import type * as monad from "@fp-ts/core/typeclass/Monad" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import * as of_ from "@fp-ts/core/typeclass/Of" import type * as pointed from "@fp-ts/core/typeclass/Pointed" import * as product_ from "@fp-ts/core/typeclass/Product" import type * as semiAlternative from "@fp-ts/core/typeclass/SemiAlternative" import * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" import * as traversable from "@fp-ts/core/typeclass/Traversable" /** * @category models * @since 1.0.0 */ export type Either = Left | Right /** * @category models * @since 1.0.0 */ export interface Left { readonly _tag: "Left" readonly left: E } /** * @category models * @since 1.0.0 */ export interface Right { readonly _tag: "Right" readonly right: A } /** * @category type lambdas * @since 1.0.0 */ export interface EitherTypeLambda extends TypeLambda { readonly type: Either } /** * Constructs a new `Either` holding a `Right` value. This usually represents a successful value due to the right bias * of this structure. * * @category constructors * @since 1.0.0 */ export const right: (a: A) => Either = either.right /** * Constructs a new `Either` holding a `Left` value. This usually represents a failure, due to the right-bias of this * structure. * * @category constructors * @since 1.0.0 */ export const left: (e: E) => Either = either.left /** * Alias of {@link right}. * * @category constructors * @since 1.0.0 */ export const of: (a: A) => Either = right /** * Tests if a value is a `Either`. * * @param input - The value to test. * * @example * import { isEither, left, right } from '@fp-ts/core/Either' * * assert.deepStrictEqual(isEither(right(1)), true) * assert.deepStrictEqual(isEither(left("error")), true) * assert.deepStrictEqual(isEither({ right: 1 }), false) * * @category guards * @since 1.0.0 */ export const isEither = (input: unknown): input is Either => typeof input === "object" && input != null && structural in input && "_tag" in input && (input["_tag"] === "Left" || input["_tag"] === "Right") /** * Determine if a `Either` is a `Left`. * * @param self - The `Either` to check. * * @example * import { isLeft, left, right } from '@fp-ts/core/Either' * * assert.deepStrictEqual(isLeft(right(1)), false) * assert.deepStrictEqual(isLeft(left("error")), true) * * @category guards * @since 1.0.0 */ export const isLeft: (self: Either) => self is Left = either.isLeft /** * Determine if a `Either` is a `Right`. * * @param self - The `Either` to check. * * @example * import { isRight, left, right } from '@fp-ts/core/Either' * * assert.deepStrictEqual(isRight(right(1)), true) * assert.deepStrictEqual(isRight(left("error")), false) * * @category guards * @since 1.0.0 */ export const isRight: (self: Either) => self is Right = either.isRight /** * Returns a `Refinement` from a `Either` returning function. * This function ensures that a `Refinement` definition is type-safe. * * @category conversions * @since 1.0.0 */ export const toRefinement = (f: (a: A) => Either): Refinement => (a: A): a is B => isRight(f(a)) /** * @category conversions * @since 1.0.0 */ export const fromIterable: { (onEmpty: LazyArg): (collection: Iterable) => Either (collection: Iterable, onEmpty: LazyArg): Either } = dual(2, (collection: Iterable, onEmpty: LazyArg): Either => { for (const a of collection) { return right(a) } return left(onEmpty()) }) /** * Converts a `Either` to an `Option` discarding the error. * * @param self - The `Either` to convert to an `Option`. * * @example * import * as O from '@fp-ts/core/Option' * import * as E from '@fp-ts/core/Either' * * assert.deepStrictEqual(E.toOption(E.right(1)), O.some(1)) * assert.deepStrictEqual(E.toOption(E.left('a')), O.none()) * * @category conversions * @since 1.0.0 */ export const toOption: (self: Either) => Option = either.getRight /** * Converts a `Either` to an `Option` discarding the error. * * Alias of {@link toOption}. * * @example * import * as O from '@fp-ts/core/Option' * import * as E from '@fp-ts/core/Either' * * assert.deepStrictEqual(E.getRight(E.right('ok')), O.some('ok')) * assert.deepStrictEqual(E.getRight(E.left('err')), O.none()) * * @category conversions * @since 1.0.0 */ export const getRight: (self: Either) => Option = toOption /** * Converts a `Either` to an `Option` discarding the value. * * @example * import * as O from '@fp-ts/core/Option' * import * as E from '@fp-ts/core/Either' * * assert.deepStrictEqual(E.getLeft(E.right('ok')), O.none()) * assert.deepStrictEqual(E.getLeft(E.left('err')), O.some('err')) * * @category conversions * @since 1.0.0 */ export const getLeft: (self: Either) => Option = either.getLeft /** * @example * import * as E from '@fp-ts/core/Either' * import * as O from '@fp-ts/core/Option' * * assert.deepStrictEqual(E.fromOption(O.some(1), () => 'error'), E.right(1)) * assert.deepStrictEqual(E.fromOption(O.none(), () => 'error'), E.left('error')) * * @category conversions * @since 1.0.0 */ export const fromOption: { (fa: Option, onNone: () => E): Either (onNone: () => E): (fa: Option) => Either } = either.fromOption /** * @category equivalence * @since 1.0.0 */ export const getEquivalence = ( EE: Equivalence, EA: Equivalence ): Equivalence> => equivalence.make((x, y) => x === y || (isLeft(x) ? isLeft(y) && EE(x.left, y.left) : isRight(y) && EA(x.right, y.right)) ) /** * @category mapping * @since 1.0.0 */ export const bimap: { (f: (e: E1) => E2, g: (a: A) => B): (self: Either) => Either (self: Either, f: (e: E1) => E2, g: (a: A) => B): Either } = dual( 3, (self: Either, f: (e: E1) => E2, g: (a: A) => B): Either => isLeft(self) ? left(f(self.left)) : right(g(self.right)) ) /** * @category instances * @since 1.0.0 */ export const Bicovariant: bicovariant.Bicovariant = { bimap } /** * Maps the `Left` side of an `Either` value to a new `Either` value. * * @param self - The input `Either` value to map. * @param f - A transformation function to apply to the `Left` value of the input `Either`. * * @category error handling * @since 1.0.0 */ export const mapLeft: { (f: (e: E) => G): (self: Either) => Either (self: Either, f: (e: E) => G): Either } = bicovariant.mapLeft(Bicovariant) /** * Maps the `Right` side of an `Either` value to a new `Either` value. * * @param self - An `Either` to map * @param f - The function to map over the value of the `Either` * * @category mapping * @since 1.0.0 */ export const map: { (f: (a: A) => B): (self: Either) => Either (self: Either, f: (a: A) => B): Either } = dual( 2, (self: Either, f: (a: A) => B): Either => isRight(self) ? right(f(self.right)) : self ) const imap = covariant.imap(map) /** * @category instances * @since 1.0.0 */ export const Covariant: covariant.Covariant = { imap, map } /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } /** * @category mapping * @since 1.0.0 */ export const flap: { (a: A, self: Either B>): Either (self: Either B>): (a: A) => Either } = covariant.flap(Covariant) /** * Maps the Right value of this effect to the specified constant value. * * @category mapping * @since 1.0.0 */ export const as: { (self: Either, b: B): Either (b: B): (self: Either) => Either } = covariant.as(Covariant) /** * Returns the effect Eithering from mapping the Right of this effect to unit. * * @category mapping * @since 1.0.0 */ export const asUnit: (self: Either) => Either = covariant.asUnit( Covariant ) /** * @category instances * @since 1.0.0 */ export const Of: of_.Of = { of } /** * @since 1.0.0 */ export const unit: Either = of_.unit(Of) /** * @category instances * @since 1.0.0 */ export const Pointed: pointed.Pointed = { of, imap, map } /** * @category combining * @since 1.0.0 */ export const flatMap: { (f: (a: A) => Either): (self: Either) => Either (self: Either, f: (a: A) => Either): Either } = dual( 2, (self: Either, f: (a: A) => Either): Either => isLeft(self) ? self : f(self.right) ) /** * @category instances * @since 1.0.0 */ export const FlatMap: flatMap_.FlatMap = { flatMap } /** * @since 1.0.0 */ export const flatten: (self: Either>) => Either = flatMap_ .flatten(FlatMap) /** * @since 1.0.0 */ export const andThen: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } = flatMap_.andThen(FlatMap) /** * @since 1.0.0 */ export const composeKleisliArrow: { ( afb: (a: A) => Either, bfc: (b: B) => Either ): (a: A) => Either ( bfc: (b: B) => Either ): (afb: (a: A) => Either) => (a: A) => Either } = flatMap_.composeKleisliArrow(FlatMap) /** * @category instances * @since 1.0.0 */ export const Chainable: chainable.Chainable = { imap, map, flatMap } /** * Sequences the specified effect after this effect, but ignores the value * produced by the effect. * * @category combining * @since 1.0.0 */ export const andThenDiscard: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } = chainable.andThenDiscard(Chainable) /** * @category instances * @since 1.0.0 */ export const Monad: monad.Monad = { imap, of, map, flatMap } const product = (self: Either, that: Either): Either => isRight(self) ? (isRight(that) ? right([self.right, that.right]) : that) : self const productMany = ( self: Either, collection: Iterable> ): Either]> => { if (isLeft(self)) { return self } const out: [A, ...Array] = [self.right] for (const e of collection) { if (isLeft(e)) { return e } out.push(e.right) } return right(out) } /** * @category instances * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } /** * Similar to `Promise.all` but operates on `Either`s. * * ``` * Iterable> -> Either * ``` * * Flattens a collection of `Either`s into a single `Either` that contains a list of all the `Right` values. * If there is a `Left` value in the collection, it returns the first `Left` found as the result. * * @param collection - An iterable collection of `Either`s to flatten. * * @example * import * as E from "@fp-ts/core/Either" * * assert.deepStrictEqual(E.all([E.right(1), E.right(2), E.right(3)]), E.right([1, 2, 3])) * assert.deepStrictEqual(E.all([E.right(1), E.left("error"), E.right(3)]), E.left("error")) * * @category combining * @since 1.0.0 */ export const all = ( collection: Iterable> ): Either> => { const out: Array = [] for (const e of collection) { if (isLeft(e)) { return e } out.push(e.right) } return right(out) } /** * @category instances * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll: all } /** * Similar to `Promise.all` but operates on `Either`s. * * ``` * [Either, Either, ...] -> Either * ``` * * @since 1.0.0 */ export const tuple: >>( ...elements: T ) => Either< [T[number]] extends [Either] ? E : never, { [I in keyof T]: [T[I]] extends [Either] ? A : never } > = product_.tuple(Product) /** * @since 1.0.0 */ export const struct: >>( fields: R ) => Either< [R[keyof R]] extends [Either] ? E : never, { [K in keyof R]: [R[K]] extends [Either] ? A : never } > = product_.struct(Product) /** * @category instances * @since 1.0.0 */ export const SemiApplicative: semiApplicative.SemiApplicative = { imap, map, product, productMany } /** * Lifts a binary function into `Either`. * * @param f - The function to lift. * * @category lifting * @since 1.0.0 */ export const lift2: (f: (a: A, b: B) => C) => { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } = semiApplicative.lift2(SemiApplicative) /** * @category combining * @since 1.0.0 */ export const zipWith: { ( self: Either, that: Either, f: (a: A, b: B) => C ): Either ( that: Either, f: (a: A, b: B) => C ): (self: Either) => Either } = semiApplicative.zipWith(SemiApplicative) /** * @since 1.0.0 */ export const ap: { (self: Either B>, that: Either): Either (that: Either): (self: Either B>) => Either } = semiApplicative.ap(SemiApplicative) /** * @category instances * @since 1.0.0 */ export const Applicative: applicative.Applicative = { imap, of, map, product, productMany, productAll: all } /** * `Semigroup` returning the left-most `Left` value. If both operands are `Right`s then the inner values * are combined using the provided `Semigroup`. * * ``` * | self | that | combine(self, that) | * | ---------- | ---------- | ----------------------- | * | left(e1) | left(e2) | left(e1) | * | left(e1) | right(a2) | left(e1) | * | right(a1) | left(e2) | left(e2) | * | right(a1) | right(a2) | right(combine(a1, a2)) | * ``` * * @category combining * @since 1.0.0 */ export const getFirstLeftSemigroup: (S: Semigroup) => Semigroup> = semiApplicative.getSemigroup(SemiApplicative) /** * `Monoid` returning the left-most `Left` value. If both operands are `Right`s then the inner values * are combined using the provided `Monoid`. * * - `combine` is provided by {@link getFirstLeftSemigroup}. * - `empty` is `right(M.empty)` * * @category combining * @since 1.0.0 */ export const getFirstLeftMonoid: (M: Monoid) => Monoid> = applicative .getMonoid(Applicative) const coproduct = ( self: Either, that: Either ): Either => isRight(self) ? self : that const coproductMany = ( self: Either, collection: Iterable> ): Either => { let out = self if (isRight(out)) { return out } for (out of collection) { if (isRight(out)) { return out } } return out } /** * @category instances * @since 1.0.0 */ export const SemiCoproduct: semiCoproduct.SemiCoproduct = { imap, coproduct, coproductMany } /** * @category error handling * @since 1.0.0 */ export const firstRightOf: { (collection: Iterable>): (self: Either) => Either (self: Either, collection: Iterable>): Either } = dual(2, coproductMany) /** * Semigroup returning the left-most `Right` value. * * ``` * | self | that | combine(self, that) | * | ---------- | ---------- | ------------------- | * | left(e1) | left(e2) | left(e2) | * | left(e1) | right(a2) | right(a2) | * | right(a1) | left(e2) | right(a1) | * | right(a1) | right(a2) | right(a1) | * ``` * * @category combining * @since 1.0.0 */ export const getFirstRightSemigroup: () => Semigroup> = semiCoproduct .getSemigroup(SemiCoproduct) /** * Returns the wrapped value if it's a `Right` or a default value if is a `Left`. * * @example * import * as E from '@fp-ts/core/Either' * import { pipe } from '@fp-ts/core/Function' * * assert.deepStrictEqual( * E.getOrElse(E.right(1), () => 0), * 1 * ) * assert.deepStrictEqual( * E.getOrElse(E.left('error'), () => 0), * 0 * ) * * @category getters * @since 1.0.0 */ export const getOrElse: { (onLeft: (e: E) => B): (self: Either) => B | A (self: Either, onLeft: (e: E) => B): A | B } = dual( 2, (self: Either, onLeft: (e: E) => B): A | B => isLeft(self) ? onLeft(self.left) : self.right ) /** * Executes this effect and returns its value, if it succeeds, but otherwise * executes the specified effect. * * @category error handling * @since 1.0.0 */ export const orElse: { (that: (e1: E1) => Either): (self: Either) => Either (self: Either, that: (e1: E1) => Either): Either } = dual( 2, (self: Either, that: (e1: E1) => Either): Either => isLeft(self) ? that(self.left) : self ) /** * Returns an effect that will produce the value of this effect, unless it * fails, in which case, it will produce the value of the specified effect. * * @category error handling * @since 1.0.0 */ export const orElseEither: { (that: (e1: E1) => Either): (self: Either) => Either> (self: Either, that: (e1: E1) => Either): Either> } = dual( 2, (self: Either, that: (e1: E1) => Either): Either> => isLeft(self) ? map(that(self.left), right) : map(self, left) ) /** * Executes this effect and returns its value, if it succeeds, but otherwise * fails with the specified error. * * @category error handling * @since 1.0.0 */ export const orElseFail: { (onLeft: LazyArg): (self: Either) => Either (self: Either, onLeft: LazyArg): Either } = dual( 2, (self: Either, onLeft: LazyArg): Either => orElse(self, () => left(onLeft())) ) /** * @category instances * @since 1.0.0 */ export const SemiAlternative: semiAlternative.SemiAlternative = { map, imap, coproduct, coproductMany: firstRightOf } /** * @category instances * @since 1.0.0 */ export const Foldable: foldable.Foldable = { reduce: dual( 3, (self: Either, b: B, f: (b: B, a: A) => B): B => isLeft(self) ? b : f(b, self.right) ) } /** * Transforms an `Either` into an `Array`. * If the input is `Left`, an empty array is returned. * If the input is `Right`, the value is wrapped in an array. * * @param self - The `Either` to convert to an array. * * @example * import { right, left, toArray } from '@fp-ts/core/Either' * * assert.deepStrictEqual(toArray(right(1)), [1]) * assert.deepStrictEqual(toArray(left("error")), []) * * @category conversions * @since 1.0.0 */ export const toArray: (self: Either) => Array = foldable.toArray(Foldable) /** * Takes two functions and an `Either` value, if the value is a `Left` the inner value is applied to the first function, * if the value is a `Right` the inner value is applied to the second function. * * @example * import * as E from '@fp-ts/core/Either' * import { pipe } from '@fp-ts/core/Function' * * const onLeft = (errors: ReadonlyArray): string => `Errors: ${errors.join(', ')}` * * const onRight = (value: number): string => `Ok: ${value}` * * assert.deepStrictEqual( * pipe( * E.right(1), * E.match(onLeft , onRight) * ), * 'Ok: 1' * ) * assert.deepStrictEqual( * pipe( * E.left(['error 1', 'error 2']), * E.match(onLeft , onRight) * ), * 'Errors: error 1, error 2' * ) * * @category pattern matching * @since 1.0.0 */ export const match: { (onLeft: (e: E) => B, onRight: (a: A) => C): (self: Either) => B | C (self: Either, onLeft: (e: E) => B, onRight: (a: A) => C): B | C } = dual( 3, (self: Either, onLeft: (e: E) => B, onRight: (a: A) => C): B | C => isLeft(self) ? onLeft(self.left) : onRight(self.right) ) /** * Takes a lazy default and a nullable value, if the value is not nully, turn it into a `Right`, if the value is nully use * the provided default as a `Left`. * * @example * import * as E from '@fp-ts/core/Either' * * const parse = E.fromNullable(() => 'nullable') * * assert.deepStrictEqual(parse(1), E.right(1)) * assert.deepStrictEqual(parse(null), E.left('nullable')) * * @category interop * @since 1.0.0 */ export const fromNullable: { (onNullable: (a: A) => E): (a: A) => Either> (a: A, onNullable: (a: A) => E): Either> } = dual( 2, (a: A, onNullable: (a: A) => E): Either> => a == null ? left(onNullable(a)) : right(a as NonNullable) ) /** * @category interop * @since 1.0.0 */ export const liftNullable = , B, E>( f: (...a: A) => B | null | undefined, onNullable: (...a: A) => E ) => (...a: A): Either> => fromNullable(f(...a), () => onNullable(...a)) /** * @category interop * @since 1.0.0 */ export const merge: (self: Either) => E | A = match(identity, identity) /** * @category combining * @since 1.0.0 */ export const flatMapNullable: { ( f: (a: A) => B | null | undefined, onNullable: (a: A) => E2 ): (self: Either) => Either> ( self: Either, f: (a: A) => B | null | undefined, onNullable: (a: A) => E2 ): Either> } = dual(3, ( self: Either, f: (a: A) => B | null | undefined, onNullable: (a: A) => E2 ): Either> => flatMap(self, liftNullable(f, onNullable))) /** * Extracts the value of an `Either` or throws if the `Either` is `Left`. * * If a default error is sufficient for your use case and you don't need to configure the thrown error, see {@link getOrThrow}. * * @param self - The `Either` to extract the value from. * @param onLeft - A function that will be called if the `Either` is `Left`. It returns the error to be thrown. * * @example * import * as E from "@fp-ts/core/Either" * * assert.deepStrictEqual( * E.getOrThrowWith(E.right(1), () => new Error('Unexpected Left')), * 1 * ) * assert.throws(() => E.getOrThrowWith(E.left("error"), () => new Error('Unexpected Left'))) * * @category interop * @since 1.0.0 */ export const getOrThrowWith: { (onLeft: (e: E) => unknown): (self: Either) => A (self: Either, onLeft: (e: E) => unknown): A } = dual(2, (self: Either, onLeft: (e: E) => unknown): A => { if (isRight(self)) { return self.right } throw onLeft(self.left) }) /** * Extracts the value of an `Either` or throws if the `Either` is `Left`. * * The thrown error is a default error. To configure the error thrown, see {@link getOrThrowWith}. * * @param self - The `Either` to extract the value from. * @throws `Error("getOrThrow called on a Left")` * * @example * import * as E from "@fp-ts/core/Either" * * assert.deepStrictEqual(E.getOrThrow(E.right(1)), 1) * assert.throws(() => E.getOrThrow(E.left("error"))) * * @category interop * @since 1.0.0 */ export const getOrThrow: (self: Either) => A = getOrThrowWith(() => new Error("getOrThrow called on a Left") ) /** * Lifts a function that may throw to one returning a `Either`. * * @category interop * @since 1.0.0 */ export const liftThrowable = , B, E>( f: (...a: A) => B, onThrow: (error: unknown) => E ): ((...a: A) => Either) => (...a) => { try { return right(f(...a)) } catch (e) { return left(onThrow(e)) } } /** * @since 1.0.0 */ export const reverse = (self: Either): Either => isLeft(self) ? right(self.left) : left(self.right) /** * @category filtering * @since 1.0.0 */ export const filter: { (refinement: Refinement, onFalse: LazyArg): ( self: Either ) => Either ( predicate: Predicate, onFalse: LazyArg ): (self: Either) => Either ( self: Either, refinement: Refinement, onFalse: LazyArg ): Either ( self: Either, predicate: Predicate, onFalse: LazyArg ): Either } = dual(3, ( self: Either, predicate: Predicate, onFalse: LazyArg ): Either => isLeft(self) ? self : predicate(self.right) ? self : left(onFalse())) /** * @category filtering * @since 1.0.0 */ export const filterMap: { ( f: (a: A) => Option, onNone: LazyArg ): (self: Either) => Either ( self: Either, f: (a: A) => Option, onNone: LazyArg ): Either } = dual(3, ( self: Either, f: (a: A) => Option, onNone: LazyArg ): Either => flatMap(self, (a) => { const ob = f(a) return option.isNone(ob) ? left(onNone()) : right(ob.value) })) /** * @category filtering * @since 1.0.0 */ export const compact: { (onNone: LazyArg): (self: Either>) => Either (self: Either>, onNone: LazyArg): Either } = dual( 2, (self: Either>, onNone: LazyArg): Either => filterMap(self, identity, onNone) ) /** * @category traversing * @since 1.0.0 */ export const traverse = ( F: applicative.Applicative ): { ( f: (a: A) => Kind ): (self: Either) => Kind> ( self: Either, f: (a: A) => Kind ): Kind> } => dual(2, ( self: Either, f: (a: A) => Kind ): Kind> => isLeft(self) ? F.of>(self) : F.map>(f(self.right), right)) /** * @category instances * @since 1.0.0 */ export const Traversable: traversable.Traversable = { traverse } /** * @category traversing * @since 1.0.0 */ export const sequence: ( F: applicative.Applicative ) => ( self: Either> ) => Kind> = traversable.sequence(Traversable) /** * @category traversing * @since 1.0.0 */ export const traverseTap: ( F: applicative.Applicative ) => { ( self: Either, f: (a: A) => Kind ): Kind> ( f: (a: A) => Kind ): (self: Either) => Kind> } = traversable.traverseTap(Traversable) /** * Returns an effect that effectfully "peeks" at the success of this effect. * * @category combinators * @since 1.0.0 */ export const tap: { (self: Either, f: (a: A) => Either): Either (f: (a: A) => Either): (self: Either) => Either } = chainable.tap(Chainable) /** * @category debugging * @since 1.0.0 */ export const inspectRight: { (onRight: (a: A) => void): (self: Either) => Either (self: Either, onRight: (a: A) => void): Either } = dual(2, (self: Either, onRight: (a: A) => void): Either => { if (isRight(self)) { onRight(self.right) } return self }) /** * @category debugging * @since 1.0.0 */ export const inspectLeft: { (onLeft: (e: E) => void): (self: Either) => Either (self: Either, onLeft: (e: E) => void): Either } = dual(2, (self: Either, onLeft: (e: E) => void): Either => { if (isLeft(self)) { onLeft(self.left) } return self }) /** * Returns an effect that effectfully "peeks" at the failure of this effect. * * @category error handling * @since 1.0.0 */ export const tapError: { (onLeft: (e: E1) => Either): (self: Either) => Either (self: Either, onLeft: (e: E1) => Either): Either } = dual( 2, (self: Either, onLeft: (e: E1) => Either): Either => { if (isRight(self)) { return self } const out = onLeft(self.left) return isLeft(out) ? out : self } ) /** * @category getters * @since 1.0.0 */ export const getOrNull: (self: Either) => A | null = getOrElse(constNull) /** * @category getters * @since 1.0.0 */ export const getOrUndefined: (self: Either) => A | undefined = getOrElse(constUndefined) /** * @example * import { liftPredicate, left, right } from '@fp-ts/core/Either' * import { pipe } from '@fp-ts/core/Function' * * assert.deepStrictEqual( * pipe( * 1, * liftPredicate((n) => n > 0, () => 'error') * ), * right(1) * ) * assert.deepStrictEqual( * pipe( * -1, * liftPredicate((n) => n > 0, () => 'error') * ), * left('error') * ) * * @category lifting * @since 1.0.0 */ export const liftPredicate: { ( refinement: Refinement, onFalse: (c: C) => E ): (c: C) => Either (predicate: Predicate, onFalse: (b: B) => E): (b: B) => Either } = (predicate: Predicate, onFalse: (b: B) => E) => (b: B) => predicate(b) ? right(b) : left(onFalse(b)) /** * @category lifting * @since 1.0.0 */ export const liftOption = , B, E>( f: (...a: A) => Option, onNone: (...a: A) => E ) => (...a: A): Either => fromOption(() => onNone(...a))(f(...a)) /** * @category combining * @since 1.0.0 */ export const flatMapOption: { ( f: (a: A) => Option, onNone: (a: A) => E2 ): (self: Either) => Either ( self: Either, f: (a: A) => Option, onNone: (a: A) => E2 ): Either } = dual(3, ( self: Either, f: (a: A) => Option, onNone: (a: A) => E2 ): Either => flatMap(self, liftOption(f, onNone))) /** * Returns a function that checks if an `Either` contains a given value using a provided `equivalence` function. * * @since 1.0.0 */ export const contains = (isEquivalent: (self: A, that: A) => boolean): { (a: A): (self: Either) => boolean (self: Either, a: A): boolean } => dual( 2, (self: Either, a: A): boolean => isLeft(self) ? false : isEquivalent(self.right, a) ) /** * Returns `false` if `Left` or returns the Either of the application of the given predicate to the `Right` value. * * @example * import * as E from '@fp-ts/core/Either' * * const f = E.exists((n: number) => n > 2) * * assert.deepStrictEqual(f(E.left('a')), false) * assert.deepStrictEqual(f(E.right(1)), false) * assert.deepStrictEqual(f(E.right(3)), true) * * @since 1.0.0 */ export const exists: { (predicate: Predicate): (self: Either) => boolean (self: Either, predicate: Predicate): boolean } = dual( 2, (self: Either, predicate: Predicate): boolean => isLeft(self) ? false : predicate(self.right) ) /** * Semigroup that models the combination of values that may be absent, elements that are `Left` are ignored * while elements that are `Right` are combined using the provided `Semigroup`. * * @category instances * @since 1.0.0 */ export const getOptionalSemigroup = (S: Semigroup): Semigroup> => semigroup.make(( x, y ) => (isLeft(y) ? x : isLeft(x) ? y : right(S.combine(x.right, y.right)))) /** * @category math * @since 1.0.0 */ export const sum: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } = lift2(N.sum) /** * @category math * @since 1.0.0 */ export const multiply: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } = lift2(N.multiply) /** * @category math * @since 1.0.0 */ export const subtract: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } = lift2(N.subtract) /** * @category math * @since 1.0.0 */ export const divide: { (self: Either, that: Either): Either (that: Either): (self: Either) => Either } = lift2(N.divide) /** * Return all the `Right` elements from an `Interable` of `Either`s. * * @category getters * @since 1.0.0 */ export const rights = (self: Iterable>): Array => { const out: Array = [] for (const a of self) { if (isRight(a)) { out.push(a.right) } } return out } /** * Return all the `Left` elements from an `Interable` of `Either`s. * * @category getters * @since 1.0.0 */ export const lefts = (self: Iterable>): Array => { const out: Array = [] for (const a of self) { if (isLeft(a)) { out.push(a.left) } } return out } // ------------------------------------------------------------------------------------- // do notation // ------------------------------------------------------------------------------------- /** * @category do notation * @since 1.0.0 */ export const tupled: (self: Either) => Either = invariant.tupled( Invariant ) /** * Appends an element to the end of a tuple. * * @category do notation * @since 1.0.0 */ export const appendElement: { , E2, B>( self: Either, that: Either ): Either ( that: Either ): >(self: Either) => Either } = semiProduct.appendElement(SemiProduct) /** * @category do notation * @since 1.0.0 */ export const bindTo: { ( name: N ): (self: Either) => Either (self: Either, name: N): Either } = invariant.bindTo(Invariant) const let_: { ( name: Exclude, f: (a: A) => B ): ( self: Either ) => Either ( self: Either, name: Exclude, f: (a: A) => B ): Either } = covariant.let(Covariant) export { /** * @category do notation * @since 1.0.0 */ let_ as let } /** * @category do notation * @since 1.0.0 */ export const Do: Either = of_.Do(Of) /** * @category do notation * @since 1.0.0 */ export const bind: { ( name: Exclude, f: (a: A) => Either ): ( self: Either ) => Either ( self: Either, name: Exclude, f: (a: A) => Either ): Either } = chainable.bind(Chainable) /** * Extends the `Either` value with the value of another `Either` type. * * If both `Either` instances are `Left`, then the result will be the first `Left`. * * @param self - The original `Either` value. * @param name - The name of the property that will be added to the original `Either` type. * @param that - The `Either` value that will be added to the original `Either` type. * * @example * import * as E from '@fp-ts/core/Either' * import { pipe } from '@fp-ts/core/Function' * * const result = pipe( * E.Do, * E.bind("a", () => E.left("e1")), * E.andThenBind("b", E.left("e2")) * ) * * assert.deepStrictEqual(result, E.left("e1")) * * @category do notation * @since 1.0.0 */ export const andThenBind: { ( name: Exclude, that: Either ): ( self: Either ) => Either ( self: Either, name: Exclude, that: Either ): Either } = semiProduct.andThenBind(SemiProduct) ================================================ FILE: src/Function.ts ================================================ /** * @since 1.0.0 */ import type { TypeLambda } from "@fp-ts/core/HKT" /** * @category type lambdas * @since 1.0.0 */ export interface FunctionTypeLambda extends TypeLambda { readonly type: (a: this["In"]) => this["Target"] } /** * Tests if a value is a `function`. * * @param input - The value to test. * * @example * import { isFunction } from '@fp-ts/core/Predicate' * * assert.deepStrictEqual(isFunction(isFunction), true) * assert.deepStrictEqual(isFunction("function"), false) * * @category guards * @since 1.0.0 */ export const isFunction = (input: unknown): input is Function => typeof input === "function" /** * Creates a function that can be used in a data-last (aka `pipe`able) or data-first style. * * @param arity - The arity of the uncurried function. * @param body - The definition of the uncurried function. * * @example * import { dual, pipe } from "@fp-ts/core/Function" * * export const sum: { * (that: number): (self: number) => number * (self: number, that: number): number * } = dual(2, (self: number, that: number): number => self + that) * * assert.deepStrictEqual(sum(2, 3), 5) * assert.deepStrictEqual(pipe(2, sum(3)), 5) * * @since 1.0.0 */ export const dual = < DataLast extends (...args: Array) => any, DataFirst extends (...args: Array) => any >( arity: Parameters["length"], body: DataFirst ): DataLast & DataFirst => { // @ts-expect-error return function() { if (arguments.length >= arity) { // @ts-expect-error return body.apply(this, arguments) } return ((self: any) => body(self, ...arguments)) as any } } /** * Apply a function to a given value. * * @param a - The value that the function will be applied to. * @param self - The function to be applied to a value. * * @example * import { pipe, apply } from "@fp-ts/core/Function" * import { length } from '@fp-ts/core/String' * * assert.deepStrictEqual(pipe(length, apply("hello")), 5) * * @since 1.0.0 */ export const apply = (a: A) => (self: (a: A) => B): B => self(a) /** * A lazy argument. * * @example * import { LazyArg, constant } from "@fp-ts/core/Function" * * export const constNull: LazyArg = constant(null) * * @since 1.0.0 */ export interface LazyArg { (): A } /** * @example * import { FunctionN } from "@fp-ts/core/Function" * * export const sum: FunctionN<[number, number], number> = (a, b) => a + b * * @since 1.0.0 */ export interface FunctionN, B> { (...args: A): B } /** * The identity function, i.e. A function that returns its input argument. * * @param a - The input argument. * * @example * import { identity } from "@fp-ts/core/Function" * * assert.deepStrictEqual(identity(5), 5) * * @since 1.0.0 */ export const identity = (a: A): A => a /** * Casts the result to the specified type. * * @param a - The value to be casted to the target type. * * @example * import { unsafeCoerce, identity } from "@fp-ts/core/Function" * * assert.deepStrictEqual(unsafeCoerce, identity) * * @since 1.0.0 */ export const unsafeCoerce: (a: A) => B = identity as any /** * Creates a constant value that never changes. * * This is useful when you want to pass a value to a higher-order function (a function that takes another function as its argument) * and want that inner function to always use the same value, no matter how many times it is called. * * @param value - The constant value to be returned. * * @example * import { constant } from "@fp-ts/core/Function" * * const constNull = constant(null) * * assert.deepStrictEqual(constNull(), null) * assert.deepStrictEqual(constNull(), null) * * @since 1.0.0 */ export const constant = (value: A): LazyArg => () => value /** * A thunk that returns always `true`. * * @example * import { constTrue } from "@fp-ts/core/Function" * * assert.deepStrictEqual(constTrue(), true) * * @since 1.0.0 */ export const constTrue: LazyArg = constant(true) /** * A thunk that returns always `false`. * * @example * import { constFalse } from "@fp-ts/core/Function" * * assert.deepStrictEqual(constFalse(), false) * * @since 1.0.0 */ export const constFalse: LazyArg = constant(false) /** * A thunk that returns always `null`. * * @example * import { constNull } from "@fp-ts/core/Function" * * assert.deepStrictEqual(constNull(), null) * * @since 1.0.0 */ export const constNull: LazyArg = constant(null) /** * A thunk that returns always `undefined`. * * @example * import { constUndefined } from "@fp-ts/core/Function" * * assert.deepStrictEqual(constUndefined(), undefined) * * @since 1.0.0 */ export const constUndefined: LazyArg = constant(undefined) /** * A thunk that returns always `void`. * * @example * import { constVoid } from "@fp-ts/core/Function" * * assert.deepStrictEqual(constVoid(), undefined) * * @since 1.0.0 */ export const constVoid: LazyArg = constUndefined /** * Reverses the order of arguments for a curried function. * * @param f - A curried function that takes multiple arguments. * * @example * import { flip } from "@fp-ts/core/Function" * * const f = (a: number) => (b: string) => a - b.length * * assert.deepStrictEqual(flip(f)('aaa')(2), -1) * * @since 1.0.0 */ export const flip = , B extends Array, C>( f: (...a: A) => (...b: B) => C ): ((...b: B) => (...a: A) => C) => (...b) => (...a) => f(...a)(...b) /** * Performs left-to-right function composition. The first argument may have any arity, the remaining arguments must be unary. * * See also {@link pipe}. * * @example * import { flow } from "@fp-ts/core/Function" * * const len = (s: string): number => s.length * const double = (n: number): number => n * 2 * * const f = flow(len, double) * * assert.deepStrictEqual(f('aaa'), 6) * * @since 1.0.0 */ export function flow, B>(ab: (...a: A) => B): (...a: A) => B export function flow, B, C>( ab: (...a: A) => B, bc: (b: B) => C ): (...a: A) => C export function flow, B, C, D>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D ): (...a: A) => D export function flow, B, C, D, E>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E ): (...a: A) => E export function flow, B, C, D, E, F>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F ): (...a: A) => F export function flow, B, C, D, E, F, G>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G ): (...a: A) => G export function flow, B, C, D, E, F, G, H>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H ): (...a: A) => H export function flow, B, C, D, E, F, G, H, I>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I ): (...a: A) => I export function flow, B, C, D, E, F, G, H, I, J>( ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J ): (...a: A) => J export function flow( ab: Function, bc?: Function, cd?: Function, de?: Function, ef?: Function, fg?: Function, gh?: Function, hi?: Function, ij?: Function ): unknown { switch (arguments.length) { case 1: return ab case 2: return function(this: unknown) { return bc!(ab.apply(this, arguments)) } case 3: return function(this: unknown) { return cd!(bc!(ab.apply(this, arguments))) } case 4: return function(this: unknown) { return de!(cd!(bc!(ab.apply(this, arguments)))) } case 5: return function(this: unknown) { return ef!(de!(cd!(bc!(ab.apply(this, arguments))))) } case 6: return function(this: unknown) { return fg!(ef!(de!(cd!(bc!(ab.apply(this, arguments)))))) } case 7: return function(this: unknown) { return gh!(fg!(ef!(de!(cd!(bc!(ab.apply(this, arguments))))))) } case 8: return function(this: unknown) { return hi!(gh!(fg!(ef!(de!(cd!(bc!(ab.apply(this, arguments)))))))) } case 9: return function(this: unknown) { return ij!(hi!(gh!(fg!(ef!(de!(cd!(bc!(ab.apply(this, arguments))))))))) } } return } /** * Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`. * The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`. * * @param ab - A function that maps from `A` to `B`. * @param bc - A function that maps from `B` to `C`. * * @example * import { compose } from "@fp-ts/core/Function" * * const increment = (n: number) => n + 1; * const square = (n: number) => n * n; * * assert.strictEqual(compose(increment, square)(2), 9); * * @since 1.0.0 */ export const compose: { (bc: (b: B) => C): (self: (a: A) => B) => (a: A) => C (self: (a: A) => B, bc: (b: B) => C): (a: A) => C } = dual(2, (ab: (a: A) => B, bc: (b: B) => C): (a: A) => C => flow(ab, bc)) /** * The `absurd` function is a stub for cases where a value of type `never` is encountered in your code, * meaning that it should be impossible for this code to be executed. * * This function is particularly when it's necessary to specify that certain cases are impossible. * * @since 1.0.0 */ export const absurd = (_: never): A => { throw new Error("Called `absurd` function which should be uncallable") } /** * Creates a tupled version of this function: instead of `n` arguments, it accepts a single tuple argument. * * @example * import { tupled } from "@fp-ts/core/Function" * * const sumTupled = tupled((x: number, y: number): number => x + y) * * assert.deepStrictEqual(sumTupled([1, 2]), 3) * * @since 1.0.0 */ export const tupled = , B>(f: (...a: A) => B): ((a: A) => B) => (a) => f(...a) /** * Inverse function of `tupled` * * @example * import { untupled } from "@fp-ts/core/Function" * * const getFirst = untupled((tuple: [A, B]): A => tuple[0]) * * assert.deepStrictEqual(getFirst(1, 2), 1) * * @since 1.0.0 */ export const untupled = , B>(f: (a: A) => B): ((...a: A) => B) => (...a) => f(a) /** * Pipes the value of an expression into a pipeline of functions. * * This is useful in combination with data-last functions as a simulation of methods: * * ``` * as.map(f).filter(g) -> pipe(as, map(f), filter(g)) * ``` * * See also {@link flow}. * * @example * import { pipe } from "@fp-ts/core/Function" * * const length = (s: string): number => s.length * const double = (n: number): number => n * 2 * const decrement = (n: number): number => n - 1 * * assert.deepStrictEqual(pipe(length("hello"), double, decrement), 9) * * @since 1.0.0 */ export function pipe(a: A): A export function pipe(a: A, ab: (a: A) => B): B export function pipe(a: A, ab: (a: A) => B, bc: (b: B) => C): C export function pipe(a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E ): E export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F ): F export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G ): G export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H ): H export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I ): I export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J ): J export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K ): K export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L ): L export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M ): M export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N ): N export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O ): O export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P ): P export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q ): Q export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R ): R export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S ): S export function pipe( a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F, fg: (f: F) => G, gh: (g: G) => H, hi: (h: H) => I, ij: (i: I) => J, jk: (j: J) => K, kl: (k: K) => L, lm: (l: L) => M, mn: (m: M) => N, no: (n: N) => O, op: (o: O) => P, pq: (p: P) => Q, qr: (q: Q) => R, rs: (r: R) => S, st: (s: S) => T ): T export function pipe( a: unknown, ab?: Function, bc?: Function, cd?: Function, de?: Function, ef?: Function, fg?: Function, gh?: Function, hi?: Function ): unknown { switch (arguments.length) { case 1: return a case 2: return ab!(a) case 3: return bc!(ab!(a)) case 4: return cd!(bc!(ab!(a))) case 5: return de!(cd!(bc!(ab!(a)))) case 6: return ef!(de!(cd!(bc!(ab!(a))))) case 7: return fg!(ef!(de!(cd!(bc!(ab!(a)))))) case 8: return gh!(fg!(ef!(de!(cd!(bc!(ab!(a))))))) case 9: return hi!(gh!(fg!(ef!(de!(cd!(bc!(ab!(a)))))))) default: { let ret = arguments[0] for (let i = 1; i < arguments.length; i++) { ret = arguments[i](ret) } return ret } } } /** * Type hole simulation. * * @since 1.0.0 */ export const hole: () => T = unsafeCoerce(absurd) /** * The SK combinator, also known as the "S-K combinator" or "S-combinator", is a fundamental combinator in the * lambda calculus and the SKI combinator calculus. * * This function is useful for discarding the first argument passed to it and returning the second argument. * * @param _ - The first argument to be discarded. * @param b - The second argument to be returned. * * @example * import { SK } from "@fp-ts/core/Function"; * * assert.deepStrictEqual(SK(0, "hello"), "hello") * * @since 1.0.0 */ export const SK = (_: A, b: B): B => b ================================================ FILE: src/HKT.ts ================================================ /** * @since 1.0.0 */ /** * @since 1.0.0 */ export declare const URI: unique symbol /** * @since 1.0.0 */ export interface TypeClass { readonly [URI]?: F } /** * @since 1.0.0 */ export interface TypeLambda { readonly In: unknown readonly Out2: unknown readonly Out1: unknown readonly Target: unknown } /** * @since 1.0.0 */ export type Kind = F extends { readonly type: unknown } ? (F & { readonly In: In readonly Out2: Out2 readonly Out1: Out1 readonly Target: Target })["type"] : { readonly F: F readonly In: (_: In) => void readonly Out2: () => Out2 readonly Out1: () => Out1 readonly Target: (_: Target) => Target } ================================================ FILE: src/Identity.ts ================================================ /** * @since 1.0.0 */ import { dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import * as readonlyArray from "@fp-ts/core/internal/ReadonlyArray" import type * as applicative from "@fp-ts/core/typeclass/Applicative" import * as chainable from "@fp-ts/core/typeclass/Chainable" import * as covariant from "@fp-ts/core/typeclass/Covariant" import type * as flatMap_ from "@fp-ts/core/typeclass/FlatMap" import type * as foldable from "@fp-ts/core/typeclass/Foldable" import * as invariant from "@fp-ts/core/typeclass/Invariant" import type * as monad from "@fp-ts/core/typeclass/Monad" import * as of_ from "@fp-ts/core/typeclass/Of" import type * as pointed from "@fp-ts/core/typeclass/Pointed" import type * as product_ from "@fp-ts/core/typeclass/Product" import type * as semiAlternative from "@fp-ts/core/typeclass/SemiAlternative" import type * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import type * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" import type * as traversable from "@fp-ts/core/typeclass/Traversable" /** * @category models * @since 1.0.0 */ export type Identity = A /** * @category type lambdas * @since 1.0.0 */ export interface IdentityTypeLambda extends TypeLambda { readonly type: Identity } /** * @category type lambdas * @since 1.0.0 */ export interface IdentityTypeLambdaFix extends TypeLambda { readonly type: Identity } const map: { (f: (a: A) => B): (self: Identity) => Identity (self: Identity, f: (a: A) => B): Identity } = dual(2, (self: Identity, f: (a: A) => B): Identity => f(self)) const imap = covariant.imap(map) /** * @category instances * @since 1.0.0 */ export const Covariant: covariant.Covariant = { imap, map } /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } const of: (a: A) => Identity = identity /** * @category instances * @since 1.0.0 */ export const Of: of_.Of = { of } /** * @category instances * @since 1.0.0 */ export const Pointed: pointed.Pointed = { of, imap, map } const flatMap: { (f: (a: A) => B): (self: Identity) => Identity (self: Identity, f: (a: A) => B): Identity } = dual(2, (self: Identity, f: (a: A) => B): Identity => f(self)) /** * @category instances * @since 1.0.0 */ export const FlatMap: flatMap_.FlatMap = { flatMap } /** * @category instances * @since 1.0.0 */ export const Chainable: chainable.Chainable = { imap, map, flatMap } /** * @category instances * @since 1.0.0 */ export const Monad: monad.Monad = { imap, of, map, flatMap } const product = (self: Identity, that: Identity): Identity<[A, B]> => [self, that] const productMany = ( self: Identity, collection: Iterable ): [A, ...Array] => [self, ...collection] /** * @category instances * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } /** * @category instances * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll: readonlyArray.fromIterable } /** * @category instances * @since 1.0.0 */ export const SemiApplicative: semiApplicative.SemiApplicative = { imap, map, product, productMany } /** * @category instances * @since 1.0.0 */ export const Applicative: applicative.Applicative = { imap, of, map, product, productMany, productAll: readonlyArray.fromIterable } /** * @category instances * @since 1.0.0 */ export const getSemiCoproduct = ( S: Semigroup ): semiCoproduct.SemiCoproduct> => ({ imap, coproduct: dual(2, S.combine), coproductMany: dual(2, S.combineMany) }) /** * @category instances * @since 1.0.0 */ export const getSemiAlternative = ( S: Semigroup ): semiAlternative.SemiAlternative> => ({ ...getSemiCoproduct(S), map }) /** * @category instances * @since 1.0.0 */ export const Foldable: foldable.Foldable = { reduce: dual(3, (self: Identity, b: B, f: (b: B, a: A) => B): B => f(b, self)) } const traverse = ( F: applicative.Applicative ): { (f: (a: A) => Kind): (self: Identity) => Kind (self: Identity, f: (a: A) => Kind): Kind } => dual( 2, (self: Identity, f: (a: A) => Kind): Kind => f(self) ) /** * @category instances * @since 1.0.0 */ export const Traversable: traversable.Traversable = { traverse } // ------------------------------------------------------------------------------------- // do notation // ------------------------------------------------------------------------------------- /** * @category do notation * @since 1.0.0 */ export const bindTo: { (name: N): (self: Identity) => Identity<{ [K in N]: A }> (self: Identity, name: N): Identity<{ [K in N]: A }> } = invariant.bindTo(Invariant) const let_: { ( name: Exclude, f: (a: A) => B ): (self: Identity) => Identity<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: Identity, name: Exclude, f: (a: A) => B ): Identity<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = covariant.let(Covariant) export { /** * @category do notation * @since 1.0.0 */ let_ as let } /** * @category do notation * @since 1.0.0 */ export const Do: Identity<{}> = of_.Do(Of) /** * @category do notation * @since 1.0.0 */ export const bind: { ( name: Exclude, f: (a: A) => Identity ): (self: Identity) => Identity<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: Identity, name: Exclude, f: (a: A) => Identity ): Identity<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = chainable.bind(Chainable) /** * A variant of `bind` that sequentially ignores the scope. * * @category do notation * @since 1.0.0 */ export const andThenBind: { ( name: Exclude, that: Identity ): (self: Identity) => Identity<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: Identity, name: Exclude, that: Identity ): Identity<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = semiProduct.andThenBind(SemiProduct) ================================================ FILE: src/Number.ts ================================================ /** * This module provides utility functions and type class instances for working with the `number` type in TypeScript. * It includes functions for basic arithmetic operations, as well as type class instances for * `Equivalence`, `Order`, `Semigroup`, and `Monoid`. * * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { Ordering } from "@fp-ts/core/Ordering" import * as predicate from "@fp-ts/core/Predicate" import * as bounded from "@fp-ts/core/typeclass/Bounded" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as order from "@fp-ts/core/typeclass/Order" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * Tests if a value is a `number`. * * @param input - The value to test. * * @example * import { isNumber } from '@fp-ts/core/Number' * * assert.deepStrictEqual(isNumber(2), true) * assert.deepStrictEqual(isNumber("2"), false) * * @category guards * @since 1.0.0 */ export const isNumber: (input: unknown) => input is number = predicate.isNumber /** * Provides an addition operation on `number`s. * * @param self - The first operand. * @param that - The second operand. * * @example * import { sum } from '@fp-ts/core/Number' * * assert.deepStrictEqual(sum(2, 3), 5) * * @category math * @since 1.0.0 */ export const sum: { (that: number): (self: number) => number (self: number, that: number): number } = dual(2, semigroup.numberSum.combine) /** * Provides a multiplication operation on `number`s. * * @param self - The first operand. * @param that - The second operand. * * @example * import { multiply } from '@fp-ts/core/Number' * * assert.deepStrictEqual(multiply(2, 3), 6) * * @category math * @since 1.0.0 */ export const multiply: { (that: number): (self: number) => number (self: number, that: number): number } = dual(2, semigroup.numberMultiply.combine) /** * Provides a subtraction operation on `number`s. * * @param self - The first operand. * @param that - The second operand. * * @example * import { subtract } from '@fp-ts/core/Number' * * assert.deepStrictEqual(subtract(2, 3), -1) * * @category math * @since 1.0.0 */ export const subtract: { (that: number): (self: number) => number (self: number, that: number): number } = dual(2, (self: number, that: number): number => self - that) /** * Provides a division operation on `number`s. * * @param self - The dividend operand. * @param that - The divisor operand. * * @example * import { divide } from '@fp-ts/core/Number' * * assert.deepStrictEqual(divide(6, 3), 2) * * @category math * @since 1.0.0 */ export const divide: { (that: number): (self: number) => number (self: number, that: number): number } = dual(2, (self: number, that: number): number => self / that) /** * Returns the result of adding `1` to a given number. * * @param n - A `number` to be incremented. * * @example * import { increment } from '@fp-ts/core/Number' * * assert.deepStrictEqual(increment(2), 3) * * @category math * @since 1.0.0 */ export const increment = (n: number): number => n + 1 /** * Decrements a number by `1`. * * @param n - A `number` to be decremented. * * @example * import { decrement } from '@fp-ts/core/Number' * * assert.deepStrictEqual(decrement(3), 2) * * @category math * @since 1.0.0 */ export const decrement = (n: number): number => n - 1 /** * @category instances * @since 1.0.0 */ export const Equivalence: equivalence.Equivalence = equivalence.number /** * @category instances * @since 1.0.0 */ export const Order: order.Order = order.number /** * Returns `true` if the first argument is less than the second, otherwise `false`. * * @param self - The first argument. * @param that - The second argument. * * @example * import { lessThan } from '@fp-ts/core/Number' * * assert.deepStrictEqual(lessThan(2, 3), true) * assert.deepStrictEqual(lessThan(3, 3), false) * assert.deepStrictEqual(lessThan(4, 3), false) * * @category predicates * @since 1.0.0 */ export const lessThan: { (that: number): (self: number) => boolean (self: number, that: number): boolean } = order.lessThan(Order) /** * Returns a function that checks if a given `number` is less than or equal to the provided one. * * @param self - The first `number` to compare with. * @param that - The second `number` to compare with. * * @example * import { lessThanOrEqualTo } from '@fp-ts/core/Number' * * assert.deepStrictEqual(lessThanOrEqualTo(2, 3), true) * assert.deepStrictEqual(lessThanOrEqualTo(3, 3), true) * assert.deepStrictEqual(lessThanOrEqualTo(4, 3), false) * * @category predicates * @since 1.0.0 */ export const lessThanOrEqualTo: { (that: number): (self: number) => boolean (self: number, that: number): boolean } = order.lessThanOrEqualTo(Order) /** * Returns `true` if the first argument is greater than the second, otherwise `false`. * * @param self - The first argument. * @param that - The second argument. * * @example * import { greaterThan } from '@fp-ts/core/Number' * * assert.deepStrictEqual(greaterThan(2, 3), false) * assert.deepStrictEqual(greaterThan(3, 3), false) * assert.deepStrictEqual(greaterThan(4, 3), true) * * @category predicates * @since 1.0.0 */ export const greaterThan: { (that: number): (self: number) => boolean (self: number, that: number): boolean } = order.greaterThan(Order) /** * Returns a function that checks if a given `number` is greater than or equal to the provided one. * * @param self - The first `number` to compare with. * @param that - The second `number` to compare with. * * @example * import { greaterThanOrEqualTo } from '@fp-ts/core/Number' * * assert.deepStrictEqual(greaterThanOrEqualTo(2, 3), false) * assert.deepStrictEqual(greaterThanOrEqualTo(3, 3), true) * assert.deepStrictEqual(greaterThanOrEqualTo(4, 3), true) * * @category predicates * @since 1.0.0 */ export const greaterThanOrEqualTo: { (that: number): (self: number) => boolean (self: number, that: number): boolean } = order.greaterThanOrEqualTo(Order) /** * Checks if a `number` is between a `minimum` and `maximum` value (inclusive). * * @param self - The `number` to check. * @param minimum - The `minimum` value to check. * @param maximum - The `maximum` value to check. * * @example * import { between } from '@fp-ts/core/Number' * * assert.deepStrictEqual(between(0, 5)(3), true) * assert.deepStrictEqual(between(0, 5)(-1), false) * assert.deepStrictEqual(between(0, 5)(6), false) * * @category predicates * @since 1.0.0 */ export const between: { (minimum: number, maximum: number): (self: number) => boolean (self: number, minimum: number, maximum: number): boolean } = order.between(Order) /** * Restricts the given `number` to be within the range specified by the `minimum` and `maximum` values. * * - If the `number` is less than the `minimum` value, the function returns the `minimum` value. * - If the `number` is greater than the `maximum` value, the function returns the `maximum` value. * - Otherwise, it returns the original `number`. * * @param self - The `number` to be clamped. * @param minimum - The lower end of the range. * @param maximum - The upper end of the range. * * @example * import { clamp } from '@fp-ts/core/Number' * * assert.deepStrictEqual(clamp(0, 5)(3), 3) * assert.deepStrictEqual(clamp(0, 5)(-1), 0) * assert.deepStrictEqual(clamp(0, 5)(6), 5) * * @since 1.0.0 */ export const clamp: { (minimum: number, maximum: number): (self: number) => number (self: number, minimum: number, maximum: number): number } = order.clamp(Order) /** * Returns the minimum between two `number`s. * * @param self - The first `number`. * @param that - The second `number`. * * @example * import { min } from '@fp-ts/core/Number' * * assert.deepStrictEqual(min(2, 3), 2) * * @since 1.0.0 */ export const min: { (that: number): (self: number) => number (self: number, that: number): number } = order.min(Order) /** * Returns the maximum between two `number`s. * * @param self - The first `number`. * @param that - The second `number`. * * @example * import { max } from '@fp-ts/core/Number' * * assert.deepStrictEqual(max(2, 3), 3) * * @since 1.0.0 */ export const max: { (that: number): (self: number) => number (self: number, that: number): number } = order.max(Order) /** * @category instances * @since 1.0.0 */ export const Bounded: bounded.Bounded = bounded.number /** * `number` semigroup under addition. * * @example * import { SemigroupSum } from '@fp-ts/core/Number' * * assert.deepStrictEqual(SemigroupSum.combine(2, 3), 5) * * @category instances * @since 1.0.0 */ export const SemigroupSum: semigroup.Semigroup = semigroup.numberSum /** * `number` semigroup under multiplication. * * @example * import { SemigroupMultiply } from '@fp-ts/core/Number' * * assert.deepStrictEqual(SemigroupMultiply.combine(2, 3), 6) * * @category instances * @since 1.0.0 */ export const SemigroupMultiply: semigroup.Semigroup = semigroup.numberMultiply /** * A `Semigroup` that uses the minimum between two values. * * @example * import { SemigroupMin } from '@fp-ts/core/Number' * * assert.deepStrictEqual(SemigroupMin.combine(2, 3), 2) * * @category instances * @since 1.0.0 */ export const SemigroupMin: semigroup.Semigroup = semigroup.min(Order) /** * A `Semigroup` that uses the maximum between two values. * * @example * import { SemigroupMax } from '@fp-ts/core/Number' * * assert.deepStrictEqual(SemigroupMax.combine(2, 3), 3) * * @category instances * @since 1.0.0 */ export const SemigroupMax: semigroup.Semigroup = semigroup.max(Order) /** * `number` monoid under addition. * * The `empty` value is `0`. * * @example * import { MonoidSum } from '@fp-ts/core/Number' * * assert.deepStrictEqual(MonoidSum.combine(2, 3), 5) * assert.deepStrictEqual(MonoidSum.combine(2, MonoidSum.empty), 2) * * @category instances * @since 1.0.0 */ export const MonoidSum: monoid.Monoid = monoid.numberSum /** * `number` monoid under multiplication. * * The `empty` value is `1`. * * @example * import { MonoidMultiply } from '@fp-ts/core/Number' * * assert.deepStrictEqual(MonoidMultiply.combine(2, 3), 6) * assert.deepStrictEqual(MonoidMultiply.combine(2, MonoidMultiply.empty), 2) * * @category instances * @since 1.0.0 */ export const MonoidMultiply: monoid.Monoid = monoid.numberMultiply /** * A `Monoid` that uses the minimum between two values. * * The `empty` value is `-Infinity`. * * @example * import { MonoidMin } from '@fp-ts/core/Number' * * assert.deepStrictEqual(MonoidMin.combine(2, 3), 2) * assert.deepStrictEqual(MonoidMin.combine(2, MonoidMin.empty), 2) * * @category instances * @since 1.0.0 */ export const MonoidMin: monoid.Monoid = bounded.min(Bounded) /** * A `Monoid` that uses the maximum between two values. * * The `empty` value is `Infinity`. * * @example * import { MonoidMax } from '@fp-ts/core/Number' * * assert.deepStrictEqual(MonoidMax.combine(2, 3), 3) * assert.deepStrictEqual(MonoidMax.combine(2, MonoidMax.empty), 2) * * @category instances * @since 1.0.0 */ export const MonoidMax: monoid.Monoid = bounded.max(Bounded) /** * Determines the sign of a given `number`. * * @param n - The `number` to determine the sign of. * * @example * import { sign } from '@fp-ts/core/Number' * * assert.deepStrictEqual(sign(-5), -1) * assert.deepStrictEqual(sign(0), 0) * assert.deepStrictEqual(sign(5), 1) * * @category math * @since 1.0.0 */ export const sign = (n: number): Ordering => Order.compare(n, 0) /** * Takes an `Iterable` of `number`s and returns their sum as a single `number`. * * @param collection - The collection of `number`s to sum. * * @example * import { sumAll } from '@fp-ts/core/Number' * * assert.deepStrictEqual(sumAll([2, 3, 4]), 9) * * @category math * @since 1.0.0 */ export const sumAll: (collection: Iterable) => number = MonoidSum.combineAll /** * Takes an `Iterable` of `number`s and returns their multiplication as a single `number`. * * @param collection - The collection of `number`s to multiply. * * @example * import { multiplyAll } from '@fp-ts/core/Number' * * assert.deepStrictEqual(multiplyAll([2, 3, 4]), 24) * * @category math * @since 1.0.0 */ export const multiplyAll: (collection: Iterable) => number = MonoidMultiply.combineAll /** * Returns the remainder left over when one operand is divided by a second operand. * * It always takes the sign of the dividend. * * @param self - The dividend. * @param divisor - The divisor. * * @example * import { remainder } from "@fp-ts/core/Number" * * assert.deepStrictEqual(remainder(2, 2), 0) * assert.deepStrictEqual(remainder(3, 2), 1) * assert.deepStrictEqual(remainder(-4, 2), -0) * * @category math * @since 1.0.0 */ export const remainder: { (divisor: number): (self: number) => number (self: number, divisor: number): number } = dual(2, (self: number, divisor: number): number => { // https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034 const selfDecCount = (self.toString().split(".")[1] || "").length const divisorDecCount = (divisor.toString().split(".")[1] || "").length const decCount = selfDecCount > divisorDecCount ? selfDecCount : divisorDecCount const selfInt = parseInt(self.toFixed(decCount).replace(".", "")) const divisorInt = parseInt(divisor.toFixed(decCount).replace(".", "")) return (selfInt % divisorInt) / Math.pow(10, decCount) }) ================================================ FILE: src/Option.ts ================================================ /** * @since 1.0.0 */ import type { Either } from "@fp-ts/core/Either" import type { LazyArg } from "@fp-ts/core/Function" import { constNull, constUndefined, dual } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import { structural } from "@fp-ts/core/internal/effect" import * as either from "@fp-ts/core/internal/Either" import * as option from "@fp-ts/core/internal/Option" import * as N from "@fp-ts/core/Number" import type { Predicate, Refinement } from "@fp-ts/core/Predicate" import type * as alternative from "@fp-ts/core/typeclass/Alternative" import * as applicative from "@fp-ts/core/typeclass/Applicative" import * as chainable from "@fp-ts/core/typeclass/Chainable" import type * as coproduct_ from "@fp-ts/core/typeclass/Coproduct" import * as covariant from "@fp-ts/core/typeclass/Covariant" import type { Equivalence } from "@fp-ts/core/typeclass/Equivalence" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as filterable from "@fp-ts/core/typeclass/Filterable" import * as flatMap_ from "@fp-ts/core/typeclass/FlatMap" import * as foldable from "@fp-ts/core/typeclass/Foldable" import * as invariant from "@fp-ts/core/typeclass/Invariant" import type * as monad from "@fp-ts/core/typeclass/Monad" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as of_ from "@fp-ts/core/typeclass/Of" import type { Order } from "@fp-ts/core/typeclass/Order" import * as order from "@fp-ts/core/typeclass/Order" import type * as pointed from "@fp-ts/core/typeclass/Pointed" import * as product_ from "@fp-ts/core/typeclass/Product" import type * as semiAlternative from "@fp-ts/core/typeclass/SemiAlternative" import * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" import * as traversable from "@fp-ts/core/typeclass/Traversable" /** * @category models * @since 1.0.0 */ export type Option = None | Some /** * @category models * @since 1.0.0 */ export interface None { readonly _tag: "None" } /** * @category models * @since 1.0.0 */ export interface Some { readonly _tag: "Some" readonly value: A } /** * @category type lambdas * @since 1.0.0 */ export interface OptionTypeLambda extends TypeLambda { readonly type: Option } /** * Creates a new `Option` that represents the absence of a value. * * @category constructors * @since 1.0.0 */ export const none = (): Option => option.none /** * Creates a new `Option` that wraps the given value. * * @param value - The value to wrap. * * @category constructors * @since 1.0.0 */ export const some: (value: A) => Option = option.some /** * Alias of {@link some}. * * @category constructors * @since 1.0.0 */ export const of: (value: A) => Option = some /** * Tests if a value is a `Option`. * * @param input - The value to check. * * @example * import { some, none, isOption } from '@fp-ts/core/Option' * * assert.deepStrictEqual(isOption(some(1)), true) * assert.deepStrictEqual(isOption(none()), true) * assert.deepStrictEqual(isOption({}), false) * * @category guards * @since 1.0.0 */ export const isOption = (input: unknown): input is Option => typeof input === "object" && input != null && structural in input && "_tag" in input && (input["_tag"] === "None" || input["_tag"] === "Some") /** * Determine if a `Option` is a `None`. * * @param self - The `Option` to check. * * @example * import { some, none, isNone } from '@fp-ts/core/Option' * * assert.deepStrictEqual(isNone(some(1)), false) * assert.deepStrictEqual(isNone(none()), true) * * @category guards * @since 1.0.0 */ export const isNone: (self: Option) => self is None = option.isNone /** * Determine if a `Option` is a `Some`. * * @param self - The `Option` to check. * * @example * import { some, none, isSome } from '@fp-ts/core/Option' * * assert.deepStrictEqual(isSome(some(1)), true) * assert.deepStrictEqual(isSome(none()), false) * * @category guards * @since 1.0.0 */ export const isSome: (self: Option) => self is Some = option.isSome /** * Matches the given `Option` and returns either the provided `onNone` value or the result of the provided `onSome` * function when passed the `Option`'s value. * * @param self - The `Option` to match * @param onNone - The value to be returned if the `Option` is `None` * @param onSome - The function to be called if the `Option` is `Some`, it will be passed the `Option`'s value and its result will be returned * * @example * import { some, none, match } from '@fp-ts/core/Option' * import { pipe } from "@fp-ts/core/Function" * * assert.deepStrictEqual( * pipe( * some(1), * match(() => 'a none', a => `a some containing ${a}`) * ), * 'a some containing 1' * ) * * assert.deepStrictEqual( * pipe( * none(), * match(() => 'a none', a => `a some containing ${a}`) * ), * 'a none' * ) * * @category pattern matching * @since 1.0.0 */ export const match: { (onNone: LazyArg, onSome: (a: A) => C): (self: Option) => B | C (self: Option, onNone: LazyArg, onSome: (a: A) => C): B | C } = dual( 3, (self: Option, onNone: LazyArg, onSome: (a: A) => C): B | C => isNone(self) ? onNone() : onSome(self.value) ) /** * Returns a type guard from a `Option` returning function. * This function ensures that a type guard definition is type-safe. * * @example * import * as O from "@fp-ts/core/Option" * * const parsePositive = (n: number): O.Option => * n > 0 ? O.some(n) : O.none() * * const isPositive = O.toRefinement(parsePositive) * * assert.deepStrictEqual(isPositive(1), true) * assert.deepStrictEqual(isPositive(-1), false) * * @category conversions * @since 1.0.0 */ export const toRefinement = (f: (a: A) => Option): (a: A) => a is B => (a: A): a is B => isSome(f(a)) /** * Converts an `Iterable` of values into an `Option`. Returns the first value of the `Iterable` wrapped in a `Some` * if the `Iterable` is not empty, otherwise returns `None`. * * @param collection - The `Iterable` to be converted to an `Option`. * * @example * import { fromIterable, some, none } from '@fp-ts/core/Option' * * assert.deepStrictEqual(fromIterable([1, 2, 3]), some(1)) * assert.deepStrictEqual(fromIterable([]), none()) * * @category conversions * @since 1.0.0 */ export const fromIterable = (collection: Iterable): Option => { for (const a of collection) { return some(a) } return none() } /** * Converts a `Either` to an `Option` discarding the error. * * @param self - The `Either` to convert to an `Option`. * * @example * import * as O from "@fp-ts/core/Option" * import * as E from "@fp-ts/core/Either" * * assert.deepStrictEqual(O.fromEither(E.right(1)), O.some(1)) * assert.deepStrictEqual(O.fromEither(E.left('error message')), O.none()) * * @category conversions * @since 1.0.0 */ export const fromEither: (self: Either) => Option = either.getRight /** * Converts a `Either` to an `Option` discarding the error. * * Alias of {@link fromEither}. * * @example * import * as O from "@fp-ts/core/Option" * import * as E from "@fp-ts/core/Either" * * assert.deepStrictEqual(O.getRight(E.right('ok')), O.some('ok')) * assert.deepStrictEqual(O.getRight(E.left('err')), O.none()) * * @category conversions * @since 1.0.0 */ export const getRight: (self: Either) => Option = fromEither /** * Converts a `Either` to an `Option` discarding the value. * * @example * import * as O from "@fp-ts/core/Option" * import * as E from "@fp-ts/core/Either" * * assert.deepStrictEqual(O.getLeft(E.right("ok")), O.none()) * assert.deepStrictEqual(O.getLeft(E.left("error")), O.some("error")) * * @category conversions * @since 1.0.0 */ export const getLeft: (self: Either) => Option = either.getLeft /** * Converts an `Option` to an `Either`, allowing you to provide a value to be used in the case of a `None`. * * @param self - the `Option` to convert. * @param onNone - a function that produces an error value when the `Option` is `None`. * * @example * import { pipe } from "@fp-ts/core/Function" * import * as O from "@fp-ts/core/Option" * import * as E from "@fp-ts/core/Either" * * const onNone = () => 'error' * assert.deepStrictEqual(pipe(O.some(1), O.toEither(onNone)), E.right(1)) * assert.deepStrictEqual(pipe(O.none(), O.toEither(onNone)), E.left('error')) * * @category conversions * @since 1.0.0 */ export const toEither: { (self: Option, onNone: () => E): Either (onNone: () => E): (self: Option) => Either } = either.fromOption /** * Returns the value of the `Option` if it is `Some`, otherwise returns `onNone` * * @param self - The `Option` to get the value of. * @param onNone - Function that returns the default value to return if the `Option` is `None`. * * @example * import { some, none, getOrElse } from '@fp-ts/core/Option' * import { pipe } from "@fp-ts/core/Function" * * assert.deepStrictEqual(pipe(some(1), getOrElse(() => 0)), 1) * assert.deepStrictEqual(pipe(none(), getOrElse(() => 0)), 0) * * @category getters * @since 1.0.0 */ export const getOrElse: { (onNone: LazyArg): (self: Option) => B | A (self: Option, onNone: LazyArg): A | B } = dual( 2, (self: Option, onNone: LazyArg): A | B => isNone(self) ? onNone() : self.value ) /** * Returns the provided `Option` `that` if `self` is `None`, otherwise returns `self`. * * @param self - The first `Option` to be checked. * @param that - The `Option` to return if `self` is `None`. * * @example * import * as O from "@fp-ts/core/Option" * import { pipe } from "@fp-ts/core/Function" * * assert.deepStrictEqual( * pipe( * O.none(), * O.orElse(() => O.none()) * ), * O.none() * ) * assert.deepStrictEqual( * pipe( * O.some('a'), * O.orElse(() => O.none()) * ), * O.some('a') * ) * assert.deepStrictEqual( * pipe( * O.none(), * O.orElse(() => O.some('b')) * ), * O.some('b') * ) * assert.deepStrictEqual( * pipe( * O.some('a'), * O.orElse(() => O.some('b')) * ), * O.some('a') * ) * * @category error handling * @since 1.0.0 */ export const orElse: { (that: LazyArg>): (self: Option) => Option (self: Option, that: LazyArg>): Option } = dual( 2, (self: Option, that: LazyArg>): Option => isNone(self) ? that() : self ) /** * Similar to `orElse`, but instead of returning a simple union, it returns an `Either` object, * which contains information about which of the two `Option`s has been chosen. * * This is useful when it's important to know whether the value was retrieved from the first `Option` or the second option. * * @param self - The first `Option` to be checked. * @param that - The second `Option` to be considered if the first `Option` is `None`. * * @category error handling * @since 1.0.0 */ export const orElseEither: { (that: LazyArg>): (self: Option) => Option> (self: Option, that: LazyArg>): Option> } = dual( 2, (self: Option, that: LazyArg>): Option> => isNone(self) ? map(that(), either.right) : map(self, either.left) ) /** * Given an `Iterable` collection of `Option`s, returns the first `Some` found in the collection. * * @param collection - An iterable collection of `Option` to be searched. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.firstSomeOf([O.none(), O.some(1), O.some(2)]), O.some(1)) * * @category error handling * @since 1.0.0 */ export const firstSomeOf = (collection: Iterable>): Option => { let out: Option = none() for (out of collection) { if (isSome(out)) { return out } } return out } /** * Similar to `Promise.all` but operates on `Option`s. * * ``` * Iterable> -> Option * ``` * * Flattens a collection of `Option`s into a single `Option` that contains a list of all the `Some` values. * If there is a `None` value in the collection, it returns `None` as the result. * * @param collection - An iterable collection of `Option`s to flatten. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.all([O.some(1), O.some(2), O.some(3)]), O.some([1, 2, 3])) * assert.deepStrictEqual(O.all([O.some(1), O.none(), O.some(3)]), O.none()) * * @category combining * @since 1.0.0 */ export const all = (collection: Iterable>): Option> => { const out: Array = [] for (const o of collection) { if (isNone(o)) { return none() } out.push(o.value) } return some(out) } /** * Constructs a new `Option` from a nullable type. If the value is `null` or `undefined`, returns `None`, otherwise * returns the value wrapped in a `Some`. * * @param nullableValue - The nullable value to be converted to an `Option`. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.fromNullable(undefined), O.none()) * assert.deepStrictEqual(O.fromNullable(null), O.none()) * assert.deepStrictEqual(O.fromNullable(1), O.some(1)) * * @category conversions * @since 1.0.0 */ export const fromNullable = ( nullableValue: A ): Option< NonNullable > => (nullableValue == null ? none() : some(nullableValue as NonNullable)) /** * This API is useful for lifting a function that returns `null` or `undefined` into the `Option` context. * * @example * import * as O from "@fp-ts/core/Option" * * const parse = (s: string): number | undefined => { * const n = parseFloat(s) * return isNaN(n) ? undefined : n * } * * const parseOption = O.liftNullable(parse) * * assert.deepStrictEqual(parseOption('1'), O.some(1)) * assert.deepStrictEqual(parseOption('not a number'), O.none()) * * @category conversions * @since 1.0.0 */ export const liftNullable = , B>( f: (...a: A) => B | null | undefined ): ((...a: A) => Option>) => (...a) => fromNullable(f(...a)) /** * Returns the value of the `Option` if it is a `Some`, otherwise returns `null`. * * @param self - The `Option` to extract the value from. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.getOrNull(O.some(1)), 1) * assert.deepStrictEqual(O.getOrNull(O.none()), null) * * @category getters * @since 1.0.0 */ export const getOrNull: (self: Option) => A | null = getOrElse(constNull) /** * Returns the value of the `Option` if it is a `Some`, otherwise returns `undefined`. * * @param self - The `Option` to extract the value from. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.getOrUndefined(O.some(1)), 1) * assert.deepStrictEqual(O.getOrUndefined(O.none()), undefined) * * @category getters * @since 1.0.0 */ export const getOrUndefined: (self: Option) => A | undefined = getOrElse(constUndefined) /** * A utility function that lifts a function that throws exceptions into a function that returns an `Option`. * * This function is useful for any function that might throw an exception, allowing the developer to handle * the exception in a more functional way. * * @param f - the function that can throw exceptions. * * @example * import * as O from "@fp-ts/core/Option" * * const parse = O.liftThrowable(JSON.parse) * * assert.deepStrictEqual(parse("1"), O.some(1)) * assert.deepStrictEqual(parse(""), O.none()) * * @category conversions * @since 1.0.0 */ export const liftThrowable = , B>( f: (...a: A) => B ): ((...a: A) => Option) => (...a) => { try { return some(f(...a)) } catch (e) { return none() } } /** * Extracts the value of an `Option` or throws if the `Option` is `None`. * * If a default error is sufficient for your use case and you don't need to configure the thrown error, see {@link getOrThrow}. * * @param self - The `Option` to extract the value from. * @param onNone - A function that will be called if the `Option` is `None`. It returns the error to be thrown. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual( * O.getOrThrowWith(O.some(1), () => new Error('Unexpected None')), * 1 * ) * assert.throws(() => O.getOrThrowWith(O.none(), () => new Error('Unexpected None'))) * * @category conversions * @since 1.0.0 */ export const getOrThrowWith: { (onNone: () => unknown): (self: Option) => A (self: Option, onNone: () => unknown): A } = dual(2, (self: Option, onNone: () => unknown): A => { if (isSome(self)) { return self.value } throw onNone() }) /** * Extracts the value of an `Option` or throws if the `Option` is `None`. * * The thrown error is a default error. To configure the error thrown, see {@link getOrThrowWith}. * * @param self - The `Option` to extract the value from. * @throws `Error("getOrThrow called on a None")` * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.getOrThrow(O.some(1)), 1) * assert.throws(() => O.getOrThrow(O.none())) * * @category conversions * @since 1.0.0 */ export const getOrThrow: (self: Option) => A = getOrThrowWith(() => new Error("getOrThrow called on a None") ) /** * Maps the `Some` side of an `Option` value to a new `Option` value. * * @param self - An `Option` to map * @param f - The function to map over the value of the `Option` * * @category transforming * @since 1.0.0 */ export const map: { (f: (a: A) => B): (self: Option) => Option (self: Option, f: (a: A) => B): Option } = dual( 2, (self: Option, f: (a: A) => B): Option => isNone(self) ? none() : some(f(self.value)) ) const imap = covariant.imap(map) /** * @since 1.0.0 */ export const Covariant: covariant.Covariant = { imap, map } /** * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } /** * @category transforming * @since 1.0.0 */ export const flap: { (a: A, self: Option<(a: A) => B>): Option (self: Option<(a: A) => B>): (a: A) => Option } = covariant.flap(Covariant) /** * Maps the `Some` value of this `Option` to the specified constant value. * * @category transforming * @since 1.0.0 */ export const as: { <_, B>(self: Option<_>, b: B): Option (b: B): <_>(self: Option<_>) => Option } = covariant.as(Covariant) /** * Returns the `Option` resulting from mapping the `Some` value to `void`. * * This is useful when the value of the `Option` is not needed, but the presence or absence of the value is important. * * @category transforming * @since 1.0.0 */ export const asUnit: <_>(self: Option<_>) => Option = covariant.asUnit(Covariant) /** * @since 1.0.0 */ export const Of: of_.Of = { of } /** * @since 1.0.0 */ export const unit: Option = of_.unit(Of) /** * @since 1.0.0 */ export const Pointed: pointed.Pointed = { of, imap, map } /** * Applies a function to the value of an `Option` and flattens the result, if the input is `Some`. * * @category transforming * @since 1.0.0 */ export const flatMap: { (f: (a: A) => Option): (self: Option) => Option (self: Option, f: (a: A) => Option): Option } = dual( 2, (self: Option, f: (a: A) => Option): Option => isNone(self) ? none() : f(self.value) ) /** * Applies a provided function that returns an `Either` to the contents of an `Option`, flattening the result into another `Option`. * * @param self - The `Option` to apply the function to. * @param f - The function to be applied to the contents of the `Option`. * * @example * import * as O from "@fp-ts/core/Option" * import * as E from "@fp-ts/core/Either" * import { pipe } from "@fp-ts/core/Function" * * const f = (n: number) => (n > 2 ? E.left('Too big') : E.right(n + 1)) * * assert.deepStrictEqual(pipe(O.some(1), O.flatMapEither(f)), O.some(2)) * assert.deepStrictEqual(pipe(O.some(3), O.flatMapEither(f)), O.none()) * * @category transforming * @since 1.0.0 */ export const flatMapEither: { (f: (a: A) => Either): (self: Option) => Option (self: Option, f: (a: A) => Either): Option } = dual( 2, (self: Option, f: (a: A) => Either): Option => flatMap(self, liftEither(f)) ) /** * This is `flatMap` + `fromNullable`, useful when working with optional values. * * @example * import { some, none, flatMapNullable } from '@fp-ts/core/Option' * import { pipe } from "@fp-ts/core/Function" * * interface Employee { * company?: { * address?: { * street?: { * name?: string * } * } * } * } * * const employee1: Employee = { company: { address: { street: { name: 'high street' } } } } * * assert.deepStrictEqual( * pipe( * some(employee1), * flatMapNullable(employee => employee.company?.address?.street?.name), * ), * some('high street') * ) * * const employee2: Employee = { company: { address: { street: {} } } } * * assert.deepStrictEqual( * pipe( * some(employee2), * flatMapNullable(employee => employee.company?.address?.street?.name), * ), * none() * ) * * @category transforming * @since 1.0.0 */ export const flatMapNullable: { (f: (a: A) => B | null | undefined): (self: Option) => Option> (self: Option, f: (a: A) => B | null | undefined): Option> } = dual( 2, (self: Option, f: (a: A) => B | null | undefined): Option> => isNone(self) ? none() : fromNullable(f(self.value)) ) /** * @since 1.0.0 */ export const FlatMap: flatMap_.FlatMap = { flatMap } /** * @category transforming * @since 1.0.0 */ export const flatten: (self: Option>) => Option = flatMap_.flatten(FlatMap) /** * @category transforming * @since 1.0.0 */ export const andThen: { <_, B>(self: Option<_>, that: Option): Option (that: Option): <_>(self: Option<_>) => Option } = flatMap_.andThen(FlatMap) /** * @category transforming * @since 1.0.0 */ export const composeKleisliArrow: { (afb: (a: A) => Option, bfc: (b: B) => Option): (a: A) => Option (bfc: (b: B) => Option): (afb: (a: A) => Option) => (a: A) => Option } = flatMap_.composeKleisliArrow(FlatMap) /** * @since 1.0.0 */ export const Chainable: chainable.Chainable = { imap, map, flatMap } /** * Sequences the specified `that` `Option` but ignores its value. * * It is useful when we want to chain multiple operations, but only care about the result of `self`. * * @param that - The `Option` that will be ignored in the chain and discarded * @param self - The `Option` we care about * * @category transforming * @since 1.0.0 */ export const andThenDiscard: { (self: Option, that: Option<_>): Option <_>(that: Option<_>): (self: Option) => Option } = chainable.andThenDiscard(Chainable) /** * Applies the provided function `f` to the value of the `Option` if it is `Some` and returns the original `Option` * unless `f` returns `None`, in which case it returns `None`. * * This function is useful for performing additional computations on the value of the input `Option` without affecting its value. * * @param f - Function to apply to the value of the `Option` if it is `Some` * @param self - The `Option` to apply the function to * * @category transforming * @since 1.0.0 */ export const tap: { (self: Option, f: (a: A) => Option<_>): Option (f: (a: A) => Option<_>): (self: Option) => Option } = chainable.tap(Chainable) /** * Useful for debugging purposes, the `onSome` callback is called with the value of `self` if it is a `Some`. * * @param self - the `Option` to inspect * @param onSome - callback function that is called with the value of `self` if it is a `Some` * * @category debugging * @since 1.0.0 */ export const inspectSome: { (onSome: (a: A) => void): (self: Option) => Option (self: Option, onSome: (a: A) => void): Option } = dual(2, (self: Option, onSome: (a: A) => void): Option => { if (isSome(self)) { onSome(self.value) } return self }) /** * Useful for debugging purposes, the `onNone` callback is is called if `self` is a `None`. * * @param self - the `Option` to inspect * @param onNone - callback function that is is called if `self` is a `None` * * @category debugging * @since 1.0.0 */ export const inspectNone: { (onNone: () => void): (self: Option) => Option (self: Option, onNone: () => void): Option } = dual(2, (self: Option, onNone: () => void): Option => { if (isNone(self)) { onNone() } return self }) /** * @since 1.0.0 */ export const Monad: monad.Monad = { imap, of, map, flatMap } const product = (self: Option, that: Option): Option<[A, B]> => isSome(self) && isSome(that) ? some([self.value, that.value]) : none() const productMany = ( self: Option, collection: Iterable> ): Option<[A, ...Array]> => { if (isNone(self)) { return none() } const out: [A, ...Array] = [self.value] for (const o of collection) { if (isNone(o)) { return none() } out.push(o.value) } return some(out) } /** * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } /** * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll: all } /** * Similar to `Promise.all` but operates on `Option`s. * * ``` * [Option, Option, ...] -> Option<[A, B, ...]> * ``` * * Takes a tuple of `Option`s and returns an `Option` of a tuple of values. * * @param elements - the tuple of `Option`s to be sequenced. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.tuple(O.some(1), O.some("hello")), O.some([1, "hello"])) * assert.deepStrictEqual(O.tuple(O.some(1), O.none()), O.none()) * * @category combining * @since 1.0.0 */ export const tuple: >>( ...elements: T ) => Option<{ [I in keyof T]: [T[I]] extends [Option] ? A : never }> = product_.tuple( Product ) /** * Takes a struct of `Option`s and returns an `Option` of a struct of values. * * @param fields - the struct of `Option`s to be sequenced. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.struct({ a: O.some(1), b: O.some("hello") }), O.some({ a: 1, b: "hello" })) * assert.deepStrictEqual(O.struct({ a: O.some(1), b: O.none() }), O.none()) * * @category combining * @since 1.0.0 */ export const struct: >>( fields: R ) => Option<{ [K in keyof R]: [R[K]] extends [Option] ? A : never }> = product_ .struct(Product) /** * @since 1.0.0 */ export const SemiApplicative: semiApplicative.SemiApplicative = { imap, map, product, productMany } /** * Monoid that models the combination of values that may be absent, elements that are `None` are ignored * while elements that are `Some` are combined using the provided `Semigroup`. * * The `empty` value is `none()`. * * @param Semigroup - The `Semigroup` used to combine two values of type `A`. * * @example * import * as O from "@fp-ts/core/Option" * import * as N from '@fp-ts/core/Number' * import { pipe } from "@fp-ts/core/Function" * * const M = O.getOptionalMonoid(N.SemigroupSum) * * assert.deepStrictEqual(M.combine(O.none(), O.none()), O.none()) * assert.deepStrictEqual(M.combine(O.some(1), O.none()), O.some(1)) * assert.deepStrictEqual(M.combine(O.none(), O.some(1)), O.some(1)) * assert.deepStrictEqual(M.combine(O.some(1), O.some(2)), O.some(3)) * * @since 1.0.0 */ export const getOptionalMonoid = ( Semigroup: Semigroup ): Monoid> => monoid.fromSemigroup( semigroup.make((self, that) => isNone(self) ? that : isNone(that) ? self : some(Semigroup.combine(self.value, that.value)) ), none() ) /** * Zips two `Option` values together using a provided function, returning a new `Option` of the result. * * @param self - The left-hand side of the zip operation * @param that - The right-hand side of the zip operation * @param f - The function used to combine the values of the two `Option`s * * @category combining * @since 1.0.0 */ export const zipWith: { (self: Option, that: Option, f: (a: A, b: B) => C): Option (that: Option, f: (a: A, b: B) => C): (self: Option) => Option } = semiApplicative.zipWith(SemiApplicative) /** * @category combining * @since 1.0.0 */ export const ap: { (self: Option<(a: A) => B>, that: Option): Option (that: Option): (self: Option<(a: A) => B>) => Option } = semiApplicative.ap(SemiApplicative) /** * Semigroup that models the combination of computations that can fail, if at least one element is `None` * then the resulting combination is `None`, otherwise if all elements are `Some` then the resulting combination * is the combination of the wrapped elements using the provided `Semigroup`. * * See also `getFailureMonoid` if you need a `Monoid` instead of a `Semigroup`. * * @category combining * @since 1.0.0 */ export const getFailureSemigroup: (S: Semigroup) => Semigroup> = semiApplicative .getSemigroup(SemiApplicative) /** * @since 1.0.0 */ export const Applicative: applicative.Applicative = { imap, of, map, product, productMany, productAll: all } /** * Monoid that models the combination of computations that can fail, if at least one element is `None` * then the resulting combination is `None`, otherwise if all elements are `Some` then the resulting combination * is the combination of the wrapped elements using the provided `Monoid`. * * The `empty` value is `some(M.empty)`. * * See also `getFailureSemigroup` if you need a `Semigroup` instead of a `Monoid`. * * @category combining * @since 1.0.0 */ export const getFailureMonoid: (M: Monoid) => Monoid> = applicative.getMonoid( Applicative ) const coproduct = (self: Option, that: Option): Option => isSome(self) ? self : that const coproductMany = (self: Option, collection: Iterable>): Option => isSome(self) ? self : firstSomeOf(collection) /** * @since 1.0.0 */ export const SemiCoproduct: semiCoproduct.SemiCoproduct = { imap, coproduct, coproductMany } /** * Semigroup returning the first `Some` value encountered. * * @category combining * @since 1.0.0 */ export const getFirstSomeSemigroup: () => Semigroup> = semiCoproduct.getSemigroup( SemiCoproduct ) /** * @since 1.0.0 */ export const Coproduct: coproduct_.Coproduct = { imap, coproduct, coproductMany, zero: none, coproductAll: firstSomeOf } /** * @since 1.0.0 */ export const SemiAlternative: semiAlternative.SemiAlternative = { map, imap, coproduct, coproductMany } /** * @since 1.0.0 */ export const Alternative: alternative.Alternative = { map, imap, coproduct, coproductMany, coproductAll: firstSomeOf, zero: none } /** * Reduces an `Iterable` of `Option` to a single value of type `B`, elements that are `None` are ignored. * * @param self - The Iterable of `Option` to be reduced. * @param b - The initial value of the accumulator. * @param f - The reducing function that takes the current accumulator value and the unwrapped value of an `Option`. * * @example * import { some, none, reduceCompact } from '@fp-ts/core/Option' * import { pipe } from "@fp-ts/core/Function" * * const iterable = [some(1), none(), some(2), none()] * assert.deepStrictEqual(pipe(iterable, reduceCompact(0, (b, a) => b + a)), 3) * * @category folding * @since 1.0.0 */ export const reduceCompact: { (b: B, f: (b: B, a: A) => B): (self: Iterable>) => B (self: Iterable>, b: B, f: (b: B, a: A) => B): B } = dual( 3, (self: Iterable>, b: B, f: (b: B, a: A) => B): B => { let out: B = b for (const oa of self) { if (isSome(oa)) { out = f(out, oa.value) } } return out } ) /** * @since 1.0.0 */ export const Foldable: foldable.Foldable = { reduce: dual( 3, (self: Option, b: B, f: (b: B, a: A) => B): B => isNone(self) ? b : f(b, self.value) ) } /** * Transforms an `Option` into an `Array`. * If the input is `None`, an empty array is returned. * If the input is `Some`, the value is wrapped in an array. * * @param self - The `Option` to convert to an array. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.toArray(O.some(1)), [1]) * assert.deepStrictEqual(O.toArray(O.none()), []) * * @category conversions * @since 1.0.0 */ export const toArray: (self: Option) => Array = foldable.toArray(Foldable) /** * @category filtering * @since 1.0.0 */ export const partitionMap: { (f: (a: A) => Either): (self: Option) => [Option, Option] (self: Option, f: (a: A) => Either): [Option, Option] } = dual(2, ( self: Option, f: (a: A) => Either ): [Option, Option] => { if (isNone(self)) { return [none(), none()] } const e = f(self.value) return either.isLeft(e) ? [some(e.left), none()] : [none(), some(e.right)] }) /** * Maps over the value of an `Option` and filters out `None`s. * * Useful when in addition to filtering you also want to change the type of the `Option`. * * @param self - The `Option` to map over. * @param f - A function to apply to the value of the `Option`. * * @category filtering * @since 1.0.0 */ export const filterMap: { (f: (a: A) => Option): (self: Option) => Option (self: Option, f: (a: A) => Option): Option } = dual( 2, (self: Option, f: (a: A) => Option): Option => isNone(self) ? none() : f(self.value) ) /** * @since 1.0.0 */ export const Filterable: filterable.Filterable = { partitionMap, filterMap } /** * Filters an `Option` using a predicate. If the predicate is not satisfied or the `Option` is `None` returns `None`. * * If you need to change the type of the `Option` in addition to filtering, see `filterMap`. * * @param predicate - A predicate function to apply to the `Option` value. * @param fb - The `Option` to filter. * * @category filtering * @since 1.0.0 */ export const filter: { (self: Option, refinement: (a: A) => a is B): Option (self: Option, predicate: (a: A) => boolean): Option (refinement: (a: A) => a is B): (self: Option) => Option (predicate: (a: A) => boolean): (self: Option) => Option } = filterable.filter(Filterable) /** * Applies an `Option` value to an effectful function that returns an `F` value. * * @param F - {@link applicative.Applicative} instance * @param self - The `Option` value. * @param f - An effectful function that returns an `F` value. * * @example * import * as O from "@fp-ts/core/Option" * import * as E from "@fp-ts/core/Either" * * const traverse = O.traverse(E.Applicative) * const f = (n: number) => n >= 0 ? E.right(1) : E.left("negative") * * assert.deepStrictEqual(traverse(O.some(1), f), E.right(O.some(1))) * assert.deepStrictEqual(traverse(O.some(-1), f), E.left("negative")) * assert.deepStrictEqual(traverse(O.none(), f), E.right(O.none())) * * @category combining * @since 1.0.0 */ export const traverse = ( F: applicative.Applicative ): { ( f: (a: A) => Kind ): (self: Option) => Kind> (self: Option, f: (a: A) => Kind): Kind> } => dual( 2, ( self: Option, f: (a: A) => Kind ): Kind> => isNone(self) ? F.of(none()) : F.map(f(self.value), some) ) /** * @since 1.0.0 */ export const Traversable: traversable.Traversable = { traverse } /** * Combines an `Option` of an `F`-structure to an `F`-structure of an `Option` with the same inner type. * * @param F - {@link applicative.Applicative} instance * @param self - `Option` of Kind `F` * * @example * import * as O from "@fp-ts/core/Option" * import * as E from "@fp-ts/core/Either" * * const sequence = O.sequence(E.Applicative) * * assert.deepStrictEqual(sequence(O.some(E.right(1))), E.right(O.some(1))) * assert.deepStrictEqual(sequence(O.some(E.left("error"))), E.left("error")) * assert.deepStrictEqual(sequence(O.none()), E.right(O.none())) * * @category combining * @since 1.0.0 */ export const sequence: ( F: applicative.Applicative ) => (self: Option>) => Kind> = traversable .sequence(Traversable) /** * @category combining * @since 1.0.0 */ export const traverseTap: ( F: applicative.Applicative ) => { ( self: Option, f: (a: A) => Kind ): Kind> ( f: (a: A) => Kind ): (self: Option) => Kind> } = traversable.traverseTap(Traversable) /** * @example * import { none, some, getEquivalence } from '@fp-ts/core/Option' * import * as N from '@fp-ts/core/Number' * * const isEquivalent = getEquivalence(N.Equivalence) * assert.deepStrictEqual(isEquivalent(none(), none()), true) * assert.deepStrictEqual(isEquivalent(none(), some(1)), false) * assert.deepStrictEqual(isEquivalent(some(1), none()), false) * assert.deepStrictEqual(isEquivalent(some(1), some(2)), false) * assert.deepStrictEqual(isEquivalent(some(1), some(1)), true) * * @category equivalence * @since 1.0.0 */ export const getEquivalence = (E: Equivalence): Equivalence> => equivalence.make((x, y) => x === y || (isNone(x) ? isNone(y) : isNone(y) ? false : E(x.value, y.value)) ) /** * The `Order` instance allows `Option` values to be compared with * `compare`, whenever there is an `Order` instance for * the type the `Option` contains. * * `None` is considered to be less than any `Some` value. * * @example * import { none, some, getOrder } from '@fp-ts/core/Option' * import * as N from '@fp-ts/core/Number' * import { pipe } from "@fp-ts/core/Function" * * const O = getOrder(N.Order) * assert.deepStrictEqual(O.compare(none(), none()), 0) * assert.deepStrictEqual(O.compare(none(), some(1)), -1) * assert.deepStrictEqual(O.compare(some(1), none()), 1) * assert.deepStrictEqual(O.compare(some(1), some(2)), -1) * assert.deepStrictEqual(O.compare(some(1), some(1)), 0) * * @category sorting * @since 1.0.0 */ export const getOrder = (O: Order): Order> => order.make((self, that) => isSome(self) ? (isSome(that) ? O.compare(self.value, that.value) : 1) : -1 ) /** * Lifts a binary function into `Option`. * * @param f - The function to lift. * * @category lifting * @since 1.0.0 */ export const lift2: (f: (a: A, b: B) => C) => { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } = semiApplicative.lift2(SemiApplicative) /** * Transforms a `Predicate` function into a `Some` of the input value if the predicate returns `true` or `None` * if the predicate returns `false`. * * @param predicate - A `Predicate` function that takes in a value of type `A` and returns a boolean. * * @example * import * as O from "@fp-ts/core/Option" * * const getOption = O.liftPredicate((n: number) => n >= 0) * * assert.deepStrictEqual(getOption(-1), O.none()) * assert.deepStrictEqual(getOption(1), O.some(1)) * * @category lifting * @since 1.0.0 */ export const liftPredicate: { (refinement: Refinement): (c: C) => Option (predicate: Predicate): (b: B) => Option } = (predicate: Predicate) => (b: B) => predicate(b) ? some(b) : none() /** * Lifts an `Either` function to an `Option` function. * * @param f - Any variadic function that returns an `Either`. * * @example * import * as O from "@fp-ts/core/Option" * import * as E from "@fp-ts/core/Either" * * const parse = (s: string) => * isNaN(+s) ? E.left(`Error: ${s} is not a number`) : E.right(+s) * * const parseNumber = O.liftEither(parse) * * assert.deepEqual(parseNumber('12'), O.some(12)) * assert.deepEqual(parseNumber('not a number'), O.none()) * * @category lifting * @since 1.0.0 */ export const liftEither = , E, B>( f: (...a: A) => Either ) => (...a: A): Option => fromEither(f(...a)) /** * Returns a function that checks if an `Option` contains a given value using a provided `Equivalence` instance. * * @param equivalent - An `Equivalence` instance to compare values of the `Option`. * @param self - The `Option` to apply the comparison to. * @param a - The value to compare against the `Option`. * * @example * import { some, none, contains } from '@fp-ts/core/Option' * import { Equivalence } from '@fp-ts/core/Number' * import { pipe } from "@fp-ts/core/Function" * * assert.deepStrictEqual(pipe(some(2), contains(Equivalence)(2)), true) * assert.deepStrictEqual(pipe(some(1), contains(Equivalence)(2)), false) * assert.deepStrictEqual(pipe(none(), contains(Equivalence)(2)), false) * * @since 1.0.0 */ export const contains = (isEquivalent: (self: A, that: A) => boolean): { (a: A): (self: Option) => boolean (self: Option, a: A): boolean } => dual(2, (self: Option, a: A): boolean => isNone(self) ? false : isEquivalent(self.value, a)) /** * Check if a value in an `Option` type meets a certain predicate. * * @param self - The `Option` to check. * @param predicate - The condition to check. * * @example * import { some, none, exists } from '@fp-ts/core/Option' * import { pipe } from "@fp-ts/core/Function" * * const isEven = (n: number) => n % 2 === 0 * * assert.deepStrictEqual(pipe(some(2), exists(isEven)), true) * assert.deepStrictEqual(pipe(some(1), exists(isEven)), false) * assert.deepStrictEqual(pipe(none(), exists(isEven)), false) * * @since 1.0.0 */ export const exists: { (predicate: Predicate): (self: Option) => boolean (self: Option, predicate: Predicate): boolean } = dual( 2, (self: Option, predicate: Predicate): boolean => isNone(self) ? false : predicate(self.value) ) // ------------------------------------------------------------------------------------- // math // ------------------------------------------------------------------------------------- /** * @category math * @since 1.0.0 */ export const sum: { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } = lift2(N.sum) /** * @category math * @since 1.0.0 */ export const multiply: { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } = lift2(N.multiply) /** * @category math * @since 1.0.0 */ export const subtract: { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } = lift2(N.subtract) /** * @category math * @since 1.0.0 */ export const divide: { (self: Option, that: Option): Option (that: Option): (self: Option) => Option } = lift2(N.divide) /** * Sum all numbers in an iterable of `Option` ignoring the `None` values. * * @param self - The iterable of `Option` to be summed. * * @example * import { sumCompact, some, none } from '@fp-ts/core/Option' * * const iterable = [some(2), none(), some(3), none()] * assert.deepStrictEqual(sumCompact(iterable), 5) * * @category math * @since 1.0.0 */ export const sumCompact = (self: Iterable>): number => { let out = 0 for (const oa of self) { if (isSome(oa)) { out += oa.value } } return out } /** * Multiply all numbers in an iterable of `Option` ignoring the `None` values. * * @param self - The iterable of `Option` to be multiplied. * * @example * import { multiplyCompact, some, none } from '@fp-ts/core/Option' * * const iterable = [some(2), none(), some(3), none()] * assert.deepStrictEqual(multiplyCompact(iterable), 6) * * @category math * @since 1.0.0 */ export const multiplyCompact = (self: Iterable>): number => { let out = 1 for (const oa of self) { if (isSome(oa)) { const a: number = oa.value if (a === 0) { return 0 } out *= a } } return out } // ------------------------------------------------------------------------------------- // do notation // ------------------------------------------------------------------------------------- /** * @category do notation * @since 1.0.0 */ export const tupled: (self: Option) => Option<[A]> = invariant.tupled(Invariant) /** * Appends an element to the end of a tuple wrapped in an `Option` type. * * @param self - The option of a tuple to which an element needs to be added. * @param that - The element which needs to be added to the tuple. * * @example * import * as O from "@fp-ts/core/Option" * * assert.deepStrictEqual(O.appendElement(O.some([1, 2]), O.some(3)), O.some([1, 2, 3])) * assert.deepStrictEqual(O.appendElement(O.some([1, 2]), O.none()), O.none()) * * @category do notation * @since 1.0.0 */ export const appendElement: { , B>(self: Option, that: Option): Option<[...A, B]> (that: Option): >(self: Option) => Option<[...A, B]> } = semiProduct.appendElement(SemiProduct) /** * @category do notation * @since 1.0.0 */ export const bindTo: { (name: N): (self: Option) => Option<{ [K in N]: A }> (self: Option, name: N): Option<{ [K in N]: A }> } = invariant.bindTo(Invariant) const let_: { ( name: Exclude, f: (a: A) => B ): (self: Option) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: Option, name: Exclude, f: (a: A) => B ): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = covariant.let(Covariant) export { /** * @category do notation * @since 1.0.0 */ let_ as let } /** * @category do notation * @since 1.0.0 */ export const bind: { ( name: Exclude, f: (a: A) => Option ): (self: Option) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: Option, name: Exclude, f: (a: A) => Option ): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = chainable.bind(Chainable) /** * @category do notation * @since 1.0.0 */ export const Do: Option<{}> = of_.Do(Of) /** * A variant of `bind` that sequentially ignores the scope. * * @category do notation * @since 1.0.0 */ export const andThenBind: { ( name: Exclude, that: Option ): (self: Option) => Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: Option, name: Exclude, that: Option ): Option<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = semiProduct.andThenBind(SemiProduct) ================================================ FILE: src/Ordering.ts ================================================ /** * @since 1.0.0 */ import type { LazyArg } from "@fp-ts/core/Function" import { dual } from "@fp-ts/core/Function" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * @category model * @since 1.0.0 */ export type Ordering = -1 | 0 | 1 /** * Inverts the ordering of the input `Ordering`. * * @param o - The input `Ordering`. * * @example * import { reverse } from "@fp-ts/core/Ordering" * * assert.deepStrictEqual(reverse(1), -1) * assert.deepStrictEqual(reverse(-1), 1) * assert.deepStrictEqual(reverse(0), 0) * * @since 1.0.0 */ export const reverse = (o: Ordering): Ordering => (o === -1 ? 1 : o === 1 ? -1 : 0) /** * Depending on the `Ordering` parameter given to it, returns a value produced by one of the 3 functions provided as parameters. * * @param self - The `Ordering` parameter to match against. * @param onLessThan - A function that will be called if the `Ordering` parameter is `-1`. * @param onEqual - A function that will be called if the `Ordering` parameter is `0`. * @param onGreaterThan - A function that will be called if the `Ordering` parameter is `1`. * * @example * import { match } from "@fp-ts/core/Ordering" * import { constant } from "@fp-ts/core/Function" * * const toMessage = match( * constant('less than'), * constant('equal'), * constant('greater than') * ) * * assert.deepStrictEqual(toMessage(-1), "less than") * assert.deepStrictEqual(toMessage(0), "equal") * assert.deepStrictEqual(toMessage(1), "greater than") * * @category pattern matching * @since 1.0.0 */ export const match: { ( onLessThan: LazyArg, onEqual: LazyArg, onGreaterThan: LazyArg ): (self: Ordering) => A | B | C ( o: Ordering, onLessThan: LazyArg, onEqual: LazyArg, onGreaterThan: LazyArg ): A | B | C } = dual(4, ( self: Ordering, onLessThan: LazyArg, onEqual: LazyArg, onGreaterThan: LazyArg ): A | B | C => self === -1 ? onLessThan() : self === 0 ? onEqual() : onGreaterThan()) /** * `Semigroup` instance for `Ordering`, returns the left-most non-zero `Ordering`. * * @example * import { Semigroup } from "@fp-ts/core/Ordering" * * assert.deepStrictEqual(Semigroup.combine(0, -1), -1) * assert.deepStrictEqual(Semigroup.combine(0, 1), 1) * assert.deepStrictEqual(Semigroup.combine(1, -1), 1) * * @category instances * @since 1.0.0 */ export const Semigroup: semigroup.Semigroup = semigroup.make( (self, that) => self !== 0 ? self : that, (self, collection) => { let ordering = self if (ordering !== 0) { return ordering } for (ordering of collection) { if (ordering !== 0) { return ordering } } return ordering } ) /** * `Monoid` instance for `Ordering`, returns the left-most non-zero `Ordering`. * * The `empty` value is `0`. * * @example * import { Monoid } from "@fp-ts/core/Ordering" * * assert.deepStrictEqual(Monoid.combine(Monoid.empty, -1), -1) * assert.deepStrictEqual(Monoid.combine(Monoid.empty, 1), 1) * assert.deepStrictEqual(Monoid.combine(1, -1), 1) * * @category instances * @since 1.0.0 */ export const Monoid: monoid.Monoid = monoid.fromSemigroup(Semigroup, 0) ================================================ FILE: src/Predicate.ts ================================================ /** * @since 1.0.0 */ import { constFalse, constTrue, dual, isFunction as isFunction_ } from "@fp-ts/core/Function" import type { TypeLambda } from "@fp-ts/core/HKT" import * as readonlyArray from "@fp-ts/core/internal/ReadonlyArray" import * as contravariant from "@fp-ts/core/typeclass/Contravariant" import * as invariant from "@fp-ts/core/typeclass/Invariant" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as of_ from "@fp-ts/core/typeclass/Of" import * as product_ from "@fp-ts/core/typeclass/Product" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" /** * @category models * @since 1.0.0 */ export interface Predicate { (a: A): boolean } /** * @category type lambdas * @since 1.0.0 */ export interface PredicateTypeLambda extends TypeLambda { readonly type: Predicate } /** * @category models * @since 1.0.0 */ export interface Refinement { (a: A): a is B } /** * Given a `Predicate` returns a `Predicate` * * @param self - the `Predicate` to be transformed to `Predicate`. * @param f - a function to transform `B` to `A`. * * @example * import * as P from "@fp-ts/core/Predicate" * import * as N from "@fp-ts/core/Number" * * const minLength3 = P.contramap(N.greaterThan(2), (s: string) => s.length) * * assert.deepStrictEqual(minLength3("a"), false) * assert.deepStrictEqual(minLength3("aa"), false) * assert.deepStrictEqual(minLength3("aaa"), true) * assert.deepStrictEqual(minLength3("aaaa"), true) * * @category constructors * @since 1.0.0 */ export const contramap: { (f: (b: B) => A): (self: Predicate) => Predicate (self: Predicate, f: (b: B) => A): Predicate } = dual(2, (self: Predicate, f: (b: B) => A): Predicate => (b) => self(f(b))) /** * Tests if a value is a `string`. * * @param input - The value to test. * * @example * import { isString } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isString("a"), true) * * assert.deepStrictEqual(isString(1), false) * * @category guards * @since 1.0.0 */ export const isString = (input: unknown): input is string => typeof input === "string" /** * Tests if a value is a `number`. * * @param input - The value to test. * * @example * import { isNumber } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isNumber(2), true) * * assert.deepStrictEqual(isNumber("2"), false) * * @category guards * @since 1.0.0 */ export const isNumber = (input: unknown): input is number => typeof input === "number" /** * Tests if a value is a `boolean`. * * @param input - The value to test. * * @example * import { isBoolean } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isBoolean(true), true) * * assert.deepStrictEqual(isBoolean("true"), false) * * @category guards * @since 1.0.0 */ export const isBoolean = (input: unknown): input is boolean => typeof input === "boolean" /** * Tests if a value is a `bigint`. * * @param input - The value to test. * * @example * import { isBigint } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isBigint(1n), true) * * assert.deepStrictEqual(isBigint(1), false) * * @category guards * @since 1.0.0 */ export const isBigint = (input: unknown): input is bigint => typeof input === "bigint" /** * Tests if a value is a `symbol`. * * @param input - The value to test. * * @example * import { isSymbol } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isSymbol(Symbol.for("a")), true) * * assert.deepStrictEqual(isSymbol("a"), false) * * @category guards * @since 1.0.0 */ export const isSymbol = (input: unknown): input is symbol => typeof input === "symbol" /** * Tests if a value is a `function`. * * @param input - The value to test. * * @example * import { isFunction } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isFunction(isFunction), true) * * assert.deepStrictEqual(isFunction("function"), false) * * @category guards * @since 1.0.0 */ export const isFunction: (input: unknown) => input is Function = isFunction_ /** * Tests if a value is `undefined`. * * @param input - The value to test. * * @example * import { isUndefined } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isUndefined(undefined), true) * * assert.deepStrictEqual(isUndefined(null), false) * assert.deepStrictEqual(isUndefined("undefined"), false) * * @category guards * @since 1.0.0 */ export const isUndefined = (input: unknown): input is undefined => input === undefined /** * Tests if a value is not `undefined`. * * @param input - The value to test. * * @example * import { isNotUndefined } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isNotUndefined(null), true) * assert.deepStrictEqual(isNotUndefined("undefined"), true) * * assert.deepStrictEqual(isNotUndefined(undefined), false) * * @category guards * @since 1.0.0 */ export const isNotUndefined = (input: A): input is Exclude => input !== undefined /** * Tests if a value is `undefined`. * * @param input - The value to test. * * @example * import { isNull } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isNull(null), true) * * assert.deepStrictEqual(isNull(undefined), false) * assert.deepStrictEqual(isNull("null"), false) * * @category guards * @since 1.0.0 */ export const isNull = (input: unknown): input is null => input === null /** * Tests if a value is not `undefined`. * * @param input - The value to test. * * @example * import { isNotNull } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isNotNull(undefined), true) * assert.deepStrictEqual(isNotNull("null"), true) * * assert.deepStrictEqual(isNotNull(null), false) * * @category guards * @since 1.0.0 */ export const isNotNull = (input: A): input is Exclude => input !== null /** * A guard that always fails. * * @param _ - The value to test. * * @example * import { isNever } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isNever(null), false) * assert.deepStrictEqual(isNever(undefined), false) * assert.deepStrictEqual(isNever({}), false) * assert.deepStrictEqual(isNever([]), false) * * @category guards * @since 1.0.0 */ export const isNever: (input: unknown) => input is never = (_: unknown): _ is never => false /** * A guard that always succeeds. * * @param _ - The value to test. * * @example * import { isUnknown } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isUnknown(null), true) * assert.deepStrictEqual(isUnknown(undefined), true) * * assert.deepStrictEqual(isUnknown({}), true) * assert.deepStrictEqual(isUnknown([]), true) * * @category guards * @since 1.0.0 */ export const isUnknown: (input: unknown) => input is unknown = (_): _ is unknown => true /** * Tests if a value is an `object`. * * @param input - The value to test. * * @example * import { isObject } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isObject({}), true) * assert.deepStrictEqual(isObject([]), true) * * assert.deepStrictEqual(isObject(null), false) * assert.deepStrictEqual(isObject(undefined), false) * * @category guards * @since 1.0.0 */ export const isObject = (input: unknown): input is object => typeof input === "object" && input != null /** * A guard that succeeds when the input is `null` or `undefined`. * * @param input - The value to test. * * @example * import { isNullable } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isNullable(null), true) * assert.deepStrictEqual(isNullable(undefined), true) * * assert.deepStrictEqual(isNullable({}), false) * assert.deepStrictEqual(isNullable([]), false) * * @category guards * @since 1.0.0 */ export const isNullable = (input: A): input is Extract => input === null || input === undefined /** * A guard that succeeds when the input is not `null` or `undefined`. * * @param input - The value to test. * * @example * import { isNotNullable } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isNotNullable({}), true) * assert.deepStrictEqual(isNotNullable([]), true) * * assert.deepStrictEqual(isNotNullable(null), false) * assert.deepStrictEqual(isNotNullable(undefined), false) * * @category guards * @since 1.0.0 */ export const isNotNullable = (input: A): input is NonNullable => input !== null && input !== undefined /** * A guard that succeeds when the input is an `Error`. * * @param input - The value to test. * * @example * import { isError } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isError(new Error()), true) * * assert.deepStrictEqual(isError(null), false) * assert.deepStrictEqual(isError({}), false) * * @category guards * @since 1.0.0 */ export const isError = (input: unknown): input is Error => input instanceof Error /** * A guard that succeeds when the input is a `Date`. * * @param input - The value to test. * * @example * import { isDate } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isDate(new Date()), true) * * assert.deepStrictEqual(isDate(null), false) * assert.deepStrictEqual(isDate({}), false) * * @category guards * @since 1.0.0 */ export const isDate = (input: unknown): input is Date => input instanceof Date /** * A guard that succeeds when the input is a record. * * @param input - The value to test. * * @example * import { isRecord } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isRecord({}), true) * assert.deepStrictEqual(isRecord({ a: 1 }), true) * * assert.deepStrictEqual(isRecord([]), false) * assert.deepStrictEqual(isRecord([1, 2, 3]), false) * assert.deepStrictEqual(isRecord(null), false) * assert.deepStrictEqual(isRecord(undefined), false) * * @category guards * @since 1.0.0 */ export const isRecord = (input: unknown): input is { [x: string | symbol]: unknown } => isObject(input) && !Array.isArray(input) /** * A guard that succeeds when the input is a readonly record. * * @param input - The value to test. * * @example * import { isReadonlyRecord } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isReadonlyRecord({}), true) * assert.deepStrictEqual(isReadonlyRecord({ a: 1 }), true) * * assert.deepStrictEqual(isReadonlyRecord([]), false) * assert.deepStrictEqual(isReadonlyRecord([1, 2, 3]), false) * assert.deepStrictEqual(isReadonlyRecord(null), false) * assert.deepStrictEqual(isReadonlyRecord(undefined), false) * * @category guards * @since 1.0.0 */ export const isReadonlyRecord: ( input: unknown ) => input is { readonly [x: string | symbol]: unknown } = isRecord /** * @since 1.0.0 */ export const compose: { (bc: Refinement): (ab: Refinement) => Refinement (ab: Refinement, bc: Refinement): Refinement } = dual( 2, (ab: Refinement, bc: Refinement): Refinement => (a): a is C => ab(a) && bc(a) ) const imap = contravariant.imap(contramap) /** * @category instances * @since 1.0.0 */ export const Contravariant: contravariant.Contravariant = { imap, contramap } /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } /** * @since 1.0.0 */ export const tupled: (self: Predicate) => Predicate = invariant.tupled( Invariant ) as any /** * @since 1.0.0 */ export const of = (_: A): Predicate => isUnknown /** * @category instances * @since 1.0.0 */ export const Of: of_.Of = { of } /** * @since 1.0.0 */ export const unit: Predicate = of_.unit(Of) const product = (self: Predicate, that: Predicate): Predicate => ([a, b]) => self(a) && that(b) const productAll = ( collection: Iterable> ): Predicate> => { const predicates = readonlyArray.fromIterable(collection) return (as) => { const len = Math.min(as.length, predicates.length) for (let i = 0; i < len; i++) { if (predicates[i](as[i]) === false) { return false } } return true } } const productMany = ( self: Predicate, collection: Iterable> ): Predicate]> => { const rest = productAll(collection) return ([head, ...tail]) => self(head) === false ? false : rest(tail) } /** * @category instances * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } /** * @category instances * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll } /** * This function appends a predicate to a tuple-like predicate, allowing you to create a new predicate that includes * the original elements and the new one. * * @param self - The tuple-like predicate to append to. * @param that - The predicate to append. * * @since 1.0.0 */ export const appendElement: { , B>( self: Predicate, that: Predicate ): Predicate ( that: Predicate ): >(self: Predicate) => Predicate } = semiProduct.appendElement(SemiProduct) as any /** * Similar to `Promise.all` but operates on `Predicate`s. * * ``` * [Predicate, Predicate, ...] -> Predicate<[A, B, ...]> * ``` * * @since 1.0.0 */ export const tuple: >>( ...predicates: T ) => Predicate] ? A : never }>> = product_.tuple(Product) /** * @since 1.0.0 */ export const struct: >>( predicates: R ) => Predicate<{ readonly [K in keyof R]: [R[K]] extends [Predicate] ? A : never }> = product_.struct(Product) /** * Negates the result of a given predicate. * * @param self - A predicate. * * @example * import * as P from "@fp-ts/core/Predicate" * import * as N from "@fp-ts/core/Number" * * const isPositive = P.not(N.lessThan(0)) * * assert.deepStrictEqual(isPositive(-1), false) * assert.deepStrictEqual(isPositive(0), true) * assert.deepStrictEqual(isPositive(1), true) * * @category combinators * @since 1.0.0 */ export const not = (self: Predicate): Predicate => (a) => !self(a) /** * Combines two predicates into a new predicate that returns `true` if at least one of the predicates returns `true`. * * @param self - A predicate. * @param that - A predicate. * * @example * import * as P from "@fp-ts/core/Predicate" * import * as N from "@fp-ts/core/Number" * * const nonZero = P.or(N.lessThan(0), N.greaterThan(0)) * * assert.deepStrictEqual(nonZero(-1), true) * assert.deepStrictEqual(nonZero(0), false) * assert.deepStrictEqual(nonZero(1), true) * * @category combinators * @since 1.0.0 */ export const or: { (that: Predicate): (self: Predicate) => Predicate (self: Predicate, that: Predicate): Predicate } = dual(2, (self: Predicate, that: Predicate): Predicate => (a) => self(a) || that(a)) /** * Combines two predicates into a new predicate that returns `true` if both of the predicates returns `true`. * * @param self - A predicate. * @param that - A predicate. * * @example * import * as P from "@fp-ts/core/Predicate" * * const minLength = (n: number) => (s: string) => s.length >= n * const maxLength = (n: number) => (s: string) => s.length <= n * * const length = (n: number) => P.and(minLength(n), maxLength(n)) * * assert.deepStrictEqual(length(2)("aa"), true) * assert.deepStrictEqual(length(2)("a"), false) * assert.deepStrictEqual(length(2)("aaa"), false) * * @category combinators * @since 1.0.0 */ export const and: { (that: Predicate): (self: Predicate) => Predicate (self: Predicate, that: Predicate): Predicate } = dual(2, (self: Predicate, that: Predicate): Predicate => (a) => self(a) && that(a)) /** * @category instances * @since 1.0.0 */ export const getSemigroupAny = (): Semigroup> => semigroup.make>( or, (self, collection) => a => { if (self(a)) { return true } for (const p of collection) { if (p(a)) { return true } } return false } ) /** * @category instances * @since 1.0.0 */ export const getMonoidAny = (): monoid.Monoid> => monoid.fromSemigroup(getSemigroupAny(), constFalse) /** * @category instances * @since 1.0.0 */ export const getSemigroupAll = (): Semigroup> => semigroup.make>( and, (self, collection) => a => { if (!self(a)) { return false } for (const p of collection) { if (!p(a)) { return false } } return true } ) /** * @category instances * @since 1.0.0 */ export const getMonoidAll = (): monoid.Monoid> => monoid.fromSemigroup(getSemigroupAll(), constTrue) /** * @since 1.0.0 */ export const all = (collection: Iterable>): Predicate => getMonoidAll().combineAll(collection) /** * @since 1.0.0 */ export const any = (collection: Iterable>): Predicate => getMonoidAny().combineAll(collection) // ------------------------------------------------------------------------------------- // do notation // ------------------------------------------------------------------------------------- /** * @category do notation * @since 1.0.0 */ export const bindTo: { (name: N): (self: Predicate) => Predicate<{ readonly [K in N]: A }> (self: Predicate, name: N): Predicate<{ readonly [K in N]: A }> } = invariant.bindTo(Invariant) /** * @category do notation * @since 1.0.0 */ export const Do: Predicate<{}> = of_.Do(Of) /** * A variant of `bind` that sequentially ignores the scope. * * @category do notation * @since 1.0.0 */ export const andThenBind: { ( name: Exclude, that: Predicate ): ( self: Predicate ) => Predicate<{ readonly [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: Predicate, name: Exclude, that: Predicate ): Predicate<{ readonly [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = semiProduct.andThenBind(SemiProduct) ================================================ FILE: src/ReadonlyArray.ts ================================================ /** * This module provides utility functions for working with arrays in TypeScript. * * @since 1.0.0 */ import type { Either } from "@fp-ts/core/Either" import * as E from "@fp-ts/core/Either" import { dual, identity } from "@fp-ts/core/Function" import type { LazyArg } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import * as readonlyArray from "@fp-ts/core/internal/ReadonlyArray" import type { Option } from "@fp-ts/core/Option" import * as O from "@fp-ts/core/Option" import type { Predicate, Refinement } from "@fp-ts/core/Predicate" import * as string from "@fp-ts/core/String" import * as applicative from "@fp-ts/core/typeclass/Applicative" import * as chainable from "@fp-ts/core/typeclass/Chainable" import type { Coproduct } from "@fp-ts/core/typeclass/Coproduct" import * as covariant from "@fp-ts/core/typeclass/Covariant" import type * as filterable from "@fp-ts/core/typeclass/Filterable" import * as flatMap_ from "@fp-ts/core/typeclass/FlatMap" import * as foldable from "@fp-ts/core/typeclass/Foldable" import * as invariant from "@fp-ts/core/typeclass/Invariant" import type * as monad from "@fp-ts/core/typeclass/Monad" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as of_ from "@fp-ts/core/typeclass/Of" import * as order from "@fp-ts/core/typeclass/Order" import type { Order } from "@fp-ts/core/typeclass/Order" import type * as pointed from "@fp-ts/core/typeclass/Pointed" import type * as product_ from "@fp-ts/core/typeclass/Product" import * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" import * as traversable from "@fp-ts/core/typeclass/Traversable" import * as traversableFilterable from "@fp-ts/core/typeclass/TraversableFilterable" /** * @category type lambdas * @since 1.0.0 */ export interface ReadonlyArrayTypeLambda extends TypeLambda { readonly type: ReadonlyArray } /** * @category models * @since 1.0.0 */ export type NonEmptyReadonlyArray = readonly [A, ...Array] /** * @category models * @since 1.0.0 */ export type NonEmptyArray = [A, ...Array] /** * Builds a `NonEmptyArray` from an non-empty collection of elements. * * @category constructors * @since 1.0.0 */ export const make = >( ...elements: Elements ): NonEmptyArray => elements /** * Return a `NonEmptyArray` of length `n` with element `i` initialized with `f(i)`. * * **Note**. `n` is normalized to an integer >= 1. * * @example * import { makeBy } from '@fp-ts/core/ReadonlyArray' * * assert.deepStrictEqual(makeBy(5, n => n * 2), [0, 2, 4, 6, 8]) * * @category constructors * @since 1.0.0 */ export const makeBy = (n: number, f: (i: number) => A): NonEmptyArray => { const max = Math.max(1, Math.floor(n)) const out: NonEmptyArray = [f(0)] for (let i = 1; i < max; i++) { out.push(f(i)) } return out } /** * Return a `NonEmptyArray` containing a range of integers, including both endpoints. * * @example * import { range } from '@fp-ts/core/ReadonlyArray' * * assert.deepStrictEqual(range(1, 3), [1, 2, 3]) * * @category constructors * @since 1.0.0 */ export const range = (start: number, end: number): NonEmptyArray => start <= end ? makeBy(end - start + 1, (i) => start + i) : [start] /** * Return a `NonEmptyArray` containing a value repeated the specified number of times. * * **Note**. `n` is normalized to an integer >= 1. * * @example * import { replicate } from '@fp-ts/core/ReadonlyArray' * * assert.deepStrictEqual(replicate("a", 3), ["a", "a", "a"]) * * @category constructors * @since 1.0.0 */ export const replicate: { (n: number): (a: A) => NonEmptyArray (a: A, n: number): NonEmptyArray } = dual(2, (a: A, n: number): NonEmptyArray => makeBy(n, () => a)) /** * @category conversions * @since 1.0.0 */ export const fromIterable: (collection: Iterable) => Array = readonlyArray.fromIterable /** * @category conversions * @since 1.0.0 */ export const fromOption: (self: Option) => Array = O.toArray /** * @category conversions * @since 1.0.0 */ export const fromEither: (self: Either) => Array = E.toArray /** * @category pattern matching * @since 1.0.0 */ export const match: { ( onEmpty: LazyArg, onNonEmpty: (self: NonEmptyReadonlyArray) => C ): (self: ReadonlyArray) => B | C ( self: ReadonlyArray, onEmpty: LazyArg, onNonEmpty: (self: NonEmptyReadonlyArray) => C ): B | C } = dual(3, ( self: ReadonlyArray, onEmpty: LazyArg, onNonEmpty: (self: NonEmptyReadonlyArray) => C ): B | C => isNonEmpty(self) ? onNonEmpty(self) : onEmpty()) /** * @category pattern matching * @since 1.0.0 */ export const matchLeft: { ( onEmpty: LazyArg, onNonEmpty: (head: A, tail: Array) => C ): (self: ReadonlyArray) => B | C ( self: ReadonlyArray, onEmpty: LazyArg, onNonEmpty: (head: A, tail: Array) => C ): B | C } = dual(3, ( self: ReadonlyArray, onEmpty: LazyArg, onNonEmpty: (head: A, tail: Array) => C ): B | C => isNonEmpty(self) ? onNonEmpty(headNonEmpty(self), tailNonEmpty(self)) : onEmpty()) /** * @category pattern matching * @since 1.0.0 */ export const matchRight: { ( onEmpty: LazyArg, onNonEmpty: (init: Array, last: A) => C ): (self: ReadonlyArray) => B | C ( self: ReadonlyArray, onEmpty: LazyArg, onNonEmpty: (init: Array, last: A) => C ): B | C } = dual(3, ( self: ReadonlyArray, onEmpty: LazyArg, onNonEmpty: (init: Array, last: A) => C ): B | C => isNonEmpty(self) ? onNonEmpty(initNonEmpty(self), lastNonEmpty(self)) : onEmpty()) /** * Prepend an element to the front of an `Iterable`, creating a new `NonEmptyArray`. * * @since 1.0.0 */ export const prepend: { (head: B): (self: Iterable) => NonEmptyArray (self: Iterable, head: B): NonEmptyArray } = dual(2, (self: Iterable, head: B): NonEmptyArray => [head, ...self]) /** * @since 1.0.0 */ export const prependAll: { (that: Iterable): (self: Iterable) => Array (self: Iterable, that: Iterable): Array } = dual( 2, (self: Iterable, that: Iterable): Array => fromIterable(that).concat(fromIterable(self)) ) /** * @since 1.0.0 */ export const prependAllNonEmpty: { (that: NonEmptyReadonlyArray): (self: Iterable) => NonEmptyArray (that: Iterable): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: Iterable, that: NonEmptyReadonlyArray): NonEmptyArray (self: NonEmptyReadonlyArray, that: Iterable): NonEmptyArray } = dual( 2, (self: Iterable, that: Iterable): Array => prependAll(self, that) ) /** * Append an element to the end of an `Iterable`, creating a new `NonEmptyArray`. * * @since 1.0.0 */ export const append: { (last: B): (self: Iterable) => NonEmptyArray (self: Iterable, last: B): NonEmptyArray } = dual(2, (self: Iterable, last: B): Array => [...self, last]) /** * @since 1.0.0 */ export const appendAll: { (that: Iterable): (self: Iterable) => Array (self: Iterable, that: Iterable): Array } = dual( 2, (self: Iterable, that: Iterable): Array => fromIterable(self).concat(fromIterable(that)) ) /** * @since 1.0.0 */ export const appendAllNonEmpty: { (that: NonEmptyReadonlyArray): (self: Iterable) => NonEmptyArray (that: Iterable): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: Iterable, that: NonEmptyReadonlyArray): NonEmptyArray (self: NonEmptyReadonlyArray, that: Iterable): NonEmptyArray } = dual( 2, (self: Iterable, that: Iterable): Array => appendAll(self, that) ) /** * Reduce an `Iterable` from the left, keeping all intermediate results instead of only the final result. * * @category folding * @since 1.0.0 */ export const scan: { (b: B, f: (b: B, a: A) => B): (self: Iterable) => NonEmptyArray (self: Iterable, b: B, f: (b: B, a: A) => B): NonEmptyArray } = dual(3, (self: Iterable, b: B, f: (b: B, a: A) => B): NonEmptyArray => { const out: NonEmptyArray = [b] let i = 0 for (const a of self) { out[i + 1] = f(out[i], a) i++ } return out }) /** * Reduce an `Iterable` from the right, keeping all intermediate results instead of only the final result. * * @category folding * @since 1.0.0 */ export const scanRight: { (b: B, f: (b: B, a: A) => B): (self: Iterable) => NonEmptyArray (self: Iterable, b: B, f: (b: B, a: A) => B): NonEmptyArray } = dual(3, (self: Iterable, b: B, f: (b: B, a: A) => B): NonEmptyArray => { const input = fromIterable(self) const out: NonEmptyArray = new Array(input.length + 1) as any out[input.length] = b for (let i = input.length - 1; i >= 0; i--) { out[i] = f(out[i + 1], input[i]) } return out }) /** * Determine if an `Array` is empty narrowing down the type to `[]`. * * @param self - The `Array` to check. * * @example * import { isEmptyArray } from "@fp-ts/core/ReadonlyArray" * * assert.deepStrictEqual(isEmptyArray([]), true); * assert.deepStrictEqual(isEmptyArray([1, 2, 3]), false); * * @category guards * @since 1.0.0 */ export const isEmptyArray = (self: Array): self is [] => self.length === 0 /** * Determine if a `ReadonlyArray` is empty narrowing down the type to `readonly []`. * * @param self - The `ReadonlyArray` to check. * * @example * import { isEmpty } from "@fp-ts/core/ReadonlyArray" * * assert.deepStrictEqual(isEmpty([]), true); * assert.deepStrictEqual(isEmpty([1, 2, 3]), false); * * @category guards * @since 1.0.0 */ // TODO: rename to isEmptyReadonlyArray export const isEmpty: (self: ReadonlyArray) => self is readonly [] = isEmptyArray as any /** * Determine if an `Array` is non empty narrowing down the type to `NonEmptyArray`. * * An `Array` is considered to be a `NonEmptyArray` if it contains at least one element. * * @param self - The `Array` to check. * * @example * import { isNonEmptyArray } from "@fp-ts/core/ReadonlyArray" * * assert.deepStrictEqual(isNonEmptyArray([]), false); * assert.deepStrictEqual(isNonEmptyArray([1, 2, 3]), true); * * @category guards * @since 1.0.0 */ export const isNonEmptyArray: (self: Array) => self is NonEmptyArray = readonlyArray.isNonEmptyArray /** * Determine if a `ReadonlyArray` is non empty narrowing down the type to `NonEmptyReadonlyArray`. * * A `ReadonlyArray` is considered to be a `NonEmptyReadonlyArray` if it contains at least one element. * * @param self - The `ReadonlyArray` to check. * * @example * import { isNonEmpty } from "@fp-ts/core/ReadonlyArray" * * assert.deepStrictEqual(isNonEmpty([]), false); * assert.deepStrictEqual(isNonEmpty([1, 2, 3]), true); * * @category guards * @since 1.0.0 */ // TODO: rename to isNonEmptyReadonlyArray export const isNonEmpty: (self: ReadonlyArray) => self is NonEmptyReadonlyArray = readonlyArray.isNonEmptyArray /** * Return the number of elements in a `ReadonlyArray`. * * @category getters * @since 1.0.0 */ export const length = (self: ReadonlyArray): number => self.length const isOutOfBound = (i: number, as: ReadonlyArray): boolean => i < 0 || i >= as.length const clamp = (i: number, as: ReadonlyArray): number => Math.floor(Math.min(Math.max(0, i), as.length)) /** * This function provides a safe way to read a value at a particular index from a `ReadonlyArray`. * * @category getters * @since 1.0.0 */ export const get: { (index: number): (self: ReadonlyArray) => Option (self: ReadonlyArray, index: number): Option } = dual(2, (self: ReadonlyArray, index: number): Option => { const i = Math.floor(index) return isOutOfBound(i, self) ? O.none() : O.some(self[i]) }) /** * Gets an element unsafely, will throw on out of bounds. * * @since 1.0.0 * @category unsafe */ export const unsafeGet: { (index: number): (self: ReadonlyArray) => A (self: ReadonlyArray, index: number): A } = dual(2, (self: ReadonlyArray, index: number): A => { const i = Math.floor(index) if (isOutOfBound(i, self)) { throw new Error(`Index ${i} out of bounds`) } return self[i] }) /** * Return a tuple containing the first element, and a new `Array` of the remaining elements, if any. * * @category getters * @since 1.0.0 */ export const unprepend = ( self: NonEmptyReadonlyArray ): [A, Array] => [headNonEmpty(self), tailNonEmpty(self)] /** * Return a tuple containing a copy of the `NonEmptyReadonlyArray` without its last element, and that last element. * * @category getters * @since 1.0.0 */ export const unappend = ( self: NonEmptyReadonlyArray ): [Array, A] => [initNonEmpty(self), lastNonEmpty(self)] /** * Get the first element of a `ReadonlyArray`, or `None` if the `ReadonlyArray` is empty. * * @category getters * @since 1.0.0 */ export const head: (self: ReadonlyArray) => Option = get(0) /** * @category getters * @since 1.0.0 */ export const headNonEmpty: (self: NonEmptyReadonlyArray) => A = unsafeGet(0) /** * Get the last element in a `ReadonlyArray`, or `None` if the `ReadonlyArray` is empty. * * @category getters * @since 1.0.0 */ export const last = (self: ReadonlyArray): Option => isNonEmpty(self) ? O.some(lastNonEmpty(self)) : O.none() /** * @category getters * @since 1.0.0 */ export const lastNonEmpty = (self: NonEmptyReadonlyArray): A => self[self.length - 1] /** * Get all but the first element of an `Iterable`, creating a new `Array`, or `None` if the `Iterable` is empty. * * @category getters * @since 1.0.0 */ export const tail = (self: Iterable): Option> => { const input = fromIterable(self) return isNonEmpty(input) ? O.some(tailNonEmpty(input)) : O.none() } /** * @category getters * @since 1.0.0 */ export const tailNonEmpty = (self: NonEmptyReadonlyArray): Array => self.slice(1) /** * Get all but the last element of an `Iterable`, creating a new `Array`, or `None` if the `Iterable` is empty. * * @category getters * @since 1.0.0 */ export const init = (self: Iterable): Option> => { const input = fromIterable(self) return isNonEmpty(input) ? O.some(initNonEmpty(input)) : O.none() } /** * Get all but the last element of a non empty array, creating a new array. * * @category getters * @since 1.0.0 */ export const initNonEmpty = (self: NonEmptyReadonlyArray): Array => self.slice(0, -1) /** * Keep only a max number of elements from the start of an `Iterable`, creating a new `Array`. * * **Note**. `n` is normalized to a non negative integer. * * @category getters * @since 1.0.0 */ export const take: { (n: number): (self: Iterable) => Array (self: Iterable, n: number): Array } = dual(2, (self: Iterable, n: number): Array => { const input = fromIterable(self) return input.slice(0, clamp(n, input)) }) /** * Keep only a max number of elements from the end of an `Iterable`, creating a new `Array`. * * **Note**. `n` is normalized to a non negative integer. * * @category getters * @since 1.0.0 */ export const takeRight: { (n: number): (self: Iterable) => Array (self: Iterable, n: number): Array } = dual(2, (self: Iterable, n: number): Array => { const input = fromIterable(self) const i = clamp(n, input) return i === 0 ? [] : input.slice(-i) }) /** * Calculate the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`. * * @category getters * @since 1.0.0 */ export const takeWhile: { (refinement: Refinement): (self: Iterable) => Array (predicate: Predicate): (self: Iterable) => Array (self: Iterable, refinement: Refinement): Array (self: Iterable, predicate: Predicate): Array } = dual(2, (self: Iterable, predicate: Predicate): Array => { const out: Array = [] for (const a of self) { if (!predicate(a)) { break } out.push(a) } return out }) const spanIndex = (self: Iterable, predicate: Predicate): number => { let i = 0 for (const a of self) { if (!predicate(a)) { break } i++ } return i } /** * Split an `Iterable` into two parts: * * 1. the longest initial subarray for which all elements satisfy the specified predicate * 2. the remaining elements * * @category filtering * @since 1.0.0 */ export const span: { ( refinement: Refinement ): (self: Iterable) => [init: Array, rest: Array] (predicate: Predicate): (self: Iterable) => [init: Array, rest: Array] ( self: Iterable, refinement: Refinement ): [init: Array, rest: Array] (self: Iterable, predicate: Predicate): [init: Array, rest: Array] } = dual( 2, (self: Iterable, predicate: Predicate): [init: Array, rest: Array] => splitAt(self, spanIndex(self, predicate)) ) /** * Drop a max number of elements from the start of an `Iterable`, creating a new `Array`. * * **Note**. `n` is normalized to a non negative integer. * * @category getters * @since 1.0.0 */ export const drop: { (n: number): (self: Iterable) => Array (self: Iterable, n: number): Array } = dual(2, (self: Iterable, n: number): Array => { const input = fromIterable(self) return input.slice(clamp(n, input), input.length) }) /** * Drop a max number of elements from the end of an `Iterable`, creating a new `Array`. * * **Note**. `n` is normalized to a non negative integer. * * @category getters * @since 1.0.0 */ export const dropRight: { (n: number): (self: Iterable) => Array (self: Iterable, n: number): Array } = dual(2, (self: Iterable, n: number): Array => { const input = fromIterable(self) return input.slice(0, input.length - clamp(n, input)) }) /** * Remove the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`. * * @category getters * @since 1.0.0 */ export const dropWhile: { (refinement: Refinement): (self: Iterable) => Array (predicate: Predicate): (self: Iterable) => Array (self: Iterable, refinement: Refinement): Array (self: Iterable, predicate: Predicate): Array } = dual( 2, (self: Iterable, predicate: Predicate): Array => fromIterable(self).slice(spanIndex(self, predicate)) ) /** * Return the first index for which a predicate holds. * * @category getters * @since 1.0.0 */ export const findFirstIndex: { (predicate: Predicate): (self: Iterable) => Option (self: Iterable, predicate: Predicate): Option } = dual(2, (self: Iterable, predicate: Predicate): Option => { let i = 0 for (const a of self) { if (predicate(a)) { return O.some(i) } i++ } return O.none() }) /** * Return the last index for which a predicate holds. * * @category getters * @since 1.0.0 */ export const findLastIndex: { (predicate: Predicate): (self: Iterable) => Option (self: Iterable, predicate: Predicate): Option } = dual(2, (self: Iterable, predicate: Predicate): Option => { const input = fromIterable(self) for (let i = input.length - 1; i >= 0; i--) { if (predicate(input[i])) { return O.some(i) } } return O.none() }) /** * Find the first element for which a predicate holds. * * @category getters * @since 1.0.0 */ export const findFirst: { (refinement: Refinement): (self: Iterable) => Option (predicate: Predicate): (self: Iterable) => Option (self: Iterable, refinement: Refinement): Option (self: Iterable, predicate: Predicate): Option } = dual(2, (self: Iterable, predicate: Predicate): Option => { const input = fromIterable(self) for (let i = 0; i < input.length; i++) { if (predicate(input[i])) { return O.some(input[i]) } } return O.none() }) /** * Find the last element for which a predicate holds. * * @category getters * @since 1.0.0 */ export const findLast: { (refinement: Refinement): (self: Iterable) => Option (predicate: Predicate): (self: Iterable) => Option (self: Iterable, refinement: Refinement): Option (self: Iterable, predicate: Predicate): Option } = dual(2, (self: Iterable, predicate: Predicate): Option => { const input = fromIterable(self) for (let i = input.length - 1; i >= 0; i--) { if (predicate(input[i])) { return O.some(input[i]) } } return O.none() }) /** * Insert an element at the specified index, creating a new `NonEmptyArray`, * or return `None` if the index is out of bounds. * * @since 1.0.0 */ export const insertAt: { (i: number, b: B): (self: Iterable) => Option> (self: Iterable, i: number, b: B): Option> } = dual(3, (self: Iterable, i: number, b: B): Option> => { const out: Array = Array.from(self) // v--- `= self.length` is ok, it means inserting in last position if (i < 0 || i > out.length) { return O.none() } out.splice(i, 0, b) return O.some(out) as any }) /** * Change the element at the specified index, creating a new `Array`, * or return a copy of the input if the index is out of bounds. * * @since 1.0.0 */ export const replace: { (i: number, b: B): (self: Iterable) => Array (self: Iterable, i: number, b: B): Array } = dual(3, (self: Iterable, i: number, b: B): Array => modify(self, i, () => b)) /** * @since 1.0.0 */ export const replaceOption: { (i: number, b: B): (self: Iterable) => Option> (self: Iterable, i: number, b: B): Option> } = dual( 3, (self: Iterable, i: number, b: B): Option> => modifyOption(self, i, () => b) ) /** * Apply a function to the element at the specified index, creating a new `Array`, * or return a copy of the input if the index is out of bounds. * * @since 1.0.0 */ export const modify: { (i: number, f: (a: A) => B): (self: Iterable) => Array (self: Iterable, i: number, f: (a: A) => B): Array } = dual( 3, (self: Iterable, i: number, f: (a: A) => B): Array => O.getOrElse(modifyOption(self, i, f), () => Array.from(self)) ) /** * Apply a function to the element at the specified index, creating a new `Array`, * or return `None` if the index is out of bounds. * * @since 1.0.0 */ export const modifyOption: { (i: number, f: (a: A) => B): (self: Iterable) => Option> (self: Iterable, i: number, f: (a: A) => B): Option> } = dual(3, (self: Iterable, i: number, f: (a: A) => B): Option> => { const out = Array.from(self) if (isOutOfBound(i, out)) { return O.none() } const next = f(out[i]) // @ts-expect-error out[i] = next return O.some(out) }) /** * Delete the element at the specified index, creating a new `Array`, * or return a copy of the input if the index is out of bounds. * * @since 1.0.0 */ export const remove: { (i: number): (self: Iterable) => Array (self: Iterable, i: number): Array } = dual(2, (self: Iterable, i: number): Array => { const out = Array.from(self) if (isOutOfBound(i, out)) { return out } out.splice(i, 1) return out }) /** * Reverse an `Iterable`, creating a new `Array`. * * @since 1.0.0 */ export const reverse = (self: Iterable): Array => Array.from(self).reverse() /** * @since 1.0.0 */ export const reverseNonEmpty = ( self: NonEmptyReadonlyArray ): NonEmptyArray => [lastNonEmpty(self), ...self.slice(0, -1).reverse()] /** * Return all the `Right` elements from an `Interable` of `Either`s. * * @category getters * @since 1.0.0 */ export const rights: (self: Iterable>) => Array = E.rights /** * Return all the `Left` elements from an `Interable` of `Either`s. * * @category getters * @since 1.0.0 */ export const lefts: (self: Iterable>) => Array = E.lefts /** * Sort the elements of an `Iterable` in increasing order, creating a new `Array`. * * @category sorting * @since 1.0.0 */ export const sort = (O: Order) => (self: Iterable): Array => { const out = Array.from(self) out.sort(O.compare) return out } /** * Sort the elements of a `NonEmptyReadonlyArray` in increasing order, creating a new `NonEmptyArray`. * * @category sorting * @since 1.0.0 */ export const sortNonEmpty = (O: Order) => (self: NonEmptyReadonlyArray): NonEmptyArray => sort(O)(self) as any /** * Sort the elements of an `Iterable` in increasing order, where elements are compared * using first `orders[0]`, then `orders[1]`, etc... * * @category sorting * @since 1.0.0 */ export const sortBy = (...orders: ReadonlyArray>) => (self: Iterable): Array => { const input = fromIterable(self) return (isNonEmpty(input) ? sortByNonEmpty(...orders)(input) : []) } /** * @category sorting * @since 1.0.0 */ export const sortByNonEmpty = ( ...orders: ReadonlyArray> ): ((as: NonEmptyReadonlyArray) => NonEmptyArray) => sortNonEmpty(order.getMonoid().combineAll(orders)) /** * Takes two `Iterable`s and returns an `Array` of corresponding pairs. * If one input `Iterable` is short, excess elements of the * longer `Iterable` are discarded. * * @since 1.0.0 */ export const zip: { (that: Iterable): (self: Iterable) => Array<[A, B]> (self: Iterable, that: Iterable): Array<[A, B]> } = dual( 2, (self: Iterable, that: Iterable): Array<[A, B]> => zipWith(self, that, (a, b) => [a, b]) ) /** * Apply a function to pairs of elements at the same index in two `Iterable`s, collecting the results in a new `Array`. If one * input `Iterable` is short, excess elements of the longer `Iterable` are discarded. * * @since 1.0.0 */ export const zipWith: { (that: Iterable, f: (a: A, b: B) => C): (self: Iterable) => Array (self: Iterable, that: Iterable, f: (a: A, b: B) => C): Array } = dual(3, (self: Iterable, that: Iterable, f: (a: A, b: B) => C): Array => { const as = fromIterable(self) const bs = fromIterable(that) return isNonEmpty(as) && isNonEmpty(bs) ? zipNonEmptyWith(bs, f)(as) : [] }) /** * @since 1.0.0 */ export const zipNonEmpty: { (that: NonEmptyReadonlyArray): (self: NonEmptyReadonlyArray) => NonEmptyArray<[A, B]> (self: NonEmptyReadonlyArray, that: NonEmptyReadonlyArray): NonEmptyArray<[A, B]> } = dual( 2, (self: NonEmptyReadonlyArray, that: NonEmptyReadonlyArray): NonEmptyArray<[A, B]> => zipNonEmptyWith(self, that, (a, b) => [a, b]) ) /** * @since 1.0.0 */ export const zipNonEmptyWith: { ( that: NonEmptyReadonlyArray, f: (a: A, b: B) => C ): (self: NonEmptyReadonlyArray) => NonEmptyArray ( self: NonEmptyReadonlyArray, that: NonEmptyReadonlyArray, f: (a: A, b: B) => C ): NonEmptyArray } = dual(3, ( self: NonEmptyReadonlyArray, that: NonEmptyReadonlyArray, f: (a: A, b: B) => C ): NonEmptyArray => { const cs: NonEmptyArray = [f(headNonEmpty(self), headNonEmpty(that))] const len = Math.min(self.length, that.length) for (let i = 1; i < len; i++) { cs[i] = f(self[i], that[i]) } return cs }) /** * This function is the inverse of `zip`. Takes an `Iterable` of pairs and return two corresponding `Array`s. * * @since 1.0.0 */ export const unzip = (self: Iterable<[A, B]>): [Array, Array] => { const input = fromIterable(self) return isNonEmpty(input) ? unzipNonEmpty(input) : [[], []] } /** * @since 1.0.0 */ export const unzipNonEmpty = ( self: NonEmptyReadonlyArray<[A, B]> ): [NonEmptyArray, NonEmptyArray] => { const fa: NonEmptyArray = [self[0][0]] const fb: NonEmptyArray = [self[0][1]] for (let i = 1; i < self.length; i++) { fa[i] = self[i][0] fb[i] = self[i][1] } return [fa, fb] } /** * Places an element in between members of an `Iterable` * * @since 1.0.0 */ export const intersperse: { (middle: B): (self: Iterable) => Array (self: Iterable, middle: B): Array } = dual(2, (self: Iterable, middle: B): Array => { const input = fromIterable(self) return (isNonEmpty(input) ? intersperseNonEmpty(input, middle) : []) }) /** * Places an element in between members of a `NonEmptyReadonlyArray` * * @since 1.0.0 */ export const intersperseNonEmpty: { (middle: B): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: NonEmptyReadonlyArray, middle: B): NonEmptyArray } = dual(2, (self: NonEmptyReadonlyArray, middle: B): NonEmptyArray => { const out: NonEmptyArray = [headNonEmpty(self)] const tail = tailNonEmpty(self) for (let i = 0; i < tail.length; i++) { if (i < tail.length) { out.push(middle) } out.push(tail[i]) } return out }) /** * Apply a function to the head, creating a new `NonEmptyReadonlyArray`. * * @since 1.0.0 */ export const modifyNonEmptyHead: { (f: (a: A) => B): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: NonEmptyReadonlyArray, f: (a: A) => B): NonEmptyArray } = dual( 2, ( self: NonEmptyReadonlyArray, f: (a: A) => B ): NonEmptyArray => [f(headNonEmpty(self)), ...tailNonEmpty(self)] ) /** * Change the head, creating a new `NonEmptyReadonlyArray`. * * @since 1.0.0 */ export const setNonEmptyHead: { (b: B): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: NonEmptyReadonlyArray, b: B): NonEmptyArray } = dual( 2, (self: NonEmptyReadonlyArray, b: B): NonEmptyArray => modifyNonEmptyHead(self, () => b) ) /** * Apply a function to the last element, creating a new `NonEmptyReadonlyArray`. * * @since 1.0.0 */ export const modifyNonEmptyLast: { (f: (a: A) => B): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: NonEmptyReadonlyArray, f: (a: A) => B): NonEmptyArray } = dual( 2, (self: NonEmptyReadonlyArray, f: (a: A) => B): NonEmptyArray => append(initNonEmpty(self), f(lastNonEmpty(self))) ) /** * Change the last element, creating a new `NonEmptyReadonlyArray`. * * @since 1.0.0 */ export const setNonEmptyLast: { (b: B): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: NonEmptyReadonlyArray, b: B): NonEmptyArray } = dual( 2, (self: NonEmptyReadonlyArray, b: B): NonEmptyArray => modifyNonEmptyLast(self, () => b) ) /** * Rotate an `Iterable` by `n` steps. * * @since 1.0.0 */ export const rotate: { (n: number): (self: Iterable) => Array (self: Iterable, n: number): Array } = dual(2, (self: Iterable, n: number): Array => { const input = fromIterable(self) return isNonEmpty(input) ? rotateNonEmpty(input, n) : [] }) /** * Rotate a `NonEmptyReadonlyArray` by `n` steps. * * @since 1.0.0 */ export const rotateNonEmpty: { (n: number): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: NonEmptyReadonlyArray, n: number): NonEmptyArray } = dual(2, (self: NonEmptyReadonlyArray, n: number): NonEmptyArray => { const len = self.length const m = Math.round(n) % len if (isOutOfBound(Math.abs(m), self) || m === 0) { return copy(self) } if (m < 0) { const [f, s] = splitNonEmptyAt(self, -m) return appendAllNonEmpty(s, f) } else { return rotateNonEmpty(self, m - len) } }) /** * Returns a function that checks if a `ReadonlyArray` contains a given value using a provided `equivalence` function. * * @category predicates * @since 1.0.0 */ export const contains = (isEquivalent: (self: A, that: A) => boolean): { (a: A): (self: Iterable) => boolean (self: Iterable, a: A): boolean } => dual(2, (self: Iterable, a: A): boolean => { for (const i of self) { if (isEquivalent(a, i)) { return true } } return false }) /** * Remove duplicates from am `Iterable`, keeping the first occurrence of an element. * * @since 1.0.0 */ export const uniq = (isEquivalent: (self: A, that: A) => boolean) => (self: Iterable): Array => { const input = fromIterable(self) return isNonEmpty(input) ? uniqNonEmpty(isEquivalent)(input) : [] } /** * Remove duplicates from a `NonEmptyReadonlyArray`, keeping the first occurrence of an element. * * @since 1.0.0 */ export const uniqNonEmpty = (isEquivalent: (self: A, that: A) => boolean) => (self: NonEmptyReadonlyArray): NonEmptyArray => { const out: NonEmptyArray = [headNonEmpty(self)] const rest = tailNonEmpty(self) for (const a of rest) { if (out.every((o) => !isEquivalent(a, o))) { out.push(a) } } return out } /** * A useful recursion pattern for processing an `Iterable` to produce a new `Array`, often used for "chopping" up the input * `Iterable`. Typically chop is called with some function that will consume an initial prefix of the `Iterable` and produce a * value and the rest of the `Array`. * * @since 1.0.0 */ export const chop: { ( f: (as: NonEmptyReadonlyArray) => readonly [B, ReadonlyArray] ): (self: Iterable) => Array ( self: Iterable, f: (as: NonEmptyReadonlyArray) => readonly [B, ReadonlyArray] ): Array } = dual(2, ( self: Iterable, f: (as: NonEmptyReadonlyArray) => readonly [B, ReadonlyArray] ): Array => { const input = fromIterable(self) return isNonEmpty(input) ? chopNonEmpty(input, f) : [] }) /** * A useful recursion pattern for processing a `NonEmptyReadonlyArray` to produce a new `NonEmptyReadonlyArray`, often used for "chopping" up the input * `NonEmptyReadonlyArray`. Typically `chop` is called with some function that will consume an initial prefix of the `NonEmptyReadonlyArray` and produce a * value and the tail of the `NonEmptyReadonlyArray`. * * @since 1.0.0 */ export const chopNonEmpty: { ( f: (as: NonEmptyReadonlyArray) => readonly [B, ReadonlyArray] ): (self: NonEmptyReadonlyArray) => NonEmptyArray ( self: NonEmptyReadonlyArray, f: (as: NonEmptyReadonlyArray) => readonly [B, ReadonlyArray] ): NonEmptyArray } = dual(2, ( self: NonEmptyReadonlyArray, f: (as: NonEmptyReadonlyArray) => readonly [B, ReadonlyArray] ): NonEmptyArray => { const [b, rest] = f(self) const out: NonEmptyArray = [b] let next: ReadonlyArray = rest while (readonlyArray.isNonEmptyArray(next)) { const [b, rest] = f(next) out.push(b) next = rest } return out }) /** * Splits an `Iterable` into two pieces, the first piece has max `n` elements. * * @category getters * @since 1.0.0 */ export const splitAt: { (n: number): (self: Iterable) => [Array, Array] (self: Iterable, n: number): [Array, Array] } = dual(2, (self: Iterable, n: number): [Array, Array] => { const input = Array.from(self) return n >= 1 && isNonEmpty(input) ? splitNonEmptyAt(input, n) : isEmpty(input) ? [input, []] : [[], input] }) /** * @since 1.0.0 */ export const copy: { (self: NonEmptyReadonlyArray): NonEmptyArray (self: ReadonlyArray): Array } = ((self: ReadonlyArray): Array => self.slice()) as any /** * Splits a `NonEmptyReadonlyArray` into two pieces, the first piece has max `n` elements. * * @category getters * @since 1.0.0 */ export const splitNonEmptyAt: { (n: number): (self: NonEmptyReadonlyArray) => [NonEmptyArray, Array] (self: NonEmptyReadonlyArray, n: number): [NonEmptyArray, Array] } = dual(2, (self: NonEmptyReadonlyArray, n: number): [NonEmptyArray, Array] => { const m = Math.max(1, n) return m >= self.length ? [copy(self), []] : [prepend(self.slice(1, m), headNonEmpty(self)), self.slice(m)] }) /** * Splits an `Iterable` into length-`n` pieces. The last piece will be shorter if `n` does not evenly divide the length of * the `Iterable`. Note that `chunksOf(n)([])` is `[]`, not `[[]]`. This is intentional, and is consistent with a recursive * definition of `chunksOf`; it satisfies the property that * * ```ts * chunksOf(n)(xs).concat(chunksOf(n)(ys)) == chunksOf(n)(xs.concat(ys))) * ``` * * whenever `n` evenly divides the length of `self`. * * @category getters * @since 1.0.0 */ export const chunksOf: { (n: number): (self: Iterable) => Array> (self: Iterable, n: number): Array> } = dual(2, (self: Iterable, n: number): Array> => { const input = fromIterable(self) return isNonEmpty(input) ? chunksOfNonEmpty(input, n) : [] }) /** * Splits a `NonEmptyReadonlyArray` into length-`n` pieces. The last piece will be shorter if `n` does not evenly divide the length of * the `NonEmptyReadonlyArray`. * * @category getters * @since 1.0.0 */ export const chunksOfNonEmpty: { (n: number): (self: NonEmptyReadonlyArray) => NonEmptyArray> (self: NonEmptyReadonlyArray, n: number): NonEmptyArray> } = dual( 2, (self: NonEmptyReadonlyArray, n: number): NonEmptyArray> => chopNonEmpty(self, splitNonEmptyAt(n)) ) /** * Group equal, consecutive elements of a `NonEmptyReadonlyArray` into `NonEmptyArray`s. * * @category grouping * @since 1.0.0 */ export const group = (isEquivalent: (self: A, that: A) => boolean) => (self: NonEmptyReadonlyArray): NonEmptyArray> => chopNonEmpty(self, (as) => { const h = headNonEmpty(as) const out: NonEmptyArray = [h] let i = 1 for (; i < as.length; i++) { const a = as[i] if (isEquivalent(a, h)) { out.push(a) } else { break } } return [out, as.slice(i)] }) /** * Splits an `Iterable` into sub-non-empty-arrays stored in an object, based on the result of calling a `string`-returning * function on each element, and grouping the results according to values returned * * @category grouping * @since 1.0.0 */ export const groupBy: { (f: (a: A) => string): (self: Iterable) => Record> (self: Iterable, f: (a: A) => string): Record> } = dual(2, (self: Iterable, f: (a: A) => string): Record> => { const out: Record> = {} for (const a of self) { const k = f(a) if (Object.prototype.hasOwnProperty.call(out, k)) { out[k].push(a) } else { out[k] = [a] } } return out }) /** * @since 1.0.0 */ export const union = (isEquivalent: (self: A, that: A) => boolean): { (that: ReadonlyArray): (self: ReadonlyArray) => Array (self: ReadonlyArray, that: ReadonlyArray): Array } => dual(2, (self: ReadonlyArray, that: ReadonlyArray): Array => { const a = Array.from(self) const b = Array.from(that) return isNonEmpty(a) && isNonEmpty(b) ? unionNonEmpty(isEquivalent)(a, b) : isNonEmpty(a) ? a : b }) /** * @since 1.0.0 */ export const unionNonEmpty = (isEquivalent: (self: A, that: A) => boolean): { (that: NonEmptyReadonlyArray): (self: ReadonlyArray) => NonEmptyArray (that: ReadonlyArray): (self: NonEmptyReadonlyArray) => NonEmptyArray (self: ReadonlyArray, that: NonEmptyReadonlyArray): NonEmptyArray (self: NonEmptyReadonlyArray, that: ReadonlyArray): NonEmptyArray } => dual( 2, (self: NonEmptyReadonlyArray, that: ReadonlyArray): NonEmptyArray => uniqNonEmpty(isEquivalent)(appendAllNonEmpty(self, that)) ) /** * Creates an `Array` of unique values that are included in all given `Iterable`s. * The order and references of result values are determined by the first `Iterable`. * * @since 1.0.0 */ export const intersection = (isEquivalent: (self: A, that: A) => boolean): { (that: Iterable): (self: Iterable) => Array (self: Iterable, that: Iterable): Array } => { const has = contains(isEquivalent) return dual( 2, (self: Iterable, that: Iterable): Array => fromIterable(self).filter((a) => has(that, a)) ) } /** * Creates a `Array` of values not included in the other given `Iterable`. * The order and references of result values are determined by the first `Iterable`. * * @since 1.0.0 */ export const difference = (isEquivalent: (self: A, that: A) => boolean): { (that: Iterable): (self: Iterable) => Array (self: Iterable, that: Iterable): Array } => { const has = contains(isEquivalent) return dual( 2, (self: Iterable, that: Iterable): Array => fromIterable(self).filter((a) => !has(that, a)) ) } /** * @category constructors * @since 1.0.0 */ export const of = (a: A): NonEmptyArray => [a] /** * @category constructors * @since 1.0.0 */ export const empty: () => Array = () => [] /** * @category instances * @since 1.0.0 */ export const Of: of_.Of = { of } /** * @category mapping * @since 1.0.0 */ export const map: { (f: (a: A, i: number) => B): (self: ReadonlyArray) => Array (self: ReadonlyArray, f: (a: A, i: number) => B): Array } = dual(2, (self: ReadonlyArray, f: (a: A, i: number) => B): Array => self.map(f)) /** * @category mapping * @since 1.0.0 */ export const mapNonEmpty: { (f: (a: A, i: number) => B): (self: readonly [A, ...Array]) => [B, ...Array] (self: readonly [A, ...Array], f: (a: A, i: number) => B): [B, ...Array] } = map as any const imap = covariant.imap(map) /** * @category instances * @since 1.0.0 */ export const Covariant: covariant.Covariant = { imap, map } /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } /** * @category mapping * @since 1.0.0 */ export const tupled: (self: ReadonlyArray) => Array<[A]> = invariant .tupled(Invariant) as any /** * @category mapping * @since 1.0.0 */ export const flap: { (a: A, self: ReadonlyArray<(a: A) => B>): Array (self: ReadonlyArray<(a: A) => B>): (a: A) => Array } = covariant.flap(Covariant) as any /** * Maps the success value of this effect to the specified constant value. * * @category mapping * @since 1.0.0 */ export const as: { <_, B>(self: ReadonlyArray<_>, b: B): Array (b: B): <_>(self: ReadonlyArray<_>) => Array } = covariant.as(Covariant) as any /** * @category instances * @since 1.0.0 */ export const Pointed: pointed.Pointed = { of, imap, map } /** * @category combining * @since 1.0.0 */ export const flatMap: { (f: (a: A, i: number) => ReadonlyArray): (self: ReadonlyArray) => Array (self: ReadonlyArray, f: (a: A, i: number) => ReadonlyArray): Array } = dual( 2, (self: ReadonlyArray, f: (a: A, i: number) => ReadonlyArray): Array => { if (isEmpty(self)) { return [] } const out: Array = [] for (let i = 0; i < self.length; i++) { out.push(...f(self[i], i)) } return out } ) /** * @category combining * @since 1.0.0 */ export const flatMapNonEmpty: { ( f: (a: A, i: number) => NonEmptyReadonlyArray ): (self: NonEmptyReadonlyArray) => NonEmptyArray ( self: NonEmptyReadonlyArray, f: (a: A, i: number) => NonEmptyReadonlyArray ): NonEmptyArray } = flatMap as any /** * @category instances * @since 1.0.0 */ export const FlatMap: flatMap_.FlatMap = { flatMap } /** * @category combining * @since 1.0.0 */ export const flatten: (self: ReadonlyArray>) => Array = flatMap_ .flatten(FlatMap) as any /** * @category combining * @since 1.0.0 */ export const flattenNonEmpty: ( self: NonEmptyReadonlyArray> ) => NonEmptyArray = flatMapNonEmpty(identity) /** * @since 1.0.0 */ export const composeKleisliArrow: { ( afb: (a: A) => ReadonlyArray, bfc: (b: B) => ReadonlyArray ): (a: A) => ReadonlyArray ( bfc: (b: B) => ReadonlyArray ): (afb: (a: A) => ReadonlyArray) => (a: A) => ReadonlyArray } = flatMap_.composeKleisliArrow(FlatMap) /** * @category instances * @since 1.0.0 */ export const Chainable: chainable.Chainable = { imap, map, flatMap } /** * @category filtering * @since 1.0.0 */ export const filterMap: { (f: (a: A, i: number) => Option): (self: Iterable) => Array (self: Iterable, f: (a: A, i: number) => Option): Array } = dual( 2, (self: Iterable, f: (a: A, i: number) => Option): Array => { const as = fromIterable(self) const out: Array = [] for (let i = 0; i < as.length; i++) { const o = f(as[i], i) if (O.isSome(o)) { out.push(o.value) } } return out } ) /** * @category filtering * @since 1.0.0 */ export const partitionMap: { (f: (a: A, i: number) => Either): (self: Iterable) => [Array, Array] (self: Iterable, f: (a: A, i: number) => Either): [Array, Array] } = dual( 2, (self: Iterable, f: (a: A, i: number) => Either): [Array, Array] => { const left: Array = [] const right: Array = [] const as = fromIterable(self) for (let i = 0; i < as.length; i++) { const e = f(as[i], i) if (E.isLeft(e)) { left.push(e.left) } else { right.push(e.right) } } return [left, right] } ) /** * @category instances * @since 1.0.0 */ export const Filterable: filterable.Filterable = { partitionMap, filterMap } /** * @category filtering * @since 1.0.0 */ export const compact: (self: Iterable>) => Array = filterMap(identity) /** * @category filtering * @since 1.0.0 */ export const filter: { ( refinement: (a: A, i: number) => a is B ): (self: Iterable) => Array (predicate: (a: A, i: number) => boolean): (self: Iterable) => Array ( self: Iterable, refinement: (a: A, i: number) => a is B ): Array (self: Iterable, predicate: (a: A, i: number) => boolean): Array } = dual( 2, (self: Iterable, predicate: (a: A, i: number) => boolean): Array => { const as = fromIterable(self) const out: Array = [] for (let i = 0; i < as.length; i++) { if (predicate(as[i], i)) { out.push(as[i]) } } return out } ) /** * @category filtering * @since 1.0.0 */ export const partition: { (refinement: (a: A, i: number) => a is B): ( self: Iterable ) => [Array, Array] ( predicate: (a: A, i: number) => boolean ): (self: Iterable) => [Array, Array] ( self: Iterable, refinement: (a: A, i: number) => a is B ): [Array, Array] ( self: Iterable, predicate: (a: A, i: number) => boolean ): [Array, Array] } = dual( 2, ( self: Iterable, predicate: (a: A, i: number) => boolean ): [Array, Array] => { const left: Array = [] const right: Array = [] const as = fromIterable(self) for (let i = 0; i < as.length; i++) { if (predicate(as[i], i)) { right.push(as[i]) } else { left.push(as[i]) } } return [left, right] } ) /** * @category filtering * @since 1.0.0 */ export const separate: (self: Iterable>) => [Array, Array] = partitionMap( identity ) /** * @category traversing * @since 1.0.0 */ export const traverseNonEmpty = ( F: semiApplicative.SemiApplicative ): { ( f: (a: A, i: number) => Kind ): (self: NonEmptyReadonlyArray) => Kind> ( self: NonEmptyReadonlyArray, f: (a: A, i: number) => Kind ): Kind> } => dual(2, ( self: NonEmptyReadonlyArray, f: (a: A, i: number) => Kind ): Kind> => { const [head, ...tail] = mapNonEmpty(self, f) return F.productMany(head, tail) }) /** * @category traversing * @since 1.0.0 */ export const traverse = (F: applicative.Applicative): { ( f: (a: A, i: number) => Kind ): (self: Iterable) => Kind> ( self: Iterable, f: (a: A, i: number) => Kind ): Kind> } => dual(2, ( self: Iterable, f: (a: A, i: number) => Kind ): Kind> => F.productAll(fromIterable(self).map(f))) /** * @category traversing * @since 1.0.0 */ export const sequence = ( F: applicative.Applicative ): ( self: ReadonlyArray> ) => Kind> => traverse(F)(identity) /** * @category instances * @since 1.0.0 */ export const Traversable: traversable.Traversable = { traverse: traverse as any } /** * @category traversing * @since 1.0.0 */ export const traverseTap: ( F: applicative.Applicative ) => { ( self: ReadonlyArray, f: (a: A) => Kind ): Kind> ( f: (a: A) => Kind ): (self: ReadonlyArray) => Kind> } = traversable.traverseTap(Traversable) as any /** * @category traversing * @since 1.0.0 */ export const sequenceNonEmpty = ( F: semiApplicative.SemiApplicative ): (( self: NonEmptyReadonlyArray> ) => Kind>) => traverseNonEmpty(F)(identity) const product = (self: ReadonlyArray, that: ReadonlyArray): ReadonlyArray<[A, B]> => { if (isEmpty(self) || isEmpty(that)) { return empty() } const out: Array<[A, B]> = [] for (let i = 0; i < self.length; i++) { for (let j = 0; j < that.length; j++) { out.push([self[i], that[j]]) } } return out } const productMany = semiProduct.productMany(map, product) /** * @category instances * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } /** * @category instances * @since 1.0.0 */ export const SemiApplicative: semiApplicative.SemiApplicative = { imap, map, product, productMany } /** * @since 1.0.0 */ export const ap: { (self: ReadonlyArray<(a: A) => B>, that: ReadonlyArray): Array (that: ReadonlyArray): (self: ReadonlyArray<(a: A) => B>) => Array } = semiApplicative.ap(SemiApplicative) as any /** * Lifts a binary function into `ReadonlyArray`. * * @param f - The function to lift. * * @category lifting * @since 1.0.0 */ export const lift2: (f: (a: A, b: B) => C) => { (self: ReadonlyArray, that: ReadonlyArray): Array (that: ReadonlyArray): (self: ReadonlyArray) => Array } = semiApplicative.lift2(SemiApplicative) as any /** * @category instances * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll: (collection) => { const arrays = fromIterable(collection) return isEmpty(arrays) ? empty() : SemiProduct.productMany(arrays[0], arrays.slice(1)) } } /** * @category instances * @since 1.0.0 */ export const Applicative: applicative.Applicative = { imap, of, map, product, productMany, productAll: Product.productAll } /** * @category lifting * @since 1.0.0 */ export const liftMonoid: (M: Monoid) => Monoid> = applicative .getMonoid( Applicative ) /** * @category instances * @since 1.0.0 */ export const Monad: monad.Monad = { imap, of, map, flatMap } /** * @category folding * @since 1.0.0 */ export const reduce: { (b: B, f: (b: B, a: A, i: number) => B): (self: Iterable) => B (self: Iterable, b: B, f: (b: B, a: A, i: number) => B): B } = dual( 3, (self: Iterable, b: B, f: (b: B, a: A, i: number) => B): B => fromIterable(self).reduce((b, a, i) => f(b, a, i), b) ) /** * @category folding * @since 1.0.0 */ export const reduceRight: { (b: B, f: (b: B, a: A, i: number) => B): (self: Iterable) => B (self: Iterable, b: B, f: (b: B, a: A, i: number) => B): B } = dual( 3, (self: Iterable, b: B, f: (b: B, a: A, i: number) => B): B => fromIterable(self).reduceRight((b, a, i) => f(b, a, i), b) ) /** * @category instances * @since 1.0.0 */ export const Foldable: foldable.Foldable = { reduce } /** * @category folding * @since 1.0.0 */ export const combineMap = (Monoid: Monoid): { (f: (a: A, i: number) => M): (self: Iterable) => M (self: Iterable, f: (a: A, i: number) => M): M } => dual( 2, (self: Iterable, f: (a: A, i: number) => M): M => fromIterable(self).reduce((m, a, i) => Monoid.combine(m, f(a, i)), Monoid.empty) ) /** * @category folding * @since 1.0.0 */ export const combineMapNonEmpty = (S: Semigroup): { (f: (a: A, i: number) => S): (self: NonEmptyReadonlyArray) => S (self: NonEmptyReadonlyArray, f: (a: A, i: number) => S): S } => dual( 2, (self: NonEmptyReadonlyArray, f: (a: A, i: number) => S): S => tailNonEmpty(self).reduce((s, a, i) => S.combine(s, f(a, i + 1)), f(headNonEmpty(self), 0)) ) /** * @category folding * @since 1.0.0 */ export const reduceKind: ( G: monad.Monad ) => { ( b: B, f: (b: B, a: A) => Kind ): (self: ReadonlyArray) => Kind ( self: ReadonlyArray, b: B, f: (b: B, a: A) => Kind ): Kind } = foldable.reduceKind(Foldable) /** * @category folding * @since 1.0.0 */ export const coproductMapKind: ( G: Coproduct ) => { ( f: (a: A) => Kind ): (self: ReadonlyArray) => Kind ( self: ReadonlyArray, f: (a: A) => Kind ): Kind } = foldable.coproductMapKind(Foldable) /** * @category filtering * @since 1.0.0 */ export const traversePartitionMap = ( F: applicative.Applicative ): { ( f: (a: A) => Kind> ): (self: ReadonlyArray) => Kind, Array]> ( self: ReadonlyArray, f: (a: A) => Kind> ): Kind, Array]> } => dual(2, ( self: ReadonlyArray, f: (a: A) => Kind> ): Kind, Array]> => { return F.map(traverse(F)(self, f), separate) }) /** * @category filtering * @since 1.0.0 */ export const traverseFilterMap = ( F: applicative.Applicative ): { ( f: (a: A) => Kind> ): (self: ReadonlyArray) => Kind> ( self: ReadonlyArray, f: (a: A) => Kind> ): Kind> } => dual(2, ( self: ReadonlyArray, f: (a: A) => Kind> ): Kind> => { return F.map(traverse(F)(self, f), compact) }) /** * @category instances * @since 1.0.0 */ export const TraversableFilterable: traversableFilterable.TraversableFilterable< ReadonlyArrayTypeLambda > = { traversePartitionMap: traversePartitionMap as any, traverseFilterMap: traverseFilterMap as any } /** * Filter values inside a context. * * @since 1.0.0 */ export const traverseFilter: ( F: applicative.Applicative ) => { ( predicate: (a: A) => Kind ): (self: ReadonlyArray) => Kind> ( self: ReadonlyArray, predicate: (a: A) => Kind ): Kind> } = traversableFilterable.traverseFilter(TraversableFilterable) as any /** * @since 1.0.0 */ export const traversePartition: ( F: applicative.Applicative ) => { ( predicate: (a: A) => Kind ): (self: ReadonlyArray) => Kind, Array]> ( self: ReadonlyArray, predicate: (a: A) => Kind ): Kind, Array]> } = traversableFilterable.traversePartition(TraversableFilterable) as any /** * @category lifting * @since 1.0.0 */ export const liftPredicate: { (refinement: Refinement): (c: C) => Array (predicate: Predicate): (b: B) => Array } = (predicate: Predicate) => (b: B) => predicate(b) ? [b] : [] /** * @category lifting * @since 1.0.0 */ export const liftOption = , B>( f: (...a: A) => Option ) => (...a: A): Array => fromOption(f(...a)) /** * @category conversions * @since 1.0.0 */ export const fromNullable = (a: A): Array> => a == null ? empty() : [a as NonNullable] /** * @category lifting * @since 1.0.0 */ export const liftNullable = , B>( f: (...a: A) => B | null | undefined ): (...a: A) => Array> => (...a) => fromNullable(f(...a)) /** * @category combining * @since 1.0.0 */ export const flatMapNullable: { (f: (a: A) => B | null | undefined): (self: ReadonlyArray) => Array> (self: ReadonlyArray, f: (a: A) => B | null | undefined): Array> } = dual( 2, (self: ReadonlyArray, f: (a: A) => B | null | undefined): Array> => isNonEmpty(self) ? fromNullable(f(headNonEmpty(self))) : empty() ) /** * @category lifting * @since 1.0.0 */ export const liftEither = , E, B>( f: (...a: A) => Either ) => (...a: A): Array => { const e = f(...a) return E.isLeft(e) ? [] : [e.right] } /** * Check if a predicate holds true for every `ReadonlyArray` member. * * @category predicates * @since 1.0.0 */ export function every( refinement: Refinement ): Refinement, ReadonlyArray> export function every(predicate: Predicate): Predicate> export function every(predicate: Predicate): Predicate> { return (self) => self.every(predicate) } /** * Check if a predicate holds true for some `ReadonlyArray` member. * * @category predicates * @since 1.0.0 */ export const some = (predicate: Predicate) => (self: ReadonlyArray): self is NonEmptyReadonlyArray => self.some(predicate) /** * Fold an `Iterable`, accumulating values in some `Monoid`, combining adjacent elements * using the specified separator. * * @since 1.0.0 */ export const intercalate = (M: Monoid): { (middle: A): (self: Iterable) => A (self: Iterable, middle: A): A } => dual( 2, (self: Iterable, middle: A): A => { const as = fromIterable(self) return isNonEmpty(as) ? intercalateNonEmpty(M)(as, middle) : M.empty } ) /** * Places an element in between members of a `NonEmptyReadonlyArray`, then folds the results using the provided `Semigroup`. * * @since 1.0.0 */ export const intercalateNonEmpty = ( S: Semigroup ): { (middle: A): (self: NonEmptyReadonlyArray) => A (self: NonEmptyReadonlyArray, middle: A): A } => dual( 2, (self: NonEmptyReadonlyArray, middle: A): A => semigroup.intercalate(S, middle).combineMany(headNonEmpty(self), tailNonEmpty(self)) ) /** * @since 1.0.0 */ export const join: { (middle: string): (self: ReadonlyArray) => string (self: ReadonlyArray, middle: string): string } = intercalate(string.Monoid) /** * @since 1.0.0 */ export const extend: { (f: (as: ReadonlyArray) => B): (self: ReadonlyArray) => Array (self: ReadonlyArray, f: (as: ReadonlyArray) => B): Array } = dual( 2, (self: ReadonlyArray, f: (as: ReadonlyArray) => B): Array => self.map((_, i, as) => f(as.slice(i))) ) /** * @since 1.0.0 */ export const min = (O: Order): ((self: NonEmptyReadonlyArray) => A) => { const S = semigroup.min(O) return (self) => self.reduce(S.combine) } /** * @since 1.0.0 */ export const max = (O: Order): ((self: NonEmptyReadonlyArray) => A) => { const S = semigroup.max(O) return (self) => self.reduce(S.combine) } /** * @category constructors * @since 1.0.0 */ export const unfold = (b: B, f: (b: B) => Option): Array => { const out: Array = [] let next: B = b let o: Option while (O.isSome(o = f(next))) { const [a, b] = o.value out.push(a) next = b } return out } /** * @category instances * @since 1.0.0 */ export const getUnionSemigroup = ( isEquivalent: (self: A, that: A) => boolean ): Semigroup> => semigroup.make(union(isEquivalent)) as any /** * @category instances * @since 1.0.0 */ export const getUnionMonoid = ( isEquivalent: (self: A, that: A) => boolean ): Monoid> => { const S = getUnionSemigroup(isEquivalent) return ({ combine: S.combine, combineMany: S.combineMany, combineAll: (collection) => S.combineMany([], collection), empty: [] }) } /** * @category instances * @since 1.0.0 */ export const getIntersectionSemigroup = ( isEquivalent: (self: A, that: A) => boolean ): Semigroup> => semigroup.make(intersection(isEquivalent)) as any /** * Returns a `Semigroup` for `ReadonlyArray`. * * @category instances * @since 1.0.0 */ export const getSemigroup: () => Semigroup> = semigroup.array /** * Returns a `Monoid` for `ReadonlyArray`. * * @category instances * @since 1.0.0 */ export const getMonoid: () => Monoid> = monoid.array /** * This function creates and returns a new `Order` for an array of values based on a given `Order` for the elements of the array. * The returned `Order` compares two arrays by applying the given `Order` to each element in the arrays. * If all elements are equal, the arrays are then compared based on their length. * It is useful when you need to compare two arrays of the same type and you have a specific way of comparing each element of the array. * * @category lifting * @since 1.0.0 */ export const getOrder: (O: Order) => Order> = order.array // ------------------------------------------------------------------------------------- // do notation // ------------------------------------------------------------------------------------- /** * @category do notation * @since 1.0.0 */ export const bindTo: { (name: N): (self: ReadonlyArray) => Array<{ [K in N]: A }> (self: ReadonlyArray, name: N): Array<{ [K in N]: A }> } = invariant.bindTo(Invariant) as any const let_: { ( name: Exclude, f: (a: A) => B ): (self: ReadonlyArray) => Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: ReadonlyArray, name: Exclude, f: (a: A) => B ): Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = covariant.let(Covariant) as any export { /** * @category do notation * @since 1.0.0 */ let_ as let } /** * @category do notation * @since 1.0.0 */ export const Do: ReadonlyArray<{}> = of_.Do(Of) /** * @category do notation * @since 1.0.0 */ export const bind: { ( name: Exclude, f: (a: A) => ReadonlyArray ): (self: ReadonlyArray) => Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: ReadonlyArray, name: Exclude, f: (a: A) => ReadonlyArray ): Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = chainable.bind(Chainable) as any /** * A variant of `bind` that sequentially ignores the scope. * * @category do notation * @since 1.0.0 */ export const andThenBind: { ( name: Exclude, that: ReadonlyArray ): (self: ReadonlyArray) => Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> ( self: ReadonlyArray, name: Exclude, that: ReadonlyArray ): Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }> } = semiProduct.andThenBind(SemiProduct) as any ================================================ FILE: src/ReadonlyRecord.ts ================================================ /** * This module provides utility functions for working with records in TypeScript. * * @since 1.0.0 */ import type { Either } from "@fp-ts/core/Either" import * as E from "@fp-ts/core/Either" import { dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Option } from "@fp-ts/core/Option" import * as O from "@fp-ts/core/Option" import type * as applicative from "@fp-ts/core/typeclass/Applicative" import * as covariant from "@fp-ts/core/typeclass/Covariant" import type * as filterable from "@fp-ts/core/typeclass/Filterable" import * as invariant from "@fp-ts/core/typeclass/Invariant" import * as traversable from "@fp-ts/core/typeclass/Traversable" import * as traversableFilterable from "@fp-ts/core/typeclass/TraversableFilterable" // ------------------------------------------------------------------------------------- // models // ------------------------------------------------------------------------------------- /** * @category models * @since 1.0.0 */ export interface ReadonlyRecord { readonly [x: string]: A } /** * @category type lambdas * @since 1.0.0 */ export interface ReadonlyRecordTypeLambda extends TypeLambda { readonly type: ReadonlyRecord } // ------------------------------------------------------------------------------------- // constructors // ------------------------------------------------------------------------------------- /** * Creates a new, empty record. * * @category constructors * @since 1.0.0 */ export const empty = (): Record => ({}) /** * Takes an iterable and a projection function and returns a record. * The projection function maps each value of the iterable to a tuple of a key and a value, which is then added to the resulting record. * * @param self - An iterable of values to be mapped to a record. * @param f - A projection function that maps values of the iterable to a tuple of a key and a value. * * @example * import { fromIterable } from '@fp-ts/core/ReadonlyRecord' * * const input = [1, 2, 3, 4] * * assert.deepStrictEqual( * fromIterable(input, a => [String(a), a * 2]), * { '1': 2, '2': 4, '3': 6, '4': 8 } * ) * * @category constructors * @since 1.0.0 */ export const fromIterable: { (f: (a: A) => readonly [string, B]): (self: Iterable) => Record (self: Iterable, f: (a: A) => readonly [string, B]): Record } = dual(2, (self: Iterable, f: (a: A) => readonly [string, B]): Record => { const out: Record = {} for (const a of self) { const [k, b] = f(a) out[k] = b } return out }) // ------------------------------------------------------------------------------------- // guards // ------------------------------------------------------------------------------------- /** * Determine if a `ReadonlyRecord` is empty. * * @param self - `ReadonlyRecord` to test for emptiness. * * @example * import { isEmpty } from "@fp-ts/core/ReadonlyRecord" * * assert.deepStrictEqual(isEmpty({}), true); * assert.deepStrictEqual(isEmpty({ a: 3 }), false); * * @category guards * @since 1.0.0 */ export const isEmpty = (self: ReadonlyRecord): self is Record => { for (const k in self) { if (has(self, k)) { return false } } return true } // ------------------------------------------------------------------------------------- // conversions // ------------------------------------------------------------------------------------- /** * Transforms the values of a `ReadonlyRecord` into an `Array` with a custom mapping function. * * @param self - The `ReadonlyRecord` to transform. * @param f - The custom mapping function to apply to each key/value of the `ReadonlyRecord`. * * @example * import { collect } from '@fp-ts/core/ReadonlyRecord' * * const x = { a: 1, b: 2, c: 3 } * assert.deepStrictEqual(collect(x, (key, n) => [key, n]), [["a", 1], ["b", 2], ["c", 3]]) * * @category conversions * @since 1.0.0 */ export const collect: { (f: (key: string, a: A) => B): (self: ReadonlyRecord) => Array (self: ReadonlyRecord, f: (key: string, a: A) => B): Array } = dual( 2, (self: ReadonlyRecord, f: (key: string, a: A) => B): Array => { const out: Array = [] for (const key of Object.keys(self)) { out.push(f(key, self[key])) } return out } ) /** * Converts a `ReadonlyRecord` to an `Array` of key-value pairs. * * @param self - A `ReadonlyRecord` to convert to an `Array`. * * @example * import { toArray } from '@fp-ts/core/ReadonlyRecord' * * const x = { a: 1, b: 2 } * assert.deepStrictEqual(toArray(x), [["a", 1], ["b", 2]]) * * @category conversions * @since 1.0.0 */ export const toArray: (self: ReadonlyRecord) => Array<[string, A]> = collect(( key, a ) => [key, a]) // ------------------------------------------------------------------------------------- // utils // ------------------------------------------------------------------------------------- /** * Returns the number of key/value pairs in a `ReadonlyRecord`. * * @param self - A `ReadonlyRecord` to calculate the number of key/value pairs in. * * @example * import { size } from "@fp-ts/core/ReadonlyRecord"; * * assert.deepStrictEqual(size({ a: "a", b: 1, c: true }), 3); * * @since 1.0.0 */ export const size = (self: ReadonlyRecord): number => Object.keys(self).length /** * Check if a given `key` exists in a `ReadonlyRecord`. * * @param self - the `ReadonlyRecord` to look in. * @param key - the key to look for in the `ReadonlyRecord`. * * @example * import { has } from '@fp-ts/core/ReadonlyRecord' * * assert.deepStrictEqual(has({ a: 1, b: 2 }, "a"), true); * assert.deepStrictEqual(has({ a: 1, b: 2 }, "c"), false); * * @since 1.0.0 */ export const has: { (key: string): (self: ReadonlyRecord) => boolean (self: ReadonlyRecord, key: string): boolean } = dual( 2, (self: ReadonlyRecord, key: string): boolean => Object.prototype.hasOwnProperty.call(self, key) ) /** * Retrieve a value at a particular key from a `ReadonlyRecord`, returning it wrapped in an `Option`. * * @param self - The `ReadonlyRecord` to retrieve value from. * @param key - Key to retrieve from `ReadonlyRecord`. * * @example * import { get } from "@fp-ts/core/ReadonlyRecord" * import { some, none } from "@fp-ts/core/Option" * * const person = { name: "John Doe", age: 35 } * * assert.deepStrictEqual(get(person, "name"), some("John Doe")) * assert.deepStrictEqual(get(person, "email"), none()) * * @since 1.0.0 */ export const get: { (key: string): (self: ReadonlyRecord) => Option (self: ReadonlyRecord, key: string): Option } = dual( 2, (self: ReadonlyRecord, key: string): Option => has(self, key) ? O.some(self[key]) : O.none() ) /** * Apply a function to the element at the specified key, creating a new record, * or return `None` if the key doesn't exist. * * @param self - The `ReadonlyRecord` to be updated. * @param key - The key of the element to modify. * @param f - The function to apply to the element. * * @example * import { modifyOption } from "@fp-ts/core/ReadonlyRecord" * import { some, none } from "@fp-ts/core/Option" * * const f = (x: number) => x * 2 * * assert.deepStrictEqual( * modifyOption({ a: 3 }, 'a', f), * some({ a: 6 }) * ) * assert.deepStrictEqual( * modifyOption({ a: 3 }, 'b', f), * none() * ) * * @since 1.0.0 */ export const modifyOption: { (key: string, f: (a: A) => B): (self: ReadonlyRecord) => Option> (self: ReadonlyRecord, key: string, f: (a: A) => B): Option> } = dual( 3, (self: ReadonlyRecord, key: string, f: (a: A) => B): Option> => { if (!has(self, key)) { return O.none() } const out: Record = { ...self } out[key] = f(self[key]) return O.some(out) } ) /** * Replaces a value in the record with the new value passed as parameter. * * @param self - The `ReadonlyRecord` to be updated. * @param key - The key to search for in the record. * @param b - The new value to replace the existing value with. * * @example * import { replaceOption } from "@fp-ts/core/ReadonlyRecord" * import { some, none } from "@fp-ts/core/Option" * * assert.deepStrictEqual( * replaceOption({ a: 1, b: 2, c: 3 }, 'a', 10), * some({ a: 10, b: 2, c: 3 }) * ) * assert.deepStrictEqual(replaceOption({}, 'a', 10), none()) * * @since 1.0.0 */ export const replaceOption: { (key: string, b: B): (self: ReadonlyRecord) => Option> (self: ReadonlyRecord, key: string, b: B): Option> } = dual( 3, (self: ReadonlyRecord, key: string, b: B): Option> => modifyOption(self, key, () => b) ) /** * Removes a key from a `ReadonlyRecord` and returns a new `Record` * * @param self - the `ReadonlyRecord` to remove the key from. * @param key - the key to remove from the `ReadonlyRecord`. * * @example * import { remove } from '@fp-ts/core/ReadonlyRecord' * * assert.deepStrictEqual(remove({ a: 1, b: 2 }, "a"), { b: 2 }) * * @since 1.0.0 */ export const remove: { (key: string): (self: ReadonlyRecord) => Record (self: ReadonlyRecord, key: string): Record } = dual(2, (self: ReadonlyRecord, key: string): Record => { const out: Record = { ...self } delete out[key] return out }) /** * Retrieves the value of the property with the given `key` from a `ReadonlyRecord` and returns an `Option` * of a tuple with the value and the `ReadonlyRecord` with the removed property. * If the key is not present, returns `O.none`. * * @param self - The input `ReadonlyRecord`. * @param key - The key of the property to retrieve. * * @example * import { pop } from '@fp-ts/core/ReadonlyRecord' * import { some, none } from '@fp-ts/core/Option' * * assert.deepStrictEqual(pop({ a: 1, b: 2 }, "a"), some([1, { b: 2 }])) * assert.deepStrictEqual(pop({ a: 1, b: 2 }, "c"), none()) * * @category record * @since 1.0.0 */ export const pop: { (key: string): (self: ReadonlyRecord) => Option]> (self: ReadonlyRecord, key: string): Option]> } = dual(2, ( self: ReadonlyRecord, key: string ): Option]> => has(self, key) ? O.some([self[key], remove(self, key)]) : O.none()) /** * Maps a `ReadonlyRecord` into another `Record` by applying a transformation function to each of its values. * * @param self - The `ReadonlyRecord` to be mapped. * @param f - A transformation function that will be applied to each of the values in the `ReadonlyRecord`. * * @example * import { map } from "@fp-ts/core/ReadonlyRecord" * * const f = (n: number) => `-${n}` * * assert.deepStrictEqual(map({ a: 3, b: 5 }, f), { a: "-3", b: "-5" }) * * const g = (n: number, key: string) => `${key.toUpperCase()}-${n}` * * assert.deepStrictEqual(map({ a: 3, b: 5 }, g), { a: "A-3", b: "B-5" }) * * @since 1.0.0 */ export const map: { (f: (a: A, key: K) => B): (self: Readonly>) => Record (self: Readonly>, f: (a: A, key: K) => B): Record } = dual( 2, (self: ReadonlyRecord, f: (a: A, key: string) => B): Record => { const out: Record = {} for (const key of Object.keys(self)) { out[key] = f(self[key], key) } return out } ) /** * Transforms a `ReadonlyRecord` into a `Record` by applying the function `f` to each key and value in the original `ReadonlyRecord`. * If the function returns `Some`, the key-value pair is included in the output `Record`. * * @param self - The input `ReadonlyRecord`. * @param f - The transformation function. * * @example * import { filterMap } from '@fp-ts/core/ReadonlyRecord' * import { some, none } from '@fp-ts/core/Option' * * const x = { a: 1, b: 2, c: 3 } * const f = (a: number, key: string) => a > 2 ? some(a * 2) : none() * assert.deepStrictEqual(filterMap(x, f), { c: 6 }) * * @since 1.0.0 */ export const filterMap: { (f: (a: A, key: string) => Option): (self: ReadonlyRecord) => Record (self: ReadonlyRecord, f: (a: A, key: string) => Option): Record } = dual(2, ( self: ReadonlyRecord, f: (a: A, key: string) => Option ): Record => { const out: Record = {} for (const key of Object.keys(self)) { const o = f(self[key], key) if (O.isSome(o)) { out[key] = o.value } } return out }) /** * Selects properties from a record whose values match the given predicate. * * @param self - The `ReadonlyRecord` to filter. * @param predicate - A function that returns a `boolean` value to determine if the entry should be included in the new record. * * @example * import { filter } from '@fp-ts/core/ReadonlyRecord' * * const x = { a: 1, b: 2, c: 3, d: 4 } * assert.deepStrictEqual(filter(x, (n) => n > 2), { c: 3, d: 4 }) * * @category filtering * @since 1.0.0 */ export const filter: { ( refinement: (a: A, key: string) => a is B ): (self: ReadonlyRecord) => Record ( predicate: (a: A, key: string) => boolean ): (self: ReadonlyRecord) => Record ( self: ReadonlyRecord, refinement: (a: A, key: string) => a is B ): Record ( self: ReadonlyRecord, predicate: (a: A, key: string) => boolean ): Record } = dual( 2, ( self: ReadonlyRecord, predicate: (a: A, key: string) => boolean ): Record => { const out: Record = {} for (const key of Object.keys(self)) { if (predicate(self[key], key)) { out[key] = self[key] } } return out } ) /** * Given a `ReadonlyRecord` with `Option` values, returns a `Record` with only the `Some` values, with the same keys. * * @param self - A `ReadonlyRecord` with `Option` values. * * @example * import { compact } from '@fp-ts/core/ReadonlyRecord' * import { some, none } from '@fp-ts/core/Option' * * assert.deepStrictEqual( * compact({ a: some(1), b: none(), c: some(2) }), * { a: 1, c: 2 } * ) * * @category filtering * @since 1.0.0 */ export const compact: (self: ReadonlyRecord>) => Record = filterMap( identity ) /** * Partitions the elements of a `ReadonlyRecord` into two groups: those that match a predicate, and those that don't. * * @param self - The `ReadonlyRecord` to partition. * @param f - The predicate function to apply to each element. * * @example * import { partitionMap } from '@fp-ts/core/ReadonlyRecord' * import { left, right } from '@fp-ts/core/Either' * * const x = { a: 1, b: 2, c: 3 } * const f = (n: number) => (n % 2 === 0 ? right(n) : left(n)) * assert.deepStrictEqual(partitionMap(x, f), [{ a: 1, c: 3 }, { b: 2}]) * * @category filtering * @since 1.0.0 */ export const partitionMap: { ( f: (a: A, key: string) => Either ): (self: ReadonlyRecord) => [Record, Record] ( self: ReadonlyRecord, f: (a: A, key: string) => Either ): [Record, Record] } = dual( 2, ( self: ReadonlyRecord, f: (a: A, key: string) => Either ): [Record, Record] => { const left: Record = {} const right: Record = {} for (const key of Object.keys(self)) { const e = f(self[key], key) if (E.isLeft(e)) { left[key] = e.left } else { right[key] = e.right } } return [left, right] } ) /** * Partitions a `ReadonlyRecord` of `Either` values into two separate records, * one with the `Left` values and one with the `Right` values. * * @param self - the `ReadonlyRecord` to partition. * * @example * import { separate } from '@fp-ts/core/ReadonlyRecord' * import { left, right } from '@fp-ts/core/Either' * * assert.deepStrictEqual( * separate({ a: left("e"), b: right(1) }), * [{ a: "e" }, { b: 1 }] * ) * * @category filtering * @since 1.0.0 */ export const separate: ( self: ReadonlyRecord> ) => [Record, Record] = partitionMap(identity) /** * Partitions a `ReadonlyRecord` into two separate `Record`s based on the result of a predicate function. * * @param self - The input `ReadonlyRecord` to partition. * @param predicate - The partitioning function to determine the partitioning of each value of the `ReadonlyRecord`. * * @example * import { partition } from '@fp-ts/core/ReadonlyRecord' * * assert.deepStrictEqual( * partition({ a: 1, b: 3 }, (n) => n > 2), * [{ a: 1 }, { b: 3 }] * ) * * @category filtering * @since 1.0.0 */ export const partition: { (refinement: (a: A, key: string) => a is B): ( self: ReadonlyRecord ) => [Record, Record] ( predicate: (a: A, key: string) => boolean ): (self: ReadonlyRecord) => [Record, Record] ( self: ReadonlyRecord, refinement: (a: A, key: string) => a is B ): [Record, Record] ( self: ReadonlyRecord, predicate: (a: A, key: string) => boolean ): [Record, Record] } = dual( 2, ( self: ReadonlyRecord, predicate: (a: A, key: string) => boolean ): [Record, Record] => { const left: Record = {} const right: Record = {} for (const key of Object.keys(self)) { if (predicate(self[key], key)) { right[key] = self[key] } else { left[key] = self[key] } } return [left, right] } ) /** * Maps each entry of a `ReadonlyRecord` to an effect and collects the results into a new record. * * @param F - an {@link applicative.Applicative Applicative} instance. * @param self - a `ReadonlyRecord` to map over. * @param f - the mapping function, which maps an entry `a` and its corresponding `key` to an effect. * * @example * import { traverse } from '@fp-ts/core/ReadonlyRecord' * import { some, none, Applicative } from '@fp-ts/core/Option' * * assert.deepStrictEqual( * traverse(Applicative)({ a: 1, b: 2 }, (n: number) => (n <= 2 ? some(n) : none())), * some({ a: 1, b: 2 }) * ) * assert.deepStrictEqual( * traverse(Applicative)({ a: 1, b: 2 }, (n: number) => (n >= 2 ? some(n) : none())), * none() * ) * * @category traversing * @since 1.0.0 */ export const traverse = (F: applicative.Applicative): { ( f: (a: A, key: string) => Kind ): (self: ReadonlyRecord) => Kind> ( self: ReadonlyRecord, f: (a: A, key: string) => Kind ): Kind> } => dual(2, ( self: ReadonlyRecord, f: (a: A, key: string) => Kind ): Kind> => F.map( F.productAll( Object.entries(self).map(([key, a]) => F.map(f(a, key), b => [key, b] as const)) ), Object.fromEntries )) /** * Transforms a `ReadonlyRecord` of `Kind` values into a `Kind` of `Record` values. * * @param F - an {@link applicative.Applicative Applicative} instance. * @param self - the `ReadonlyRecord` of `Kind` values. * * @example * import * as RR from '@fp-ts/core/ReadonlyRecord' * import { some, none, Applicative } from '@fp-ts/core/Option' * * const sequence = RR.sequence(Applicative) * * assert.deepStrictEqual(sequence({ a: some(1), b: some(2) }), some({ a: 1, b: 2 })) * assert.deepStrictEqual(sequence({ a: none(), b: some(2) }), none()) * * @category traversing * @since 1.0.0 */ export const sequence = ( F: applicative.Applicative ): ( self: ReadonlyRecord> ) => Kind> => traverse(F)(identity) const imap = covariant.imap(map) /** * @category instances * @since 1.0.0 */ export const Covariant: covariant.Covariant = { imap, map } /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } /** * @category mapping * @since 1.0.0 */ export const tupled: (self: ReadonlyRecord) => Record = invariant.tupled( Invariant ) /** * @category mapping * @since 1.0.0 */ export const flap: { (self: ReadonlyRecord<(a: A) => B>): (a: A) => Record (a: A, self: ReadonlyRecord<(a: A) => B>): Record } = covariant.flap(Covariant) /** * Maps the success value of this effect to the specified constant value. * * @category mapping * @since 1.0.0 */ export const as: { (b: B): <_>(self: ReadonlyRecord<_>) => Record <_, B>(self: ReadonlyRecord<_>, b: B): Record } = covariant.as(Covariant) /** * @category instances * @since 1.0.0 */ export const Filterable: filterable.Filterable = { partitionMap, filterMap } /** * @category instances * @since 1.0.0 */ export const Traversable: traversable.Traversable = { traverse } /** * @category traversing * @since 1.0.0 */ export const traverseTap: ( F: applicative.Applicative ) => { ( f: (a: A) => Kind ): (self: ReadonlyRecord) => Kind> ( self: ReadonlyRecord, f: (a: A) => Kind ): Kind> } = traversable.traverseTap(Traversable) /** * @category filtering * @since 1.0.0 */ export const traversePartitionMap = ( F: applicative.Applicative ): { ( f: (a: A) => Kind> ): ( self: ReadonlyRecord ) => Kind, Record]> ( self: ReadonlyRecord, f: (a: A) => Kind> ): Kind, Record]> } => dual(2, ( self: ReadonlyRecord, f: (a: A) => Kind> ): Kind, Record]> => { return F.map(traverse(F)(self, f), separate) }) /** * @category filtering * @since 1.0.0 */ export const traverseFilterMap = ( F: applicative.Applicative ): { ( f: (a: A) => Kind> ): (self: ReadonlyRecord) => Kind> ( self: ReadonlyRecord, f: (a: A) => Kind> ): Kind> } => dual(2, ( self: ReadonlyRecord, f: (a: A) => Kind> ): Kind> => { return F.map(traverse(F)(self, f), compact) }) /** * @category instances * @since 1.0.0 */ export const TraversableFilterable: traversableFilterable.TraversableFilterable< ReadonlyRecordTypeLambda > = { traversePartitionMap, traverseFilterMap } /** * Filter values inside a context. * * @since 1.0.0 */ export const traverseFilter: ( F: applicative.Applicative ) => { ( predicate: (a: A) => Kind ): (self: ReadonlyRecord) => Kind> ( self: ReadonlyRecord, predicate: (a: A) => Kind ): Kind> } = traversableFilterable.traverseFilter(TraversableFilterable) /** * @since 1.0.0 */ export const traversePartition: ( F: applicative.Applicative ) => { ( predicate: (a: A) => Kind ): ( self: ReadonlyRecord ) => Kind, Record]> ( self: ReadonlyRecord, predicate: (a: A) => Kind ): Kind, Record]> } = traversableFilterable.traversePartition(TraversableFilterable) ================================================ FILE: src/String.ts ================================================ /** * This module provides utility functions and type class instances for working with the `string` type in TypeScript. * It includes functions for basic string manipulation, as well as type class instances for * `Equivalence`, `Order`, `Semigroup`, and `Monoid`. * * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import * as readonlyArray from "@fp-ts/core/internal/ReadonlyArray" import type { Refinement } from "@fp-ts/core/Predicate" import * as predicate from "@fp-ts/core/Predicate" import type { NonEmptyArray } from "@fp-ts/core/ReadonlyArray" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as order from "@fp-ts/core/typeclass/Order" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * Tests if a value is a `string`. * * @param input - The value to test. * * @example * import { isString } from '@fp-ts/core/String' * * assert.deepStrictEqual(isString("a"), true) * assert.deepStrictEqual(isString(1), false) * * @category guards * @since 1.0.0 */ export const isString: Refinement = predicate.isString /** * @category instances * @since 1.0.0 */ export const Equivalence: equivalence.Equivalence = equivalence.string /** * @category instances * @since 1.0.0 */ export const Order: order.Order = order.string /** * `string` semigroup under concatenation. * * @category instances * @since 1.0.0 */ export const Semigroup: semigroup.Semigroup = semigroup.string /** * `string` monoid under concatenation. * * The `empty` value is `''`. * * @category instances * @since 1.0.0 */ export const Monoid: monoid.Monoid = monoid.string /** * The empty string `""`. * * @since 1.0.0 */ export const empty: "" = "" as const /** * @since 1.0.0 */ export const concat: { (that: string): (self: string) => string (self: string, that: string): string } = dual(2, Semigroup.combine) /** * @example * import * as S from '@fp-ts/core/String' * import { pipe } from '@fp-ts/core/Function' * * assert.deepStrictEqual(pipe('a', S.toUpperCase), 'A') * * @since 1.0.0 */ export const toUpperCase = (self: string): string => self.toUpperCase() /** * @example * import * as S from '@fp-ts/core/String' * import { pipe } from '@fp-ts/core/Function' * * assert.deepStrictEqual(pipe('A', S.toLowerCase), 'a') * * @since 1.0.0 */ export const toLowerCase = (self: string): string => self.toLowerCase() /** * @example * import * as S from '@fp-ts/core/String' * import { pipe } from '@fp-ts/core/Function' * * assert.deepStrictEqual(pipe('abc', S.replace('b', 'd')), 'adc') * * @since 1.0.0 */ export const replace: { (searchValue: string | RegExp, replaceValue: string): (self: string) => string (self: string, searchValue: string | RegExp, replaceValue: string): string } = dual( 3, (self: string, searchValue: string | RegExp, replaceValue: string): string => self.replace(searchValue, replaceValue) ) /** * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.trim(' a '), 'a') * * @since 1.0.0 */ export const trim = (self: string): string => self.trim() /** * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.trimStart(' a '), 'a ') * * @since 1.0.0 */ export const trimStart = (self: string): string => self.trimStart() /** * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.trimEnd(' a '), ' a') * * @since 1.0.0 */ export const trimEnd = (self: string): string => self.trimEnd() /** * @example * import * as S from '@fp-ts/core/String' * import { pipe } from '@fp-ts/core/Function' * * assert.deepStrictEqual(pipe('abcd', S.slice(1, 3)), 'bc') * * @since 1.0.0 */ export const slice: { (start: number, end: number): (self: string) => string (self: string, start: number, end: number): string } = dual(3, (self: string, start: number, end: number): string => self.slice(start, end)) /** * Test whether a `string` is empty. * * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.isEmpty(''), true) * assert.deepStrictEqual(S.isEmpty('a'), false) * * @since 1.0.0 */ export const isEmpty = (self: string): self is "" => self.length === 0 /** * Test whether a `string` is non empty. * * @since 1.0.0 */ export const isNonEmpty = (self: string): boolean => self.length > 0 /** * Calculate the number of characters in a `string`. * * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.length('abc'), 3) * * @since 1.0.0 */ export const length = (self: string): number => self.length /** * @example * import * as S from '@fp-ts/core/String' * import { pipe } from '@fp-ts/core/Function' * * assert.deepStrictEqual(pipe('abc', S.split('')), ['a', 'b', 'c']) * assert.deepStrictEqual(pipe('', S.split('')), ['']) * * @since 1.0.0 */ export const split: { (separator: string | RegExp): (self: string) => NonEmptyArray (self: string, separator: string | RegExp): NonEmptyArray } = dual(2, (self: string, separator: string | RegExp): NonEmptyArray => { const out = self.split(separator) return readonlyArray.isNonEmptyArray(out) ? out : [self] }) /** * Returns `true` if `searchString` appears as a substring of `self`, at one or more positions that are * greater than or equal to `0`; otherwise, returns `false`. * * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.includes("abc", "b"), true) * assert.deepStrictEqual(S.includes("abc", "d"), false) * * @since 1.0.0 */ export const includes: { (searchString: string): (self: string) => boolean (self: string, searchString: string): boolean } = dual(2, (self: string, searchString: string): boolean => self.includes(searchString)) /** * Returns `true` if `searchString` appears as a substring of `self`, at one or more positions that are * greater than or equal to `position`; otherwise, returns `false`. * * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.includesWithPosition("abc", "b", 1), true) * assert.deepStrictEqual(S.includesWithPosition("abc", "a", 1), false) * * @since 1.0.0 */ export const includesWithPosition: { (searchString: string, position: number): (self: string) => boolean (self: string, searchString: string, position: number): boolean } = dual( 3, (self: string, searchString: string, position: number): boolean => self.includes(searchString, position) ) /** * Returns `true` if the sequence of elements of `searchString` is the * same as the corresponding elements of `s` starting at * position. Otherwise returns false. * * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.startsWith("abc", "a"), true) * assert.deepStrictEqual(S.startsWith("bc", "a"), false) * * @since 1.0.0 */ export const startsWith: { (searchString: string): (self: string) => boolean (self: string, searchString: string): boolean } = dual( 2, (self: string, searchString: string): boolean => self.startsWith(searchString) ) /** * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.startsWithPosition("abc", "b", 1), true) * assert.deepStrictEqual(S.startsWithPosition("bc", "a", 1), false) * * @since 1.0.0 */ export const startsWithPosition: { (searchString: string, position: number): (self: string) => boolean (self: string, searchString: string, position: number): boolean } = dual( 3, (self: string, searchString: string, position: number): boolean => self.startsWith(searchString, position) ) /** * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.endsWith("abc", "c"), true) * assert.deepStrictEqual(S.endsWith("ab", "c"), false) * * @since 1.0.0 */ export const endsWith: { (searchString: string): (self: string) => boolean (self: string, searchString: string): boolean } = dual(2, (self: string, searchString: string): boolean => self.endsWith(searchString)) /** * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.endsWithPosition("abc", "b", 2), true) * assert.deepStrictEqual(S.endsWithPosition("abc", "c", 2), false) * * @since 1.0.0 */ export const endsWithPosition: { (searchString: string, position: number): (self: string) => boolean (self: string, searchString: string, position: number): boolean } = dual( 3, (self: string, searchString: string, position: number): boolean => self.endsWith(searchString, position) ) /** * Keep the specified number of characters from the start of a string. * * If `n` is larger than the available number of characters, the string will * be returned whole. * * If `n` is not a positive number, an empty string will be returned. * * If `n` is a float, it will be rounded down to the nearest integer. * * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.takeLeft("Hello World", 5), "Hello") * * @since 1.0.0 */ export const takeLeft: { (n: number): (self: string) => string (self: string, n: number): string } = dual(2, (self: string, n: number): string => self.slice(0, Math.max(n, 0))) /** * Keep the specified number of characters from the end of a string. * * If `n` is larger than the available number of characters, the string will * be returned whole. * * If `n` is not a positive number, an empty string will be returned. * * If `n` is a float, it will be rounded down to the nearest integer. * * @example * import * as S from '@fp-ts/core/String' * * assert.deepStrictEqual(S.takeRight("Hello World", 5), "World") * * @since 1.0.0 */ export const takeRight: { (n: number): (self: string) => string (self: string, n: number): string } = dual( 2, (self: string, n: number): string => self.slice(Math.max(0, self.length - Math.floor(n)), Infinity) ) /* Missing: - charCodeAt - substring - at - charAt - codePointAt - indexOf - lastIndexOf - localeCompare - match - matchAll - normalize - padEnd - padStart - repeat - replaceAll - search - toLocaleLowerCase - toLocaleUpperCase */ // TODO: 100% coverage tests (ask Max) // const CR = 0x0d // const LF = 0x0a // /** // * Returns an `IterableIterator` which yields each line contained within the // * string, trimming off the trailing newline character. // * // * @since 1.0.0 // */ // // export const linesIterator = (self: string): LinesIterator => linesSeparated(self, true) // /** // * Returns an `IterableIterator` which yields each line contained within the // * string as well as the trailing newline character. // * // * @since 1.0.0 // */ // export const linesWithSeparators = (s: string): LinesIterator => linesSeparated(s, false) // /** // * For every line in this string, strip a leading prefix consisting of blanks // * or control characters followed by the character specified by `marginChar` // * from the line. // * // * @since 1.0.0 // */ // export const stripMarginWith = (marginChar: string) => // (self: string): string => { // let out = "" // for (const line of linesWithSeparators(self)) { // let index = 0 // while (index < line.length && line.charAt(index) <= " ") { // index = index + 1 // } // const stripped = index < line.length && line.charAt(index) === marginChar // ? line.substring(index + 1) // : line // out = out + stripped // } // return out // } // /** // * For every line in this string, strip a leading prefix consisting of blanks // * or control characters followed by the `"|"` character from the line. // * // * @since 1.0.0 // */ // export const stripMargin = (self: string): string => stripMarginWith("|")(self) // class LinesIterator implements IterableIterator { // private index: number // private readonly length: number // constructor(readonly s: string, readonly stripped: boolean = false) { // this.index = 0 // this.length = s.length // } // next(): IteratorResult { // if (this.done) { // return { done: true, value: undefined } // } // const start = this.index // while (!this.done && !isLineBreak(this.s[this.index]!)) { // this.index = this.index + 1 // } // let end = this.index // if (!this.done) { // const char = this.s[this.index]! // this.index = this.index + 1 // if (!this.done && isLineBreak2(char, this.s[this.index]!)) { // this.index = this.index + 1 // } // if (!this.stripped) { // end = this.index // } // } // return { done: false, value: this.s.substring(start, end) } // } // [Symbol.iterator](): IterableIterator { // return new LinesIterator(this.s, this.stripped) // } // private get done(): boolean { // return this.index >= this.length // } // } // /** // * Test if the provided character is a line break character (i.e. either `"\r"` // * or `"\n"`). // */ // const isLineBreak = (char: string): boolean => { // const code = char.charCodeAt(0) // return code === CR || code === LF // } // /** // * Test if the provided characters combine to form a carriage return/line-feed // * (i.e. `"\r\n"`). // */ // const isLineBreak2 = (char0: string, char1: string): boolean => // char0.charCodeAt(0) === CR && char1.charCodeAt(0) === LF // const linesSeparated = (self: string, stripped: boolean): LinesIterator => // new LinesIterator(self, stripped) ================================================ FILE: src/Struct.ts ================================================ /** * This module provides utility functions for working with structs in TypeScript. * * @since 1.0.0 */ import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as order from "@fp-ts/core/typeclass/Order" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * Create a new object by picking properties of an existing object. * * @example * import { pick } from "@fp-ts/core/Struct" * import { pipe } from "@fp-ts/core/Function" * * assert.deepStrictEqual(pipe({ a: "a", b: 1, c: true }, pick("a", "b")), { a: "a", b: 1 }) * * @since 1.0.0 */ export const pick = ]>( ...keys: Keys ) => (s: S): { [K in Keys[number]]: S[K] } => { const out: any = {} for (const k of keys) { out[k] = s[k] } return out } /** * Create a new object by omitting properties of an existing object. * * @example * import { omit } from "@fp-ts/core/Struct" * import { pipe } from "@fp-ts/core/Function" * * assert.deepStrictEqual(pipe({ a: "a", b: 1, c: true }, omit("c")), { a: "a", b: 1 }) * * @since 1.0.0 */ export const omit = ]>( ...keys: Keys ) => (s: S): { [K in Exclude]: S[K] } => { const out: any = { ...s } for (const k of keys) { delete out[k] } return out } /** * Given a struct of `Equivalence`s returns a new `Equivalence` that compares values of a struct * by applying each `Equivalence` to the corresponding property of the struct. * * Alias of {@link equivalence.struct}. * * @example * import { getEquivalence } from "@fp-ts/core/Struct" * import * as S from "@fp-ts/core/String" * import * as N from "@fp-ts/core/Number" * * const PersonEquivalence = getEquivalence({ * name: S.Equivalence, * age: N.Equivalence * }) * * assert.deepStrictEqual( * PersonEquivalence({ name: "John", age: 25 }, { name: "John", age: 25 }), * true * ) * assert.deepStrictEqual( * PersonEquivalence({ name: "John", age: 25 }, { name: "John", age: 40 }), * false * ) * * @category combinators * @since 1.0.0 */ export const getEquivalence: >>( predicates: R ) => equivalence.Equivalence< { readonly [K in keyof R]: [R[K]] extends [equivalence.Equivalence] ? A : never } > = equivalence.struct /** * This function creates and returns a new `Order` for a struct of values based on the given `Order`s * for each property in the struct. * * Alias of {@link order.struct}. * * @category combinators * @since 1.0.0 */ export const getOrder: }>( fields: R ) => order.Order<{ [K in keyof R]: [R[K]] extends [order.Order] ? A : never }> = order.struct /** * This function creates and returns a new `Semigroup` for a struct of values based on the given `Semigroup`s for each property in the struct. * The returned `Semigroup` combines two structs of the same type by applying the corresponding `Semigroup` passed as arguments to each property in the struct. * * It is useful when you need to combine two structs of the same type and you have a specific way of combining each property of the struct. * * See also {@link getMonoid}. * * @example * import { getSemigroup } from "@fp-ts/core/Struct" * import * as Semigroup from "@fp-ts/core/typeclass/Semigroup" * import * as O from "@fp-ts/core/Option" * * const PersonSemigroup = getSemigroup({ * name: Semigroup.last(), * age: O.getOptionalMonoid(Semigroup.last()) * }) * * assert.deepStrictEqual( * PersonSemigroup.combine({ name: "John", age: O.none() }, { name: "John", age: O.some(25) }), * { name: "John", age: O.some(25) } * ) * assert.deepStrictEqual( * PersonSemigroup.combine({ name: "John", age: O.some(25) }, { name: "John", age: O.none() }), * { name: "John", age: O.some(25) } * ) * * @category combinators * @since 1.0.0 */ export const getSemigroup: }>( fields: R ) => semigroup.Semigroup< { [K in keyof R]: [R[K]] extends [semigroup.Semigroup] ? A : never } > = semigroup.struct /** * This function creates and returns a new `Monoid` for a struct of values based on the given `Monoid`s for each property in the struct. * The returned `Monoid` combines two structs of the same type by applying the corresponding `Monoid` passed as arguments to each property in the struct. * * The `empty` value of the returned `Monoid` is a struct where each property is the `empty` value of the corresponding `Monoid` in the input `monoids` object. * * It is useful when you need to combine two structs of the same type and you have a specific way of combining each property of the struct. * * See also {@link getSemigroup}. * * @category combinators * @since 1.0.0 */ export const getMonoid: }>( fields: R ) => monoid.Monoid<{ [K in keyof R]: [R[K]] extends [monoid.Monoid] ? A : never }> = monoid.struct ================================================ FILE: src/Symbol.ts ================================================ /** * @since 1.0.0 */ import * as predicate from "@fp-ts/core/Predicate" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" /** * Tests if a value is a `symbol`. * * @param input - The value to test. * * @example * import { isSymbol } from "@fp-ts/core/Predicate" * * assert.deepStrictEqual(isSymbol(Symbol.for("a")), true) * assert.deepStrictEqual(isSymbol("a"), false) * * @category guards * @since 1.0.0 */ export const isSymbol: (u: unknown) => u is symbol = predicate.isSymbol /** * @category instances * @since 1.0.0 */ export const Equivalence: equivalence.Equivalence = equivalence.symbol ================================================ FILE: src/These.ts ================================================ /** * @since 1.0.0 */ import type { Either, Left, Right } from "@fp-ts/core/Either" import * as E from "@fp-ts/core/Either" import type { LazyArg } from "@fp-ts/core/Function" import { constNull, constUndefined, dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import { proto, structural } from "@fp-ts/core/internal/effect" import * as N from "@fp-ts/core/Number" import * as O from "@fp-ts/core/Option" import type { Option } from "@fp-ts/core/Option" import type { Predicate, Refinement } from "@fp-ts/core/Predicate" import type { NonEmptyReadonlyArray } from "@fp-ts/core/ReadonlyArray" import * as RA from "@fp-ts/core/ReadonlyArray" import * as applicative from "@fp-ts/core/typeclass/Applicative" import * as bicovariant from "@fp-ts/core/typeclass/Bicovariant" import * as chainable from "@fp-ts/core/typeclass/Chainable" import * as covariant from "@fp-ts/core/typeclass/Covariant" import type { Equivalence } from "@fp-ts/core/typeclass/Equivalence" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as flatMap_ from "@fp-ts/core/typeclass/FlatMap" import type * as foldable from "@fp-ts/core/typeclass/Foldable" import * as invariant from "@fp-ts/core/typeclass/Invariant" import type * as monad from "@fp-ts/core/typeclass/Monad" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import * as of_ from "@fp-ts/core/typeclass/Of" import type * as pointed from "@fp-ts/core/typeclass/Pointed" import * as product_ from "@fp-ts/core/typeclass/Product" import type * as semiAlternative from "@fp-ts/core/typeclass/SemiAlternative" import * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" import * as traversable from "@fp-ts/core/typeclass/Traversable" /** * @category model * @since 1.0.0 */ export interface Both { readonly _tag: "Both" readonly left: E readonly right: A } /** * @category model * @since 1.0.0 */ export type These = Either | Both /** * @category model * @since 1.0.0 */ export type Validated = These, A> /** * @category type lambdas * @since 1.0.0 */ export interface TheseTypeLambda extends TypeLambda { readonly type: These } /** * @category type lambdas * @since 3.0.0 */ export interface ValidatedTypeLambda extends TypeLambda { readonly type: Validated } /** * @category constructors * @since 1.0.0 */ export const left: (left: E) => These = E.left /** * @category constructors * @since 1.0.0 */ export const right: (right: A) => These = E.right /** * Alias of {@link right}. * * @category constructors * @since 1.0.0 */ export const of: (right: A) => These = right /** * @category constructors * @since 1.0.0 */ export const both = (left: E, right: A): These => Object.setPrototypeOf({ _tag: "Both", left, right }, proto) /** * @category constructors * @since 1.0.0 */ export const leftOrBoth: { (onSome: LazyArg): (self: Option) => These (self: Option, onSome: LazyArg): These } = dual( 2, (self: Option, onSome: LazyArg): These => O.isNone(self) ? left(onSome()) : both(onSome(), self.value) ) /** * @category constructors * @since 1.0.0 */ export const rightOrBoth: { (onNone: LazyArg): (self: Option) => These (self: Option, onNone: LazyArg): These } = dual( 2, (self: Option, onNone: LazyArg): These => O.isNone(self) ? right(onNone()) : both(self.value, onNone()) ) /** * @category constructors * @since 1.0.0 */ export const fail = (e: E): Validated => left([e]) /** * @category constructors * @since 1.0.0 */ export const warn = (e: E, a: A): Validated => both([e], a) // ------------------------------------------------------------------------------------- // equivalence // ------------------------------------------------------------------------------------- /** * @category equivalence * @since 1.0.0 */ export const getEquivalence = ( EE: Equivalence, EA: Equivalence ): Equivalence> => equivalence.make((x, y) => isLeft(x) ? isLeft(y) && EE(x.left, y.left) : isRight(x) ? isRight(y) && EA(x.right, y.right) : isBoth(y) && EE(x.left, y.left) && EA(x.right, y.right) ) /** * @category pattern matching * @since 1.0.0 */ export const match: { ( onLeft: (e: E) => B, onRight: (a: A) => C, onBoth: (e: E, a: A) => D ): (self: These) => B | C | D ( self: These, onLeft: (e: E) => B, onRight: (a: A) => C, onBoth: (e: E, a: A) => D ): B | C | D } = dual(4, ( self: These, onLeft: (e: E) => B, onRight: (a: A) => C, onBoth: (e: E, a: A) => D ): B | C | D => { switch (self._tag) { case "Left": return onLeft(self.left) case "Right": return onRight(self.right) case "Both": return onBoth(self.left, self.right) } }) /** * @since 1.0.0 */ export const reverse: (self: These) => These = match( right, left, (e, a) => both(a, e) ) // ------------------------------------------------------------------------------------- // guards // ------------------------------------------------------------------------------------- /** * Tests if a value is a `These`. * * @param input - The value to check. * * @category guards * @since 1.0.0 */ export const isThese = (input: unknown): input is These => typeof input === "object" && input != null && structural in input && "_tag" in input && (input["_tag"] === "Left" || input["_tag"] === "Right" || input["_tag"] === "Both") /** * Determine if a `These` is a `Left`. * * @param self - The `These` to check. * * @example * import { isLeft, left, right, both } from '@fp-ts/core/These' * * assert.deepStrictEqual(isLeft(right(1)), false) * assert.deepStrictEqual(isLeft(left("error")), true) * assert.deepStrictEqual(isLeft(both("error", 1)), false) * * @category guards * @since 1.0.0 */ export const isLeft = (self: These): self is Left => self._tag === "Left" /** * Determine if a `These` is a `Left` or a `Both`. * * @param self - The `These` to check. * * @example * import { isLeftOrBoth, left, right, both } from '@fp-ts/core/These' * * assert.deepStrictEqual(isLeftOrBoth(right(1)), false) * assert.deepStrictEqual(isLeftOrBoth(left("error")), true) * assert.deepStrictEqual(isLeftOrBoth(both("error", 1)), true) * * @category guards * @since 1.0.0 */ export const isLeftOrBoth = (self: These): self is Left | Both => self._tag !== "Right" /** * Determine if a `These` is a `Right`. * * @param self - The `These` to check. * * @example * import { isRight, left, right, both } from '@fp-ts/core/These' * * assert.deepStrictEqual(isRight(right(1)), true) * assert.deepStrictEqual(isRight(left("error")), false) * assert.deepStrictEqual(isRight(both("error", 1)), false) * * @category guards * @since 1.0.0 */ export const isRight = (self: These): self is Right => self._tag === "Right" /** * Determine if a `These` is a `Right` or a `Both`. * * @param self - The `These` to check. * * @example * import { isRightOrBoth, left, right, both } from '@fp-ts/core/These' * * assert.deepStrictEqual(isRightOrBoth(right(1)), true) * assert.deepStrictEqual(isRightOrBoth(left("error")), false) * assert.deepStrictEqual(isRightOrBoth(both("error", 1)), true) * * @category guards * @since 1.0.0 */ export const isRightOrBoth = (self: These): self is Right | Both => self._tag !== "Left" /** * Determine if a `These` is a `Both`. * * @param self - The `These` to check. * * @example * import { isBoth, left, right, both } from '@fp-ts/core/These' * * assert.deepStrictEqual(isBoth(right(1)), false) * assert.deepStrictEqual(isBoth(left("error")), false) * assert.deepStrictEqual(isBoth(both("error", 1)), true) * * @category guards * @since 1.0.0 */ export const isBoth = (self: These): self is Both => self._tag === "Both" /** * Lifts a function that may throw to one returning a `These`. * * @category interop * @since 1.0.0 */ export const liftThrowable: , B, E>( f: (...a: A) => B, onThrow: (error: unknown) => E ) => ((...a: A) => These) = E.liftThrowable /** * Extracts the value of a `These` or throws if the `These` is `Left`. * * If a default error is sufficient for your use case and you don't need to configure the thrown error, see {@link getOrThrow}. * * @param self - The `These` to extract the value from. * @param onLeft - A function that will be called if the `These` is `Left`. It returns the error to be thrown. * * @example * import * as E from "@fp-ts/core/These" * * assert.deepStrictEqual( * E.getOrThrowWith(E.right(1), () => new Error('Unexpected Left')), * 1 * ) * assert.deepStrictEqual( * E.getOrThrowWith(E.both("warning", 1), () => new Error('Unexpected Left')), * 1 * ) * assert.throws(() => E.getOrThrowWith(E.left("error"), () => new Error('Unexpected Left'))) * * @category interop * @since 1.0.0 */ export const getOrThrowWith: { (onLeft: (e: E) => unknown): (self: These) => A (self: These, onLeft: (e: E) => unknown): A } = dual(2, (self: These, onLeft: (e: E) => unknown): A => { if (isRightOrBoth(self)) { return self.right } throw onLeft(self.left) }) /** * Extracts the value of a `These` or throws if the `These` is `Left`. * * The thrown error is a default error. To configure the error thrown, see {@link getOrThrowWith}. * * @param self - The `These` to extract the value from. * @throws `Error("getOrThrow called on a Left")` * * @example * import * as T from "@fp-ts/core/These" * * assert.deepStrictEqual(T.getOrThrow(T.right(1)), 1) * assert.deepStrictEqual(T.getOrThrow(T.both("warning", 1)), 1) * assert.throws(() => T.getOrThrow(T.left("error"))) * * @category interop * @since 1.0.0 */ export const getOrThrow: (self: These) => A = getOrThrowWith(() => new Error("getOrThrow called on a Left") ) /** * Extracts the value of a `These` or throws if the `These` is `Left`. * * If a default error is sufficient for your use case and you don't need to configure the thrown error, see {@link getOrThrow}. * * @param self - The `These` to extract the value from. * @param onLeft - A function that will be called if the `These` is `Left`. It returns the error to be thrown. * * @example * import * as E from "@fp-ts/core/These" * * assert.deepStrictEqual( * E.getRightOnlyOrThrowWith( * E.right(1), * () => new Error("Unexpected Left or Both") * ), * 1 * ) * assert.throws(() => E.getRightOnlyOrThrowWith(E.both("warning", 1), () => new Error("Unexpected Left or Both"))) * assert.throws(() => E.getRightOnlyOrThrowWith(E.left("error"), () => new Error("Unexpected Left or Both"))) * * @category interop * @since 1.0.0 */ export const getRightOnlyOrThrowWith: { (onLeftOrBoth: (e: E) => unknown): (self: These) => A (self: These, onLeftOrBoth: (e: E) => unknown): A } = dual(2, (self: These, onLeftOrBoth: (e: E) => unknown): A => { if (isRight(self)) { return self.right } throw onLeftOrBoth(self.left) }) /** * Extracts the value of a `These` or throws if the `These` is not a `Right`. * * The thrown error is a default error. To configure the error thrown, see {@link getRightOnlyOrThrowWith}. * * @param self - The `These` to extract the value from. * @throws `Error("getOrThrow called on a Left")` * * @example * import * as T from "@fp-ts/core/These" * * assert.deepStrictEqual(T.getRightOnlyOrThrow(T.right(1)), 1) * assert.throws(() => T.getRightOnlyOrThrow(T.both("error", 1))) * assert.throws(() => T.getRightOnlyOrThrow(T.left("error"))) * * @category interop * @since 1.0.0 */ export const getRightOnlyOrThrow: (self: These) => A = getRightOnlyOrThrowWith(() => new Error("getRightOnlyOrThrow called on a Left or a Both") ) /** * @category conversions * @since 1.0.0 */ export const fromNullable: { (onNullable: LazyArg): (a: A) => These> (a: A, onNullable: LazyArg): These> } = dual( 2, (a: A, onNullable: LazyArg): These> => a == null ? left(onNullable()) : right(a as NonNullable) ) /** * @category conversions * @since 1.0.0 */ export const fromEither = (self: Either): Validated => E.isLeft(self) ? left([self.left]) : self /** * @category conversions * @since 1.0.0 */ export const toEither: { (onBoth: (e: E, a: A) => Either): (self: These) => Either (self: These, onBoth: (e: E, a: A) => Either): Either } = dual( 2, (self: These, onBoth: (e: E, a: A) => Either): Either => isBoth(self) ? onBoth(self.left, self.right) : self ) /** * @category conversions * @since 1.0.0 */ export const absolve: (self: These) => Either = toEither(( _, a ) => E.right(a)) /** * @category conversions * @since 1.0.0 */ export const condemn: (self: These) => Either = toEither(( e, _ ) => E.left(e)) /** * @category lifting * @since 1.0.0 */ export const liftNullable = , B, E>( f: (...a: A) => B | null | undefined, onNullable: (...a: A) => E ) => (...a: A): These> => fromNullable(() => onNullable(...a))(f(...a)) /** * @category combining * @since 1.0.0 */ export const flatMapNullable: { ( f: (a: A) => B | null | undefined, onNullable: (a: A) => E2 ): (self: Validated) => Validated> ( self: Validated, f: (a: A) => B | null | undefined, onNullable: (a: A) => E2 ): Validated> } = dual(3, ( self: Validated, f: (a: A) => B | null | undefined, onNullable: (a: A) => E2 ): Validated> => flatMap(self, liftNullable(f, (a) => [onNullable(a)]))) /** * @category lifting * @since 1.0.0 */ export const liftPredicate: { ( refinement: Refinement, onFalse: (c: C) => E ): (c: C) => These (predicate: Predicate, onFalse: (b: B) => E): (b: B) => These } = (predicate: Predicate, onFalse: (b: B) => E) => (b: B) => predicate(b) ? right(b) : left(onFalse(b)) /** * @category conversions * @since 1.0.0 */ export const fromIterable: { (onEmpty: LazyArg): (collection: Iterable) => These (collection: Iterable, onEmpty: LazyArg): These } = dual(2, (collection: Iterable, onEmpty: LazyArg): These => { for (const a of collection) { return right(a) } return left(onEmpty()) }) /** * @category conversions * @since 1.0.0 */ export const fromOption: { (onNone: LazyArg): (self: Option) => These (self: Option, onNone: LazyArg): These } = dual( 2, (self: Option, onNone: LazyArg): These => O.isNone(self) ? left(onNone()) : right(self.value) ) /** * @category conversions * @since 1.0.0 */ export const fromTuple = (self: readonly [E, A]): These => both(self[0], self[1]) /** * @category lifting * @since 1.0.0 */ export const liftOption = , B, E>( f: (...a: A) => Option, onNone: (...a: A) => E ) => (...a: A): These => fromOption(() => onNone(...a))(f(...a)) /** * @category lifting * @since 1.0.0 */ export const liftEither = , E, B>( f: (...a: A) => Either ) => (...a: A): Validated => fromEither(f(...a)) /** * @category lifting * @since 1.0.0 */ export const liftThese = , E, B>( f: (...a: A) => These ) => (...a: A): Validated => toValidated(f(...a)) /** * @category combining * @since 1.0.0 */ export const flatMapOption: { ( f: (a: A) => Option, onNone: (a: A) => E2 ): (self: Validated) => Validated ( self: Validated, f: (a: A) => Option, onNone: (a: A) => E2 ): Validated } = dual(3, ( self: Validated, f: (a: A) => Option, onNone: (a: A) => E2 ): Validated => flatMap(self, liftOption(f, (a) => [onNone(a)]))) /** * @category combining * @since 1.0.0 */ export const flatMapEither: { (f: (a: A) => Either): (self: Validated) => Validated (self: Validated, f: (a: A) => Either): Validated } = dual( 2, (self: Validated, f: (a: A) => Either): Validated => flatMap(self, liftEither(f)) ) /** * @category combining * @since 1.0.0 */ export const flatMapThese: { (f: (a: A) => These): (self: Validated) => Validated (self: Validated, f: (a: A) => These): Validated } = dual( 2, (self: Validated, f: (a: A) => These): Validated => flatMap(self, liftThese(f)) ) /** * Converts a `These` to an `Option` discarding the error (`Both` included). * * @category getters * @since 1.0.0 */ export const getRight = ( self: These ): Option => isLeft(self) ? O.none() : O.some(self.right) /** * Returns the value if and only if the value is a `Right` (i.e. `Both` is excluded). * * @category getters * @since 1.0.0 */ export const getRightOnly = ( self: These ): Option => isRight(self) ? O.some(self.right) : O.none() /** * Converts a `These` to an `Option` discarding the value (`Both` included). * * @category getters * @since 1.0.0 */ export const getLeft = ( self: These ): Option => isRight(self) ? O.none() : O.some(self.left) /** * Returns the error if and only if the value is a `Left` (i.e. `Both` is excluded). * * @category getters * @since 1.0.0 */ export const getLeftOnly = ( self: These ): Option => isLeft(self) ? O.some(self.left) : O.none() /** * @category getters * @since 1.0.0 */ export const getBoth = ( self: These ): Option => isBoth(self) ? O.some([self.left, self.right]) : O.none() /** * @category getters * @since 1.0.0 */ export const getBothOrElse: { (e: LazyArg, a: LazyArg): (self: These) => [E, A] (self: These, e: LazyArg, a: LazyArg): [E, A] } = dual(3, (self: These, e: LazyArg, a: LazyArg): [E, A] => isLeft(self) ? [self.left, a()] : isRight(self) ? [e(), self.right] : [self.left, self.right]) /** * @category getters * @since 1.0.0 */ export const getOrElse: { (onLeft: LazyArg): (self: These) => A | B (self: These, onLeft: LazyArg): A | B } = dual( 2, (self: These, onLeft: LazyArg): A | B => isLeft(self) ? onLeft() : self.right ) /** * @category getters * @since 1.0.0 */ export const getOrNull: (self: These) => A | null = getOrElse(constNull) /** * @category getters * @since 1.0.0 */ export const getOrUndefined: (self: These) => A | undefined = getOrElse(constUndefined) /** * @category debugging * @since 1.0.0 */ export const inspectRight: { (onRight: (a: A) => void): (self: These) => These (self: These, onRight: (a: A) => void): These } = dual(2, (self: These, onRight: (a: A) => void): These => { if (isRight(self)) { onRight(self.right) } return self }) /** * @category debugging * @since 1.0.0 */ export const inspectRightOrBoth: { (onRightOrBoth: (a: A) => void): (self: These) => These (self: These, onRightOrBoth: (a: A) => void): These } = dual(2, (self: These, onRightOrBoth: (a: A) => void): These => { if (isRightOrBoth(self)) { onRightOrBoth(self.right) } return self }) /** * @category debugging * @since 1.0.0 */ export const inspectLeft: { (onLeft: (e: E) => void): (self: These) => These (self: These, onLeft: (e: E) => void): These } = dual(2, (self: These, onLeft: (e: E) => void): These => { if (isLeft(self)) { onLeft(self.left) } return self }) /** * @category debugging * @since 1.0.0 */ export const inspectBoth: { (onBoth: (e: E, a: A) => void): (self: These) => These (self: These, onBoth: (e: E, a: A) => void): These } = dual(2, (self: These, onBoth: (e: E, a: A) => void): These => { if (isBoth(self)) { onBoth(self.left, self.right) } return self }) /** * @category mapping * @since 1.0.0 */ export const bimap: { (f: (e: E1) => E2, g: (a: A) => B): (self: These) => These (self: These, f: (e: E1) => E2, g: (a: A) => B): These } = dual( 3, (self: These, f: (e: E1) => E2, g: (a: A) => B): These => isLeft(self) ? left(f(self.left)) : isRight(self) ? right(g(self.right)) : both(f(self.left), g(self.right)) ) /** * @category instances * @since 1.0.0 */ export const Bicovariant: bicovariant.Bicovariant = { bimap } /** * Maps the `Left` side of an `These` value to a new `These` value. * * @param self - The input `These` value to map. * @param f - A transformation function to apply to the `Left` value of the input `These`. * * @category error handling * @since 1.0.0 */ export const mapLeft: { (f: (e: E) => G): (self: These) => These (self: These, f: (e: E) => G): These } = bicovariant.mapLeft(Bicovariant) /** * @category conversions * @since 1.0.0 */ export const toValidated: (self: These) => Validated = mapLeft((e) => [e]) /** * Maps the `Right` side of an `These` value to a new `These` value. * * @param self - An `These` to map * @param f - The function to map over the value of the `These` * * @category mapping * @since 1.0.0 */ export const map: { (self: These, f: (a: A) => B): These (f: (a: A) => B): (self: These) => These } = bicovariant.map(Bicovariant) const imap = covariant.imap(map) /** * @category instances * @since 1.0.0 */ export const Covariant: covariant.Covariant = { imap, map } /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } /** * @category mapping * @since 1.0.0 */ export const tupled: (self: These) => These = invariant.tupled( Invariant ) /** * @category mapping * @since 1.0.0 */ export const flap: { (a: A, self: These B>): These (self: These B>): (a: A) => These } = covariant.flap(Covariant) /** * Maps the right value of this effect to the specified constant value. * * @category mapping * @since 1.0.0 */ export const as: { (self: These, b: B): These (b: B): (self: These) => These } = covariant.as(Covariant) /** * Returns the effect resulting from mapping the right of this effect to unit. * * @category mapping * @since 1.0.0 */ export const asUnit: (self: These) => These = covariant.asUnit(Covariant) /** * @category instances * @since 1.0.0 */ export const Of: of_.Of = { of } /** * @since 1.0.0 */ export const unit: These = of_.unit(Of) /** * @category instances * @since 1.0.0 */ export const Pointed: pointed.Pointed = { of, imap, map } /** * @category traversing * @since 1.0.0 */ export const traverse = ( F: applicative.Applicative ): { ( f: (a: A) => Kind ): (self: These) => Kind> ( self: These, f: (a: A) => Kind ): Kind> } => dual(2, ( self: These, f: (a: A) => Kind ): Kind> => isLeft(self) ? F.of>(self) : isRight(self) ? F.map>(f(self.right), right) : F.map(f(self.right), (b) => both(self.left, b))) /** * @category instances * @since 1.0.0 */ export const Traversable: traversable.Traversable = { traverse } /** * @category traversing * @since 1.0.0 */ export const sequence: ( F: applicative.Applicative ) => ( self: These> ) => Kind> = traversable.sequence(Traversable) /** * @category traversing * @since 1.0.0 */ export const traverseTap: ( F: applicative.Applicative ) => { ( self: These, f: (a: A) => Kind ): Kind> ( f: (a: A) => Kind ): (self: These) => Kind> } = traversable.traverseTap(Traversable) /** * Returns a function that checks if a `These` contains a given value using a provided `equivalence` function. * * @since 1.0.0 */ export const contains = (isEquivalent: (self: A, that: A) => boolean): { (a: A): (self: These) => boolean (self: These, a: A): boolean } => dual( 2, (self: These, a: A): boolean => isLeft(self) ? false : isEquivalent(self.right, a) ) /** * @category predicates * @since 1.0.0 */ export const exists: { (predicate: Predicate): (self: These) => boolean (self: These, predicate: Predicate): boolean } = dual( 2, (self: These, predicate: Predicate): boolean => isLeft(self) ? false : predicate(self.right) ) /** * @category instances * @since 1.0.0 */ export const Foldable: foldable.Foldable = { reduce: dual( 3, (self: These, b: B, f: (b: B, a: A) => B): B => isLeft(self) ? b : f(b, self.right) ) } /** * Executes this effect and returns its value, if it succeeds, but otherwise * executes the specified effect. * * @category error handling * @since 1.0.0 */ export const orElse: { (that: (e1: E1) => These): (self: These) => These (self: These, that: (e1: E1) => These): These } = dual( 2, (self: These, that: (e1: E1) => These): These => isLeft(self) ? that(self.left) : self ) /** * Returns an effect that will produce the value of this effect, unless it * fails, in which case, it will produce the value of the specified effect. * * @category error handling * @since 1.0.0 */ export const orElseEither: { ( that: (e1: E1) => These ): (self: These) => These> ( self: These, that: (e1: E1) => These ): These> } = dual(2, ( self: These, that: (e1: E1) => These ): These> => isLeft(self) ? map(that(self.left), E.right) : map(self, E.left)) /** * Executes this effect and returns its value, if it succeeds, but otherwise * fails with the specified error. * * @category error handling * @since 1.0.0 */ export const orElseFail: { (onLeft: LazyArg): (self: These) => These (self: These, onLeft: LazyArg): These } = dual( 2, (self: These, onLeft: LazyArg): These => orElse(self, () => left(onLeft())) ) const coproduct = (self: These, that: These): These => isRightOrBoth(self) ? self : that const coproductMany = (self: These, collection: Iterable>): These => { let out = self if (isRightOrBoth(out)) { return out } for (out of collection) { if (isRightOrBoth(out)) { return out } } return out } /** * @category error handling * @since 1.0.0 */ export const firstRightOrBothOf: { (collection: Iterable>): (self: These) => These (self: These, collection: Iterable>): These } = dual(2, coproductMany) /** * @category instances * @since 1.0.0 */ export const SemiCoproduct: semiCoproduct.SemiCoproduct = { imap, coproduct, coproductMany } /** * @category combining * @since 1.0.0 */ export const getFirstRightOrBothSemigroup: () => Semigroup> = semiCoproduct .getSemigroup(SemiCoproduct) /** * @category instances * @since 1.0.0 */ export const SemiAlternative: semiAlternative.SemiAlternative = { map, imap, coproduct, coproductMany: firstRightOrBothOf } /** * @category filtering * @since 1.0.0 */ export const filter: { (refinement: Refinement, onFalse: LazyArg): ( self: These ) => These ( predicate: Predicate, onFalse: LazyArg ): (self: These) => These ( self: These, refinement: Refinement, onFalse: LazyArg ): These ( self: These, predicate: Predicate, onFalse: LazyArg ): These } = dual(3, ( self: These, predicate: Predicate, onFalse: LazyArg ): These => isLeft(self) ? self : predicate(self.right) ? self : left(onFalse())) /** * @category filtering * @since 1.0.0 */ export const filterMap: { ( f: (a: A) => Option, onNone: LazyArg ): (self: These) => These ( self: These, f: (a: A) => Option, onNone: LazyArg ): These } = dual(3, ( self: These, f: (a: A) => Option, onNone: LazyArg ): These => { if (isLeft(self)) { return self } if (isRight(self)) { const ob = f(self.right) return O.isNone(ob) ? left(onNone()) : right(ob.value) } const ob = f(self.right) return O.isNone(ob) ? left(onNone()) : both(self.left, ob.value) }) /** * @category filtering * @since 1.0.0 */ export const compact: { (onNone: LazyArg): (self: These>) => These (self: These>, onNone: LazyArg): These } = dual( 2, (self: These>, onNone: LazyArg): These => filterMap(self, identity, onNone) ) const product = ( self: Validated, that: Validated ): Validated => { if (isLeft(self)) { return self } if (isRight(self)) { if (isLeft(that)) { return that } if (isRight(that)) { return right([self.right, that.right]) } return both(that.left, [self.right, that.right]) } if (isLeft(that)) { return left(RA.appendAllNonEmpty(self.left, that.left)) } if (isRight(that)) { return both(self.left, [self.right, that.right]) } return both(RA.appendAllNonEmpty(self.left, that.left), [self.right, that.right]) } /** * Similar to `Promise.all` but operates on `These`s. * * ``` * Iterable> -> These * ``` * * @category combining * @since 1.0.0 */ const all = ( collection: Iterable> ): Validated> => { const rights: Array = [] const lefts: Array = [] let isFatal = false for (const t of collection) { if (isLeft(t)) { lefts.push(...t.left) isFatal = true break } else if (isRight(t)) { rights.push(t.right) } else { lefts.push(...t.left) rights.push(t.right) } } if (RA.isNonEmpty(lefts)) { return isFatal ? left(lefts) : both(lefts, rights) } return right(rights) } const productMany = ( self: Validated, collection: Iterable> ): Validated]> => map(product(self, all(collection)), ([a, as]) => [a, ...as]) /** * @category instances * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } /** * @category instances * @since 1.0.0 */ export const SemiApplicative: semiApplicative.SemiApplicative = { imap, map, product, productMany } /** * Lifts a binary function into `These`. * * @param f - The function to lift. * * @category lifting * @since 1.0.0 */ export const lift2: (f: (a: A, b: B) => C) => { (self: Validated, that: Validated): Validated (that: Validated): (self: Validated) => Validated } = semiApplicative.lift2(SemiApplicative) /** * @category combining * @since 1.0.0 */ export const zipWith: { ( self: Validated, that: Validated, f: (a: A, b: B) => C ): Validated ( that: Validated, f: (a: A, b: B) => C ): (self: Validated) => Validated } = semiApplicative.zipWith(SemiApplicative) /** * @since 1.0.0 */ export const ap: { (self: Validated B>, that: Validated): Validated ( that: Validated ): (self: Validated B>) => Validated } = semiApplicative.ap(SemiApplicative) /** * @category combining * @since 1.0.0 */ export const getFirstLeftSemigroup: (S: Semigroup) => Semigroup> = semiApplicative.getSemigroup(SemiApplicative) /** * Appends an element to the end of a tuple. * * @since 1.0.0 */ export const appendElement: { , E2, B>( self: Validated, that: Validated ): Validated ( that: Validated ): >(self: Validated) => Validated } = semiProduct.appendElement(SemiProduct) /** * @category instances * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll: all } /** * Similar to `Promise.all` but operates on `These`s. * * ``` * [These, These, ...] -> These * ``` * * @since 1.0.0 */ export const tuple: >>(...tuple: T) => Validated< [T[number]] extends [Validated] ? E : never, { [I in keyof T]: [T[I]] extends [Validated] ? A : never } > = product_.tuple(Product) /** * @since 1.0.0 */ export const struct: >>( r: R ) => Validated< [R[keyof R]] extends [Validated] ? E : never, { [K in keyof R]: [R[K]] extends [Validated] ? A : never } > = product_ .struct(Product) /** * @category combining * @since 1.0.0 */ export const flatMap: { (f: (a: A) => Validated): (self: Validated) => Validated (self: Validated, f: (a: A) => Validated): Validated } = dual( 2, (self: Validated, f: (a: A) => Validated): Validated => { if (isLeft(self)) { return self } if (isRight(self)) { return f(self.right) } const that = f(self.right) if (isLeft(that)) { return left(RA.appendAllNonEmpty(that.left)(self.left)) } if (isRight(that)) { return both(self.left, that.right) } return both(RA.appendAllNonEmpty(that.left)(self.left), that.right) } ) /** * @category instances * @since 1.0.0 */ export const Applicative: applicative.Applicative = { imap, of, map, product, productMany, productAll: all } /** * @category combining * @since 1.0.0 */ export const getFirstLeftMonoid: (M: Monoid) => Monoid> = applicative .getMonoid( Applicative ) /** * @category instances * @since 1.0.0 */ export const FlatMap: flatMap_.FlatMap = { flatMap } /** * @since 1.0.0 */ export const flatten: ( self: Validated> ) => Validated = flatMap_.flatten(FlatMap) /** * @since 1.0.0 */ export const andThen: { (self: Validated, that: Validated): Validated (that: Validated): (self: Validated) => Validated } = flatMap_.andThen(FlatMap) /** * @since 1.0.0 */ export const composeKleisliArrow: { ( afb: (a: A) => Validated, bfc: (b: B) => Validated ): (a: A) => Validated ( bfc: (b: B) => Validated ): (afb: (a: A) => Validated) => (a: A) => Validated } = flatMap_.composeKleisliArrow(FlatMap) /** * @category instances * @since 1.0.0 */ export const Chainable: chainable.Chainable = { imap, map, flatMap } /** * Sequences the specified effect after this effect, but ignores the value * produced by the effect. * * @category combining * @since 1.0.0 */ export const andThenDiscard: { (self: Validated, that: Validated): Validated (that: Validated): (self: Validated) => Validated } = chainable.andThenDiscard(Chainable) /** * Returns an effect that effectfully "peeks" at the success of this effect. * * @category combinators * @since 1.0.0 */ export const tap: { (self: Validated, f: (a: A) => Validated): Validated (f: (a: A) => Validated): (self: Validated) => Validated } = chainable.tap(Chainable) /** * @category instances * @since 1.0.0 */ export const Monad: monad.Monad = { imap, of, map, flatMap } // ------------------------------------------------------------------------------------- // math // ------------------------------------------------------------------------------------- /** * @category math * @since 1.0.0 */ export const sum: { (self: Validated, that: Validated): Validated (that: Validated): (self: Validated) => Validated } = lift2(N.sum) /** * @category math * @since 1.0.0 */ export const multiply: { (self: Validated, that: Validated): Validated (that: Validated): (self: Validated) => Validated } = lift2(N.multiply) /** * @category math * @since 1.0.0 */ export const subtract: { (self: Validated, that: Validated): Validated (that: Validated): (self: Validated) => Validated } = lift2(N.subtract) /** * @category math * @since 1.0.0 */ export const divide: { (self: Validated, that: Validated): Validated (that: Validated): (self: Validated) => Validated } = lift2(N.divide) // ------------------------------------------------------------------------------------- // do notation // ------------------------------------------------------------------------------------- /** * @category do notation * @since 1.0.0 */ export const bindTo: { (name: N): (self: These) => These (self: These, name: N): These } = invariant.bindTo(Invariant) const let_: { ( name: Exclude, f: (a: A) => B ): (self: These) => These ( self: These, name: Exclude, f: (a: A) => B ): These } = covariant.let(Covariant) export { /** * @category do notation * @since 1.0.0 */ let_ as let } /** * @category do notation * @since 1.0.0 */ export const Do: These = of_.Do(Of) /** * @category do notation * @since 1.0.0 */ export const bind: { ( name: Exclude, f: (a: A) => Validated ): ( self: Validated ) => Validated ( self: Validated, name: Exclude, f: (a: A) => Validated ): Validated } = chainable.bind(Chainable) /** * @category do notation * @since 1.0.0 */ export const bindEither: { ( name: Exclude, f: (a: A) => Either ): ( self: Validated ) => Validated ( self: Validated, name: Exclude, f: (a: A) => Either ): Validated } = dual(3, ( self: Validated, name: Exclude, f: (a: A) => Either ): Validated => bind(self, name, (a) => fromEither(f(a)))) /** * @category do notation * @since 1.0.0 */ export const bindThese: { ( name: Exclude, f: (a: A) => These ): ( self: Validated ) => Validated ( self: Validated, name: Exclude, f: (a: A) => These ): Validated } = dual(3, ( self: Validated, name: Exclude, f: (a: A) => These ): Validated => bind(self, name, (a) => toValidated(f(a)))) /** * @category do notation * @since 1.0.0 */ export const andThenBind: { ( name: Exclude, that: Validated ): ( self: Validated ) => Validated ( self: Validated, name: Exclude, that: Validated ): Validated } = semiProduct.andThenBind(SemiProduct) ================================================ FILE: src/Tuple.ts ================================================ /** * This module provides utility functions for working with tuples in TypeScript. * * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { TypeLambda } from "@fp-ts/core/HKT" import * as bicovariant from "@fp-ts/core/typeclass/Bicovariant" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as order from "@fp-ts/core/typeclass/Order" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * @category type lambdas * @since 1.0.0 */ export interface TupleTypeLambda extends TypeLambda { readonly type: [this["Out1"], this["Target"]] } /** * Constructs a new tuple from the provided values. * * @param elements - The list of elements to create the tuple from. * * @example * import { tuple } from "@fp-ts/core/Tuple" * * assert.deepStrictEqual(tuple(1, 'hello', true), [1, 'hello', true]) * * @category constructors * @since 1.0.0 */ export const tuple = >(...elements: A): A => elements /** * Return the first element of a tuple. * * @param self - A tuple of length `2`. * * @example * import { getFirst } from "@fp-ts/core/Tuple" * * assert.deepStrictEqual(getFirst(["hello", 42]), "hello") * * @category getters * @since 1.0.0 */ export const getFirst = (self: readonly [L, R]): L => self[0] /** * Return the second element of a tuple. * * @param self - A tuple of length `2`. * * @example * import { getSecond } from "@fp-ts/core/Tuple" * * assert.deepStrictEqual(getSecond(["hello", 42]), 42) * * @category getters * @since 1.0.0 */ export const getSecond = (self: readonly [L, R]): R => self[1] /** * Transforms both elements of a tuple using the given functions. * * @param self - A tuple of length `2`. * @param f - The function to transform the first element of the tuple. * @param g - The function to transform the second element of the tuple. * * @example * import { bimap } from "@fp-ts/core/Tuple" * * assert.deepStrictEqual( * bimap(["hello", 42], s => s.toUpperCase(), n => n.toString()), * ["HELLO", "42"] * ) * * @category mapping * @since 1.0.0 */ export const bimap: { (f: (e: L1) => L2, g: (a: R1) => R2): (self: readonly [L1, R1]) => [L2, R2] (self: readonly [L1, R1], f: (e: L1) => L2, g: (a: R1) => R2): [L2, R2] } = dual( 3, ( self: readonly [L1, R1], f: (e: L1) => L2, g: (a: R1) => R2 ): [L2, R2] => [f(self[0]), g(self[1])] ) /** * @category instances * @since 1.0.0 */ export const Bicovariant: bicovariant.Bicovariant = { bimap } /** * Transforms the first component of a tuple using a given function. * * @param self - A tuple of length `2`. * @param f - The function to transform the first element of the tuple. * * @example * import { mapFirst } from "@fp-ts/core/Tuple" * * assert.deepStrictEqual( * mapFirst(["hello", 42], s => s.toUpperCase()), * ["HELLO", 42] * ) * * @category mapping * @since 1.0.0 */ export const mapFirst: { (f: (left: L1) => L2): (self: readonly [L1, R]) => [L2, R] (self: readonly [L1, R], f: (left: L1) => L2): [L2, R] } = bicovariant.mapLeft(Bicovariant) as any /** * Transforms the second component of a tuple using a given function. * * @param self - A tuple of length `2`. * @param f - The function to transform the second element of the tuple. * * @example * import { mapSecond } from "@fp-ts/core/Tuple" * * assert.deepStrictEqual( * mapSecond(["hello", 42], n => n.toString()), * ["hello", "42"] * ) * * @category mapping * @since 1.0.0 */ export const mapSecond: { (f: (right: R1) => R2): (self: readonly [L, R1]) => [L, R2] (self: readonly [L, R1], f: (right: R1) => R2): [L, R2] } = bicovariant.map(Bicovariant) as any /** * Swaps the two elements of a tuple. * * @param self - A tuple of length `2`. * * @example * import { swap } from "@fp-ts/core/Tuple" * * assert.deepStrictEqual(swap(["hello", 42]), [42, "hello"]) * * @since 1.0.0 */ export const swap = (self: readonly [L, R]): [R, L] => [self[1], self[0]] /** * Given a tuple of `Equivalence`s returns a new `Equivalence` that compares values of a tuple * by applying each `Equivalence` to the corresponding element of the tuple. * * @category combinators * @since 1.0.0 */ export const getEquivalence: >>( ...predicates: T ) => equivalence.Equivalence< Readonly<{ [I in keyof T]: [T[I]] extends [equivalence.Equivalence] ? A : never }> > = equivalence.tuple /** * This function creates and returns a new `Order` for a tuple of values based on the given `Order`s for each element in the tuple. * The returned `Order` compares two tuples of the same type by applying the corresponding `Order` to each element in the tuple. * It is useful when you need to compare two tuples of the same type and you have a specific way of comparing each element * of the tuple. * * @category combinators * @since 1.0.0 */ export const getOrder: >>( ...elements: T ) => order.Order<{ [I in keyof T]: [T[I]] extends [order.Order] ? A : never }> = order.tuple /** * This function creates and returns a new `Semigroup` for a tuple of values based on the given `Semigroup`s for each element in the tuple. * The returned `Semigroup` combines two tuples of the same type by applying the corresponding `Semigroup` passed as arguments to each element in the tuple. * * It is useful when you need to combine two tuples of the same type and you have a specific way of combining each element of the tuple. * * @category combinators * @since 1.0.0 */ export const getSemigroup = semigroup.tuple /** * This function creates and returns a new `Monoid` for a tuple of values based on the given `Monoid`s for each element in the tuple. * The returned `Monoid` combines two tuples of the same type by applying the corresponding `Monoid` passed as arguments to each element in the tuple. * * The `empty` value of the returned `Monoid` is the tuple of `empty` values of the input `Monoid`s. * * It is useful when you need to combine two tuples of the same type and you have a specific way of combining each element of the tuple. * * @category combinators * @since 1.0.0 */ export const getMonoid = monoid.tuple /** * Appends an element to the end of a tuple. * * @since 1.0.0 */ export const appendElement: { (that: B): >(self: A) => [...A, B] , B>(self: A, that: B): [...A, B] } = dual(2, , B>(self: A, that: B): [...A, B] => [...self, that]) /* TODO: - at - swap */ ================================================ FILE: src/index.ts ================================================ /** * @since 1.0.0 */ // ------------------------------------------------------------------------------------- // HKT // ------------------------------------------------------------------------------------- import * as hkt from "@fp-ts/core/HKT" // ------------------------------------------------------------------------------------- // data types // ------------------------------------------------------------------------------------- import * as bigint from "@fp-ts/core/Bigint" import * as boolean from "@fp-ts/core/Boolean" import * as either from "@fp-ts/core/Either" import * as _function from "@fp-ts/core/Function" import * as identity from "@fp-ts/core/Identity" import * as number from "@fp-ts/core/Number" import * as option from "@fp-ts/core/Option" import * as ordering from "@fp-ts/core/Ordering" import * as predicate from "@fp-ts/core/Predicate" import * as readonlyArray from "@fp-ts/core/ReadonlyArray" import * as readonlyRecord from "@fp-ts/core/ReadonlyRecord" import * as string from "@fp-ts/core/String" import * as struct from "@fp-ts/core/Struct" import * as symbol from "@fp-ts/core/Symbol" import * as these from "@fp-ts/core/These" import * as tuple from "@fp-ts/core/Tuple" // ------------------------------------------------------------------------------------- // typeclasses // ------------------------------------------------------------------------------------- import * as alternative from "@fp-ts/core/typeclass/Alternative" import * as applicative from "@fp-ts/core/typeclass/Applicative" import * as bicovariant from "@fp-ts/core/typeclass/Bicovariant" import * as bounded from "@fp-ts/core/typeclass/Bounded" import * as chainable from "@fp-ts/core/typeclass/Chainable" import * as contravariant from "@fp-ts/core/typeclass/Contravariant" import * as coproduct from "@fp-ts/core/typeclass/Coproduct" import * as covariant from "@fp-ts/core/typeclass/Covariant" import * as equivalence from "@fp-ts/core/typeclass/Equivalence" import * as filterable from "@fp-ts/core/typeclass/Filterable" import * as flatMap from "@fp-ts/core/typeclass/FlatMap" import * as foldable from "@fp-ts/core/typeclass/Foldable" import * as invariant from "@fp-ts/core/typeclass/Invariant" import * as monad from "@fp-ts/core/typeclass/Monad" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as of from "@fp-ts/core/typeclass/Of" import * as order from "@fp-ts/core/typeclass/Order" import * as pointed from "@fp-ts/core/typeclass/Pointed" import * as product from "@fp-ts/core/typeclass/Product" import * as semiAlternative from "@fp-ts/core/typeclass/SemiAlternative" import * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" import * as traversable from "@fp-ts/core/typeclass/Traversable" import * as traversableFilterable from "@fp-ts/core/typeclass/TraversableFilterable" export { /** * @since 1.0.0 */ _function as function, /** * @category typeclass * @since 1.0.0 */ alternative, /** * @category typeclass * @since 1.0.0 */ applicative, /** * @category typeclass * @since 1.0.0 */ bicovariant, /** * @since 1.0.0 */ bigint, /** * @since 1.0.0 */ boolean, /** * @category typeclass * @since 1.0.0 */ bounded, /** * @category typeclass * @since 1.0.0 */ chainable, /** * @category typeclass * @since 1.0.0 */ contravariant, /** * @category typeclass * @since 1.0.0 */ coproduct, /** * @category typeclass * @since 1.0.0 */ covariant, /** * @since 1.0.0 */ either, /** * @category typeclass * @since 1.0.0 */ equivalence, /** * @category typeclass * @since 1.0.0 */ filterable, /** * @category typeclass * @since 1.0.0 */ flatMap, /** * @category typeclass * @since 1.0.0 */ foldable, /** * @since 1.0.0 */ hkt, /** * @since 1.0.0 */ identity, /** * @category typeclass * @since 1.0.0 */ invariant, /** * @category typeclass * @since 1.0.0 */ monad, /** * @category typeclass * @since 1.0.0 */ monoid, /** * @since 1.0.0 */ number, /** * @category typeclass * @since 1.0.0 */ of, /** * @since 1.0.0 */ option, /** * @category typeclass * @since 1.0.0 */ order, /** * @since 1.0.0 */ ordering, /** * @category typeclass * @since 1.0.0 */ pointed, /** * @since 1.0.0 */ predicate, /** * @category typeclass * @since 1.0.0 */ product, /** * @since 1.0.0 */ readonlyArray, /** * @since 1.0.0 */ readonlyRecord, /** * @category typeclass * @since 1.0.0 */ semiAlternative, /** * @category typeclass * @since 1.0.0 */ semiApplicative, /** * @category typeclass * @since 1.0.0 */ semiCoproduct, /** * @category typeclass * @since 1.0.0 */ semigroup, /** * @category typeclass * @since 1.0.0 */ semiProduct, /** * @since 1.0.0 */ string, /** * @since 1.0.0 */ struct, /** * @since 1.0.0 */ symbol, /** * @since 1.0.0 */ these, /** * @category typeclass * @since 1.0.0 */ traversable, /** * @category typeclass * @since 1.0.0 */ traversableFilterable, /** * @since 1.0.0 */ tuple } ================================================ FILE: src/internal/Either.ts ================================================ /** * @since 1.0.0 */ import type { Either, Left, Right } from "@fp-ts/core/Either" import { dual } from "@fp-ts/core/Function" import { proto } from "@fp-ts/core/internal/effect" import * as option from "@fp-ts/core/internal/Option" import type { Option } from "@fp-ts/core/Option" /** @internal */ export const isLeft = (ma: Either): ma is Left => ma._tag === "Left" /** @internal */ export const isRight = (ma: Either): ma is Right => ma._tag === "Right" /** @internal */ export const left = (e: E): Either => Object.setPrototypeOf({ _tag: "Left", left: e }, proto) /** @internal */ export const right = (a: A): Either => Object.setPrototypeOf({ _tag: "Right", right: a }, proto) /** @internal */ export const getLeft = ( self: Either ): Option => (isRight(self) ? option.none : option.some(self.left)) /** @internal */ export const getRight = ( self: Either ): Option => (isLeft(self) ? option.none : option.some(self.right)) /** @internal */ export const fromOption = dual( 2, (self: Option, onNone: () => E): Either => option.isNone(self) ? left(onNone()) : right(self.value) ) ================================================ FILE: src/internal/Option.ts ================================================ /** * @since 1.0.0 */ import { proto } from "@fp-ts/core/internal/effect" import type { None, Option, Some } from "@fp-ts/core/Option" /** @internal */ export const isNone = (fa: Option): fa is None => fa._tag === "None" /** @internal */ export const isSome = (fa: Option): fa is Some => fa._tag === "Some" /** @internal */ export const none: Option = Object.setPrototypeOf({ _tag: "None" }, proto) /** @internal */ export const some = (a: A): Option => Object.setPrototypeOf({ _tag: "Some", value: a }, proto) ================================================ FILE: src/internal/ReadonlyArray.ts ================================================ /** * @since 1.0.0 */ import type { NonEmptyArray } from "@fp-ts/core/ReadonlyArray" /** @internal */ export const isNonEmptyArray = (self: ReadonlyArray): self is NonEmptyArray => self.length > 0 /** @internal */ export const fromIterable = (collection: Iterable): Array => Array.isArray(collection) ? collection : Array.from(collection) ================================================ FILE: src/internal/effect.ts ================================================ /** * @since 1.0.0 */ /** @internal */ export const structural = Symbol.for("@effect/data/Equal/structural") /** @internal */ export const proto = Object.setPrototypeOf({ [structural]: true }, Object.prototype) ================================================ FILE: src/typeclass/Alternative.ts ================================================ /** * @since 1.0.0 */ import type { TypeLambda } from "@fp-ts/core/HKT" import type { Coproduct } from "@fp-ts/core/typeclass/Coproduct" import type { SemiAlternative } from "@fp-ts/core/typeclass/SemiAlternative" /** * @category type class * @since 1.0.0 */ export interface Alternative extends SemiAlternative, Coproduct {} ================================================ FILE: src/typeclass/Applicative.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import * as monoid from "@fp-ts/core/typeclass/Monoid" import type { Product } from "@fp-ts/core/typeclass/Product" import type { SemiApplicative } from "@fp-ts/core/typeclass/SemiApplicative" import * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" /** * @category type class * @since 1.0.0 */ export interface Applicative extends SemiApplicative, Product {} /** * Lift a `Monoid` into `F`, combining the inner values using the provided `Monoid`: * * - `combine` is provided by {@link semiApplicative.getSemigroup}. * - `empty` is `F.of(M.empty)` * * @param F - The `Applicative` instance for `F`. * @param M - The `Monoid` instance for `A`. * * @since 1.0.0 */ export const getMonoid = (F: Applicative) => (M: Monoid): Monoid> => monoid.fromSemigroup( semiApplicative.getSemigroup(F)(M), F.of(M.empty) ) ================================================ FILE: src/typeclass/Bicovariant.ts ================================================ /** * @since 1.0.0 */ import { dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" /** * @category type class * @since 1.0.0 */ export interface Bicovariant extends TypeClass { readonly bimap: { ( f: (e: E1) => E2, g: (a: A) => B ): (self: Kind) => Kind ( self: Kind, f: (e: E1) => E2, g: (a: A) => B ): Kind } } /** * Returns a default ternary `bimap` composition. * * @since 1.0.0 */ export const bimapComposition = ( CovariantF: Covariant, BicovariantG: Bicovariant ) => ( self: Kind>, f: (e: E1) => E2, g: (a: A) => B ): Kind> => CovariantF.map(self, BicovariantG.bimap(f, g)) /** * Returns a default `mapLeft` implementation. * * @since 1.0.0 */ export const mapLeft = ( F: Bicovariant ): { (f: (e: E) => G): (self: Kind) => Kind (self: Kind, f: (e: E) => G): Kind } => dual( 2, (self: Kind, f: (e: E) => G): Kind => F.bimap(self, f, identity) ) /** * Returns a default `map` implementation. * * @since 1.0.0 */ export const map = ( F: Bicovariant ): Covariant["map"] => dual( 2, (self: Kind, f: (a: A) => B): Kind => F.bimap(self, identity, f) ) ================================================ FILE: src/typeclass/Bounded.ts ================================================ /** * @since 1.0.0 */ import type { TypeLambda } from "@fp-ts/core/HKT" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as order from "@fp-ts/core/typeclass/Order" import type { Order } from "@fp-ts/core/typeclass/Order" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * @category type class * @since 1.0.0 */ export interface Bounded extends Order { readonly maxBound: A readonly minBound: A } /** * @category type lambdas * @since 1.0.0 */ export interface BoundedTypeLambda extends TypeLambda { readonly type: Bounded } /** * `Monoid` that returns last minimum of elements. * * @category constructors * @since 1.0.0 */ export const min = (B: Bounded): Monoid => monoid.fromSemigroup(semigroup.min(B), B.maxBound) /** * `Monoid` that returns last maximum of elements. * * @category constructors * @since 1.0.0 */ export const max = (B: Bounded): Monoid => monoid.fromSemigroup(semigroup.max(B), B.minBound) /** * @category instances * @since 1.0.0 */ export const number: Bounded = { compare: order.number.compare, maxBound: Infinity, minBound: -Infinity } /** * Clamp a value between `minBound` and `maxBound` values. * * @since 1.0.0 */ export const clamp = (B: Bounded): (a: A) => A => order.clamp(B)(B.minBound, B.maxBound) /** * Reverses the `Order` of a `Bounded` and flips `maxBound` and `minBound` values. * * @since 1.0.0 */ export const reverse = (B: Bounded): Bounded => ({ ...order.reverse(B), minBound: B.maxBound, maxBound: B.minBound }) ================================================ FILE: src/typeclass/Chainable.ts ================================================ /** * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" import type { FlatMap } from "@fp-ts/core/typeclass/FlatMap" /** * @category type class * @since 1.0.0 */ export interface Chainable extends FlatMap, Covariant {} /** * Sequences the specified effect after this effect, but ignores the value * produced by the effect. * * @category combining * @since 1.0.0 */ export const andThenDiscard = (F: Chainable): { ( that: Kind ): (self: Kind) => Kind ( self: Kind, that: Kind ): Kind } => dual(2, ( self: Kind, that: Kind ): Kind => tap(F)(self, () => that)) /** * Returns an effect that effectfully "peeks" at the success of this effect. * * @since 1.0.0 */ export const tap = (F: Chainable): { ( f: (a: A) => Kind ): (self: Kind) => Kind ( self: Kind, f: (a: A) => Kind ): Kind } => dual( 2, ( self: Kind, f: (a: A) => Kind ): Kind => F.flatMap(self, a => F.map(f(a), () => a)) ) /** * @category do notation * @since 1.0.0 */ export const bind = (F: Chainable): { ( name: Exclude, f: (a: A) => Kind ): ( self: Kind ) => Kind ( self: Kind, name: Exclude, f: (a: A) => Kind ): Kind } => dual(3, ( self: Kind, name: Exclude, f: (a: A) => Kind ): Kind => F.flatMap(self, a => F.map(f(a), b => Object.assign({}, a, { [name]: b }) as any))) ================================================ FILE: src/typeclass/Contravariant.ts ================================================ /** * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Invariant } from "@fp-ts/core/typeclass/Invariant" /** * @category type class * @since 1.0.0 */ export interface Contravariant extends Invariant { readonly contramap: { (f: (b: B) => A): (self: Kind) => Kind (self: Kind, f: (b: B) => A): Kind } } /** * Composing two contravariant functors yields a Covariant functor. * * Returns a default binary `map` composition. * * @since 1.0.0 */ export const contramapComposition = ( F: Contravariant, G: Contravariant ) => ( self: Kind>, f: (a: A) => B ): Kind> => F.contramap(self, G.contramap(f)) /** * Returns a default `imap` implementation. * * @since 1.0.0 */ export const imap = ( contramap: ( self: Kind, f: (b: B) => A ) => Kind ): Invariant["imap"] => dual(3, (self, _, from) => contramap(self, from)) ================================================ FILE: src/typeclass/Coproduct.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import type { SemiCoproduct } from "@fp-ts/core/typeclass/SemiCoproduct" import * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" /** * @category type class * @since 1.0.0 */ export interface Coproduct extends SemiCoproduct { readonly zero: () => Kind readonly coproductAll: ( collection: Iterable> ) => Kind } /** * @since 1.0.0 */ export const getMonoid = (F: Coproduct) => (): Monoid< Kind > => ({ ...semiCoproduct.getSemigroup(F)(), empty: F.zero(), combineAll: F.coproductAll }) ================================================ FILE: src/typeclass/Covariant.ts ================================================ /** * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Invariant } from "@fp-ts/core/typeclass/Invariant" /** * @category type class * @since 1.0.0 */ export interface Covariant extends Invariant { readonly map: { (f: (a: A) => B): (self: Kind) => Kind (self: Kind, f: (a: A) => B): Kind } } /** * Returns a default `map` composition. * * @since 1.0.0 */ export const mapComposition = ( F: Covariant, G: Covariant ): (( self: Kind>, f: (a: A) => B ) => Kind>) => (self, f) => F.map(self, G.map(f)) /** * Returns a default `imap` implementation. * * @since 1.0.0 */ export const imap = ( map: (self: Kind, f: (a: A) => B) => Kind ): Invariant["imap"] => dual(3, (self, to, _) => map(self, to)) /** * @category mapping * @since 1.0.0 */ export const flap = (F: Covariant): { (self: Kind B>): (a: A) => Kind (a: A, self: Kind B>): Kind } => dual( 2, (a: A, self: Kind B>): Kind => F.map(self, f => f(a)) ) /** * @category mapping * @since 1.0.0 */ export const as = (F: Covariant): { (b: B): (self: Kind) => Kind (self: Kind, b: B): Kind } => dual( 2, (self: Kind, b: B): Kind => F.map(self, () => b) ) /** * @category mapping * @since 1.0.0 */ export const asUnit = ( F: Covariant ): ((self: Kind) => Kind) => as(F)(undefined) const let_ = ( F: Covariant ): { ( name: Exclude, f: (a: A) => B ): ( self: Kind ) => Kind ( self: Kind, name: Exclude, f: (a: A) => B ): Kind } => dual(3, ( self: Kind, name: Exclude, f: (a: A) => B ): Kind => F.map(self, a => Object.assign({}, a, { [name]: f(a) }) as any)) export { /** * @category do notation * @since 1.0.0 */ let_ as let } ================================================ FILE: src/typeclass/Equivalence.ts ================================================ /** * This module provides an implementation of the `Equivalence` type class, which defines a binary relation * that is reflexive, symmetric, and transitive. In other words, it defines a notion of equivalence between values of a certain type. * These properties are also known in mathematics as an "equivalence relation". * * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { TypeLambda } from "@fp-ts/core/HKT" import * as readonlyArray from "@fp-ts/core/internal/ReadonlyArray" import * as contravariant from "@fp-ts/core/typeclass/Contravariant" import type * as invariant from "@fp-ts/core/typeclass/Invariant" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as product_ from "@fp-ts/core/typeclass/Product" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import type * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" /** * @category type class * @since 1.0.0 */ export interface Equivalence { (self: A, that: A): boolean } /** * @category type lambdas * @since 1.0.0 */ export interface EquivalenceTypeLambda extends TypeLambda { readonly type: Equivalence } /** * @category constructors * @since 1.0.0 */ export const make = (isEquivalent: (self: A, that: A) => boolean): Equivalence => (self: A, that: A): boolean => self === that || isEquivalent(self, that) const isStrictEquivalent = (x: unknown, y: unknown) => x === y /** * Return an `Equivalence` that uses strict equality (===) to compare values. * * @since 1.0.0 * @category constructors */ export const strict: () => Equivalence = () => isStrictEquivalent /** * @category instances * @since 1.0.0 */ export const string: Equivalence = strict() /** * @category instances * @since 1.0.0 */ export const number: Equivalence = strict() /** * @category instances * @since 1.0.0 */ export const boolean: Equivalence = strict() /** * @category instances * @since 1.0.0 */ export const bigint: Equivalence = strict() /** * @category instances * @since 1.0.0 */ export const symbol: Equivalence = strict() /** * @category instances * @since 1.0.0 */ export const getSemigroup = (): Semigroup> => semigroup.make( (self, that) => make((x, y) => self(x, y) && that(x, y)), (self, collection) => make((x, y) => { if (!self(x, y)) { return false } for (const equivalence of collection) { if (!equivalence(x, y)) { return false } } return true }) ) const isAlwaysEquivalent: Equivalence = (_x, _y) => true /** * @category instances * @since 1.0.0 */ export const getMonoid = (): Monoid> => monoid.fromSemigroup(getSemigroup(), isAlwaysEquivalent) /** * @category combinators * @since 1.0.0 */ export const contramap: { (f: (b: B) => A): (self: Equivalence) => Equivalence (self: Equivalence, f: (b: B) => A): Equivalence } = dual( 2, (self: Equivalence, f: (b: B) => A): Equivalence => make((x, y) => self(f(x), f(y))) ) const imap = contravariant.imap(contramap) /** * @category instances * @since 1.0.0 */ export const Contravariant: contravariant.Contravariant = { imap, contramap } /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } const product = (self: Equivalence, that: Equivalence): Equivalence<[A, B]> => make(([xa, xb], [ya, yb]) => self(xa, ya) && that(xb, yb)) const productAll = (collection: Iterable>): Equivalence> => { const equivalences = readonlyArray.fromIterable(collection) return make((x, y) => { const len = Math.min(x.length, y.length, equivalences.length) for (let i = 0; i < len; i++) { if (!equivalences[i](x[i], y[i])) { return false } } return true }) } const productMany = ( self: Equivalence, collection: Iterable> ): Equivalence<[A, ...Array]> => { const equivalence = productAll(collection) return make((x, y) => !self(x[0], y[0]) ? false : equivalence(x.slice(1), y.slice(1))) } /** * @category instances * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } const of: (a: A) => Equivalence = () => isAlwaysEquivalent /** * @category instances * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll } /** * Similar to `Promise.all` but operates on `Equivalence`s. * * ``` * [Equivalence, Equivalence, ...] -> Equivalence<[A, B, ...]> * ``` * * Given a tuple of `Equivalence`s returns a new `Equivalence` that compares values of a tuple * by applying each `Equivalence` to the corresponding element of the tuple. * * @category combinators * @since 1.0.0 */ export const tuple: >>( ...predicates: T ) => Equivalence] ? A : never }>> = product_.tuple(Product) /** * Given a struct of `Equivalence`s returns a new `Equivalence` that compares values of a struct * by applying each `Equivalence` to the corresponding property of the struct. * * @category combinators * @since 1.0.0 */ export const struct: >>( predicates: R ) => Equivalence<{ readonly [K in keyof R]: [R[K]] extends [Equivalence] ? A : never }> = product_.struct(Product) ================================================ FILE: src/typeclass/Filterable.ts ================================================ /** * `Filterable` represents data structures which can be _partitioned_/_filtered_. * * @since 1.0.0 */ import type { Either } from "@fp-ts/core/Either" import { dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" import * as either from "@fp-ts/core/internal/Either" import * as option from "@fp-ts/core/internal/Option" import type { Option } from "@fp-ts/core/Option" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" /** * @category models * @since 1.0.0 */ export interface Filterable extends TypeClass { readonly partitionMap: { ( f: (a: A) => Either ): (self: Kind) => [Kind, Kind] ( self: Kind, f: (a: A) => Either ): [Kind, Kind] } readonly filterMap: { (f: (a: A) => Option): (self: Kind) => Kind (self: Kind, f: (a: A) => Option): Kind } } /** * Returns a default binary `partitionMap` composition. * * @since 1.0.0 */ export const partitionMapComposition = ( F: Covariant, G: Filterable ) => ( self: Kind>, f: (a: A) => Either ): [Kind>, Kind>] => { const filterMap = filterMapComposition(F, G) return [filterMap(self, a => either.getLeft(f(a))), filterMap(self, a => either.getRight(f(a)))] } /** * Returns a default binary `filterMap` composition. * * @since 1.0.0 */ export const filterMapComposition = ( F: Covariant, G: Filterable ) => ( self: Kind>, f: (a: A) => Option ): Kind> => F.map(self, G.filterMap(f)) /** * @since 1.0.0 */ export const compact = ( F: Filterable ): (self: Kind>) => Kind => F.filterMap(identity) /** * @since 1.0.0 */ export const separate = ( F: Filterable ): ( self: Kind> ) => [Kind, Kind] => F.partitionMap(identity) /** * @since 1.0.0 */ export const filter: ( F: Filterable ) => { (refinement: (a: A) => a is B): ( self: Kind ) => Kind ( predicate: (a: A) => boolean ): (self: Kind) => Kind ( self: Kind, refinement: (a: A) => a is B ): Kind ( self: Kind, predicate: (a: A) => boolean ): Kind } = (Filterable: Filterable) => dual( 2, (self: Kind, predicate: (a: A) => boolean): Kind => Filterable.filterMap(self, (b) => (predicate(b) ? option.some(b) : option.none)) ) /** * @since 1.0.0 */ export const partition = ( F: Filterable ): { (refinement: (a: A) => a is B): ( self: Kind ) => [Kind, Kind] (predicate: (a: A) => boolean): ( self: Kind ) => [Kind, Kind] ( self: Kind, refinement: (a: A) => a is B ): [Kind, Kind] ( self: Kind, predicate: (a: A) => boolean ): [Kind, Kind] } => dual( 2, ( self: Kind, predicate: (a: A) => boolean ): [Kind, Kind] => F.partitionMap(self, (b) => (predicate(b) ? either.right(b) : either.left(b))) ) ================================================ FILE: src/typeclass/FlatMap.ts ================================================ /** * @since 1.0.0 */ import { dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" /** * @category type class * @since 1.0.0 */ export interface FlatMap extends TypeClass { readonly flatMap: { ( f: (a: A) => Kind ): (self: Kind) => Kind ( self: Kind, f: (a: A) => Kind ): Kind } } /** * @since 1.0.0 */ export const flatten = (F: FlatMap) => ( self: Kind> ): Kind => F.flatMap(self, identity) /** * A variant of `flatMap` that ignores the value produced by this effect. * * @since 1.0.0 */ export const andThen = (F: FlatMap): { ( that: Kind ): (self: Kind) => Kind ( self: Kind, that: Kind ): Kind } => dual(2, ( self: Kind, that: Kind ): Kind => F.flatMap(self, () => that)) /** * @since 1.0.0 */ export const composeKleisliArrow = ( F: FlatMap ): { ( bfc: (b: B) => Kind ): ( afb: (a: A) => Kind ) => (a: A) => Kind ( afb: (a: A) => Kind, bfc: (b: B) => Kind ): (a: A) => Kind } => dual( 2, ( afb: (a: A) => Kind, bfc: (b: B) => Kind ): ((a: A) => Kind) => a => F.flatMap(afb(a), bfc) ) ================================================ FILE: src/typeclass/Foldable.ts ================================================ /** * @since 1.0.0 */ import { dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" import type { Coproduct } from "@fp-ts/core/typeclass/Coproduct" import type { Monad } from "@fp-ts/core/typeclass/Monad" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" /** * @category type class * @since 1.0.0 */ export interface Foldable extends TypeClass { readonly reduce: { (b: B, f: (b: B, a: A) => B): (self: Kind) => B (self: Kind, b: B, f: (b: B, a: A) => B): B } } /** * Returns a default ternary `reduce` composition. * * @since 1.0.0 */ export const reduceComposition = ( F: Foldable, G: Foldable ) => ( self: Kind>, b: B, f: (b: B, a: A) => B ): B => F.reduce(self, b, (b, ga) => G.reduce(ga, b, f)) /** * @since 1.0.0 */ export const toArrayMap = ( F: Foldable ): { (f: (a: A) => B): (self: Kind) => Array (self: Kind, f: (a: A) => B): Array } => dual( 2, (self: Kind, f: (a: A) => B): Array => F.reduce(self, [], (out: Array, a) => [...out, f(a)]) ) /** * @since 1.0.0 */ export const toArray = ( F: Foldable ): (self: Kind) => Array => toArrayMap(F)(identity) /** * @since 1.0.0 */ export const combineMap = (F: Foldable) => (M: Monoid): { (f: (a: A) => M): (self: Kind) => M (self: Kind, f: (a: A) => M): M } => dual(2, (self: Kind, f: (a: A) => M): M => F.reduce(self, M.empty, (m, a) => M.combine(m, f(a)))) /** * @since 1.0.0 */ export const reduceKind = (F: Foldable) => (G: Monad): { ( b: B, f: (b: B, a: A) => Kind ): (self: Kind) => Kind ( self: Kind, b: B, f: (b: B, a: A) => Kind ): Kind } => dual(3, ( self: Kind, b: B, f: (b: B, a: A) => Kind ): Kind => F.reduce( self, G.of(b), (gb: Kind, a) => G.flatMap(gb, b => f(b, a)) )) /** * @since 1.0.0 */ export const coproductMapKind = (F: Foldable) => (G: Coproduct): { ( f: (a: A) => Kind ): (self: Kind) => Kind ( self: Kind, f: (a: A) => Kind ): Kind } => dual(2, ( self: Kind, f: (a: A) => Kind ): Kind => F.reduce(self, G.zero(), (gb: Kind, a) => G.coproduct(gb, f(a)))) ================================================ FILE: src/typeclass/Invariant.ts ================================================ /** * The `Invariant` typeclass is a higher-order abstraction over types that allow mapping the contents of a type in both directions. * It is similar to the `Covariant` typeclass but provides an `imap` opration, which allows transforming a value in both directions. * This typeclass is useful when dealing with data types that can be converted to and from some other types. * The `imap` operation provides a way to convert such data types to other types that they can interact with while preserving their invariants. * * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" /** * @category type class * @since 1.0.0 */ export interface Invariant extends TypeClass { readonly imap: { ( to: (a: A) => B, from: (b: B) => A ): (self: Kind) => Kind ( self: Kind, to: (a: A) => B, from: (b: B) => A ): Kind } } /** * Returns a default ternary `imap` composition. * * @since 1.0.0 */ export const imapComposition = ( F: Invariant, G: Invariant ) => ( self: Kind>, to: (a: A) => B, from: (b: B) => A ): Kind> => F.imap(self, G.imap(to, from), G.imap(from, to)) /** * @category do notation * @since 1.0.0 */ export const bindTo = (F: Invariant): { ( name: N ): (self: Kind) => Kind ( self: Kind, name: N ): Kind } => dual(2, ( self: Kind, name: N ): Kind => F.imap(self, a => ({ [name]: a } as any), ({ [name]: a }) => a)) /** * Convert a value in a singleton array in a given effect. * * @since 1.0.0 */ export const tupled = ( F: Invariant ): ((self: Kind) => Kind) => F.imap(a => [a], ([a]) => a) ================================================ FILE: src/typeclass/Monad.ts ================================================ /** * @since 1.0.0 */ import type { TypeLambda } from "@fp-ts/core/HKT" import type { FlatMap } from "@fp-ts/core/typeclass/FlatMap" import type { Pointed } from "@fp-ts/core/typeclass/Pointed" /** * @category type class * @since 1.0.0 */ export interface Monad extends FlatMap, Pointed {} ================================================ FILE: src/typeclass/Monoid.ts ================================================ /** * @since 1.0.0 */ import type { Bounded } from "@fp-ts/core/typeclass/Bounded" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" /** * @category type class * @since 1.0.0 */ export interface Monoid extends Semigroup { readonly empty: A readonly combineAll: (collection: Iterable) => A } /** * @category constructors * @since 1.0.0 */ export const fromSemigroup = (S: Semigroup, empty: Monoid["empty"]): Monoid => ({ combine: S.combine, combineMany: S.combineMany, empty, combineAll: collection => S.combineMany(empty, collection) }) /** * Get a monoid where `combine` will return the minimum, based on the provided bounded order. * * The `empty` value is the `maxBound` value. * * @category constructors * @since 1.0.0 */ export const min = (B: Bounded): Monoid => fromSemigroup(semigroup.min(B), B.maxBound) /** * Get a monoid where `combine` will return the maximum, based on the provided bounded order. * * The `empty` value is the `minimum` value. * * @category constructors * @since 1.0.0 */ export const max = (B: Bounded): Monoid => fromSemigroup(semigroup.max(B), B.minBound) /** * The dual of a `Monoid`, obtained by swapping the arguments of `combine`. * * @category combinators * @since 1.0.0 */ export const reverse = (M: Monoid): Monoid => fromSemigroup(semigroup.reverse(M), M.empty) /** * @category instances * @since 1.0.0 */ export const string: Monoid = fromSemigroup(semigroup.string, "") /** * `number` monoid under addition. * * The `empty` value is `0`. * * @category instances * @since 1.0.0 */ export const numberSum: Monoid = fromSemigroup(semigroup.numberSum, 0) /** * `number` monoid under multiplication. * * The `empty` value is `1`. * * @category instances * @since 1.0.0 */ export const numberMultiply: Monoid = fromSemigroup(semigroup.numberMultiply, 1) /** * `number` monoid under addition. * * The `bigint` value is `0n`. * * @category instances * @since 1.0.0 */ export const bigintSum: Monoid = fromSemigroup(semigroup.bigintSum, 0n) /** * `bigint` monoid under multiplication. * * The `empty` value is `1n`. * * @category instances * @since 1.0.0 */ export const bigintMultiply: Monoid = fromSemigroup(semigroup.bigintMultiply, 1n) /** * `boolean` monoid under conjunction. * * The `empty` value is `true`. * * @category instances * @since 1.0.0 */ export const booleanAll: Monoid = fromSemigroup(semigroup.booleanAll, true) /** * `boolean` monoid under disjunction. * * The `empty` value is `false`. * * @category instances * @since 1.0.0 */ export const booleanAny: Monoid = fromSemigroup(semigroup.booleanAny, false) /** * `boolean` monoid under exclusive disjunction. * * The `empty` value is `false`. * * @category instances * @since 1.0.0 */ export const booleanXor: Monoid = fromSemigroup(semigroup.booleanXor, false) /** * `boolean` monoid under equivalence. * * The `empty` value is `true`. * * @category instances * @since 1.0.0 */ export const booleanEqv: Monoid = fromSemigroup(semigroup.booleanEqv, true) /** * Similar to `Promise.all` but operates on `Monoid`s. * * ``` * [Monoid, Monoid, ...] -> Monoid<[A, B, ...]> * ``` * * This function creates and returns a new `Monoid` for a tuple of values based on the given `Monoid`s for each element in the tuple. * The returned `Monoid` combines two tuples of the same type by applying the corresponding `Monoid` passed as arguments to each element in the tuple. * * The `empty` value of the returned `Monoid` is the tuple of `empty` values of the input `Monoid`s. * * It is useful when you need to combine two tuples of the same type and you have a specific way of combining each element of the tuple. * * @category combinators * @since 1.0.0 */ export const tuple = >>( ...elements: T ): Monoid<{ readonly [I in keyof T]: [T[I]] extends [Monoid] ? A : never }> => { const empty = elements.map((m) => m.empty) as any return fromSemigroup(semigroup.tuple(...elements), empty) } /** * Given a type `A`, this function creates and returns a `Semigroup` for `ReadonlyArray`. * * The `empty` value is the empty array. * * @category combinators * @since 1.0.0 */ export const array = (): Monoid> => fromSemigroup(semigroup.array(), []) /** * This function creates and returns a new `Monoid` for a struct of values based on the given `Monoid`s for each property in the struct. * The returned `Monoid` combines two structs of the same type by applying the corresponding `Monoid` passed as arguments to each property in the struct. * * The `empty` value of the returned `Monoid` is a struct where each property is the `empty` value of the corresponding `Monoid` in the input `monoids` object. * * It is useful when you need to combine two structs of the same type and you have a specific way of combining each property of the struct. * * @category combinators * @since 1.0.0 */ export const struct = }>( fields: R ): Monoid<{ readonly [K in keyof R]: [R[K]] extends [Monoid] ? A : never }> => { const empty = {} as any for (const k in fields) { if (Object.prototype.hasOwnProperty.call(fields, k)) { empty[k] = fields[k].empty } } return fromSemigroup(semigroup.struct(fields), empty) } ================================================ FILE: src/typeclass/Of.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" /** * @category type class * @since 1.0.0 */ export interface Of extends TypeClass { readonly of: (a: A) => Kind } /** * Returns a default `of` composition. * * @since 1.0.0 */ export const ofComposition = ( F: Of, G: Of ) => (a: A): Kind> => F.of(G.of(a)) /** * @since 1.0.0 */ export const unit = ( F: Of ): Kind => F.of(undefined) /** * @category do notation * @since 1.0.0 */ export const Do = ( F: Of ): Kind => F.of({}) ================================================ FILE: src/typeclass/Order.ts ================================================ /** * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { TypeLambda } from "@fp-ts/core/HKT" import * as readonlyArray from "@fp-ts/core/internal/ReadonlyArray" import * as contravariant from "@fp-ts/core/typeclass/Contravariant" import type * as invariant from "@fp-ts/core/typeclass/Invariant" import type { Monoid } from "@fp-ts/core/typeclass/Monoid" import * as monoid from "@fp-ts/core/typeclass/Monoid" import * as product_ from "@fp-ts/core/typeclass/Product" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import type * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" /** * @category type class * @since 1.0.0 */ export interface Order { readonly compare: (self: A, that: A) => -1 | 0 | 1 } /** * @category type lambdas * @since 1.0.0 */ export interface OrderTypeLambda extends TypeLambda { readonly type: Order } /** * @category constructors * @since 1.0.0 */ export const make = ( compare: Order["compare"] ): Order => ({ compare: (self, that) => self === that ? 0 : compare(self, that) }) /** * @category instances * @since 1.0.0 */ export const string: Order = make((self, that) => self < that ? -1 : 1) /** * @category instances * @since 1.0.0 */ export const number: Order = make((self, that) => self < that ? -1 : 1) /** * @category instances * @since 1.0.0 */ export const boolean: Order = make((self, that) => self < that ? -1 : 1) /** * @category instances * @since 1.0.0 */ export const bigint: Order = make((self, that) => self < that ? -1 : 1) /** * @since 1.0.0 */ export const reverse = (O: Order): Order => make((self, that) => O.compare(that, self)) /** * @category instances * @since 1.0.0 */ export const getSemigroup = (): Semigroup> => semigroup.make( (O1, O2) => make((self, that) => { const out = O1.compare(self, that) if (out !== 0) { return out } return O2.compare(self, that) }), (self, collection) => make((a1, a2) => { let out = self.compare(a1, a2) if (out !== 0) { return out } for (const O of collection) { out = O.compare(a1, a2) if (out !== 0) { return out } } return out }) ) const empty: Order = make(() => 0) /** * @category instances * @since 1.0.0 */ export const getMonoid = (): Monoid> => monoid.fromSemigroup(getSemigroup(), empty) /** * @category combinators * @since 1.0.0 */ export const contramap: { (f: (b: B) => A): (self: Order) => Order (self: Order, f: (b: B) => A): Order } = dual( 2, (self: Order, f: (b: B) => A): Order => make((b1, b2) => self.compare(f(b1), f(b2))) ) const imap = contravariant.imap(contramap) /** * @category instances * @since 1.0.0 */ export const Contravariant: contravariant.Contravariant = { imap, contramap } /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } const product = (self: Order, that: Order): Order<[A, B]> => make(([xa, xb], [ya, yb]) => { const o = self.compare(xa, ya) return o !== 0 ? o : that.compare(xb, yb) }) const productAll = (collection: Iterable>): Order> => { const orders = readonlyArray.fromIterable(collection) return make((x, y) => { const len = Math.min(x.length, y.length, orders.length) for (let i = 0; i < len; i++) { const o = orders[i].compare(x[i], y[i]) if (o !== 0) { return o } } return 0 }) } const productMany = ( self: Order, collection: Iterable> ): Order<[A, ...Array]> => { const order = productAll(collection) return make((x, y) => { const o = self.compare(x[0], y[0]) return o !== 0 ? o : order.compare(x.slice(1), y.slice(1)) }) } /** * @category instances * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } const of: (a: A) => Order = () => empty /** * @category instances * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll } /** * Similar to `Promise.all` but operates on `Order`s. * * ``` * [Order, Order, ...] -> Order<[A, B, ...]> * ``` * * This function creates and returns a new `Order` for a tuple of values based on the given `Order`s for each element in the tuple. * The returned `Order` compares two tuples of the same type by applying the corresponding `Order` to each element in the tuple. * It is useful when you need to compare two tuples of the same type and you have a specific way of comparing each element * of the tuple. * * @category combinators * @since 1.0.0 */ export const tuple: >>( ...elements: T ) => Order<{ [I in keyof T]: [T[I]] extends [Order] ? A : never }> = product_.tuple( Product ) /** * This function creates and returns a new `Order` for an array of values based on a given `Order` for the elements of the array. * The returned `Order` compares two arrays by applying the given `Order` to each element in the arrays. * If all elements are equal, the arrays are then compared based on their length. * It is useful when you need to compare two arrays of the same type and you have a specific way of comparing each element of the array. * * @category combinators * @since 1.0.0 */ export const array = (O: Order): Order> => make((self, that) => { const aLen = self.length const bLen = that.length const len = Math.min(aLen, bLen) for (let i = 0; i < len; i++) { const o = O.compare(self[i], that[i]) if (o !== 0) { return o } } return number.compare(aLen, bLen) }) /** * This function creates and returns a new `Order` for a struct of values based on the given `Order`s * for each property in the struct. * * @category combinators * @since 1.0.0 */ export const struct: }>( fields: R ) => Order<{ [K in keyof R]: [R[K]] extends [Order] ? A : never }> = product_.struct( Product ) /** * Test whether one value is _strictly less than_ another. * * @since 1.0.0 */ export const lessThan = (O: Order): { (that: A): (self: A) => boolean (self: A, that: A): boolean } => dual(2, (self: A, that: A) => O.compare(self, that) === -1) /** * Test whether one value is _strictly greater than_ another. * * @since 1.0.0 */ export const greaterThan = (O: Order): { (that: A): (self: A) => boolean (self: A, that: A): boolean } => dual(2, (self: A, that: A) => O.compare(self, that) === 1) /** * Test whether one value is _non-strictly less than_ another. * * @since 1.0.0 */ export const lessThanOrEqualTo = (O: Order): { (that: A): (self: A) => boolean (self: A, that: A): boolean } => dual(2, (self: A, that: A) => O.compare(self, that) !== 1) /** * Test whether one value is _non-strictly greater than_ another. * * @since 1.0.0 */ export const greaterThanOrEqualTo = (O: Order): { (that: A): (self: A) => boolean (self: A, that: A): boolean } => dual(2, (self: A, that: A) => O.compare(self, that) !== -1) /** * Take the minimum of two values. If they are considered equal, the first argument is chosen. * * @since 1.0.0 */ export const min = (O: Order): { (that: A): (self: A) => A (self: A, that: A): A } => dual(2, (self: A, that: A) => self === that || O.compare(self, that) < 1 ? self : that) /** * Take the maximum of two values. If they are considered equal, the first argument is chosen. * * @since 1.0.0 */ export const max = (O: Order): { (that: A): (self: A) => A (self: A, that: A): A } => dual(2, (self: A, that: A) => self === that || O.compare(self, that) > -1 ? self : that) /** * Clamp a value between a minimum and a maximum. * * @since 1.0.0 */ export const clamp = (O: Order): { (minimum: A, maximum: A): (self: A) => A (self: A, minimum: A, maximum: A): A } => dual( 3, (self: A, minimum: A, maximum: A): A => min(O)(maximum, max(O)(minimum, self)) ) /** * Test whether a value is between a minimum and a maximum (inclusive). * * @since 1.0.0 */ export const between = (O: Order): { (minimum: A, maximum: A): (self: A) => boolean (self: A, minimum: A, maximum: A): boolean } => dual( 3, (self: A, minimum: A, maximum: A): boolean => !lessThan(O)(self, minimum) && !greaterThan(O)(self, maximum) ) ================================================ FILE: src/typeclass/Pointed.ts ================================================ /** * @since 1.0.0 */ import type { TypeLambda } from "@fp-ts/core/HKT" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" import type { Of } from "@fp-ts/core/typeclass/Of" /** * @category type class * @since 1.0.0 */ export interface Pointed extends Covariant, Of {} ================================================ FILE: src/typeclass/Product.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Of } from "@fp-ts/core/typeclass/Of" import type { SemiProduct } from "@fp-ts/core/typeclass/SemiProduct" /** * @category type class * @since 1.0.0 */ export interface Product extends SemiProduct, Of { readonly productAll: ( collection: Iterable> ) => Kind> } /** * @since 1.0.0 */ export const tuple = (F: Product) => >>(...elements: T): Kind< F, ([T[number]] extends [Kind] ? R : never), ([T[number]] extends [Kind] ? O : never), ([T[number]] extends [Kind] ? E : never), { [I in keyof T]: [T[I]] extends [Kind] ? A : never } > => F.productAll(elements) as any /** * @since 1.0.0 */ export const struct = (F: Product) => }>(fields: R): Kind< F, ([R[keyof R]] extends [Kind] ? R : never), ([R[keyof R]] extends [Kind] ? O : never), ([R[keyof R]] extends [Kind] ? E : never), { [K in keyof R]: [R[K]] extends [Kind] ? A : never } > => { const keys = Object.keys(fields) return F.imap(F.productAll(keys.map(k => fields[k])), values => { const out: any = {} for (let i = 0; i < values.length; i++) { out[keys[i]] = values[i] } return out }, (r) => keys.map(k => r[k])) } ================================================ FILE: src/typeclass/SemiAlternative.ts ================================================ /** * @since 1.0.0 */ import type { TypeLambda } from "@fp-ts/core/HKT" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" import type { SemiCoproduct } from "@fp-ts/core/typeclass/SemiCoproduct" /** * @category type class * @since 1.0.0 */ export interface SemiAlternative extends SemiCoproduct, Covariant {} ================================================ FILE: src/typeclass/SemiApplicative.ts ================================================ /** * @since 1.0.0 */ import { dual, identity, SK } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import type { SemiProduct } from "@fp-ts/core/typeclass/SemiProduct" /** * @category type class * @since 1.0.0 */ export interface SemiApplicative extends SemiProduct, Covariant {} /** * Lift a `Semigroup` into 'F', the inner values are combined using the provided `Semigroup`. * * @category lifting * @since 1.0.0 */ export const getSemigroup = (F: SemiApplicative) => (S: Semigroup): Semigroup> => semigroup.make( (self, that) => F.map(F.product(self, that), ([a1, a2]) => S.combine(a1, a2)), (self, collection) => F.map(F.productMany(self, collection), ([head, ...tail]) => S.combineMany(head, tail)) ) /** * Zips two `F` values together using a provided function, returning a new `F` of the result. * * @param self - The left-hand side of the zip operation * @param that - The right-hand side of the zip operation * @param f - The function used to combine the values of the two `Option`s * * @since 1.0.0 */ export const zipWith = (F: SemiApplicative): { ( that: Kind, f: (a: A, b: B) => C ): (self: Kind) => Kind ( self: Kind, that: Kind, f: (a: A, b: B) => C ): Kind } => dual( 3, ( self: Kind, that: Kind, f: (a: A, b: B) => C ): Kind => F.map(F.product(self, that), ([a, b]) => f(a, b)) ) /** * @since 1.0.0 */ export const ap = (F: SemiApplicative): { ( that: Kind ): ( self: Kind B> ) => Kind ( self: Kind B>, that: Kind ): Kind } => dual(2, ( self: Kind B>, that: Kind ): Kind => zipWith(F)(self, that, (f, a) => f(a))) /** * @since 1.0.0 */ export const andThenDiscard = (F: SemiApplicative): { ( that: Kind ): (self: Kind) => Kind ( self: Kind, that: Kind ): Kind } => dual(2, ( self: Kind, that: Kind ): Kind => zipWith(F)(self, that, identity)) /** * @since 1.0.0 */ export const andThen = (F: SemiApplicative): { ( that: Kind ): (self: Kind) => Kind ( self: Kind, that: Kind ): Kind } => dual(2, ( self: Kind, that: Kind ): Kind => zipWith(F)(self, that, SK)) /** * Lifts a binary function into `F`. * * @param f - The function to lift. * * @category lifting * @since 1.0.0 */ export const lift2 = (F: SemiApplicative) => (f: (a: A, b: B) => C): { ( that: Kind ): (self: Kind) => Kind ( self: Kind, that: Kind ): Kind } => dual(2, ( self: Kind, that: Kind ): Kind => zipWith(F)(self, that, f)) ================================================ FILE: src/typeclass/SemiCoproduct.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Invariant } from "@fp-ts/core/typeclass/Invariant" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" /** * @category type class * @since 1.0.0 */ export interface SemiCoproduct extends Invariant { readonly coproduct: ( self: Kind, that: Kind ) => Kind readonly coproductMany: ( self: Kind, collection: Iterable> ) => Kind } /** * @since 1.0.0 */ export const getSemigroup = (F: SemiCoproduct) => (): Semigroup> => ({ combine: F.coproduct, combineMany: F.coproductMany }) ================================================ FILE: src/typeclass/SemiProduct.ts ================================================ /** * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" import type { Invariant } from "@fp-ts/core/typeclass/Invariant" import type { SemiApplicative } from "@fp-ts/core/typeclass/SemiApplicative" /** * @category type class * @since 1.0.0 */ export interface SemiProduct extends Invariant { readonly product: ( self: Kind, that: Kind ) => Kind readonly productMany: ( self: Kind, collection: Iterable> ) => Kind]> } /** * Returns a default `productMany` implementation. * * @category constructors * @since 1.0.0 */ export const productMany = ( map: Covariant["map"], product: SemiProduct["product"] ): SemiProduct["productMany"] => ( self: Kind, collection: Iterable> ) => { let out = map(self, (a): [A, ...Array] => [a]) for (const fa of collection) { out = map( product(out, fa), ([[head, ...tail], a]): [A, ...Array] => [head, ...tail, a] ) } return out } /** * Returns a default `product` composition. * * @since 1.0.0 */ export const productComposition = ( F: SemiApplicative, G: SemiProduct ) => ( self: Kind>, that: Kind> ): Kind< F, FR1 & FR2, FO1 | FO2, FE1 | FE2, Kind > => F.map(F.product(self, that), ([ga, gb]) => G.product(ga, gb)) /** * Returns a default `productMany` composition. * * @since 1.0.0 */ export const productManyComposition = ( F: SemiApplicative, G: SemiProduct ) => ( self: Kind>, collection: Iterable>> ): Kind]>> => F.map(F.productMany(self, collection), ([ga, ...gas]) => G.productMany(ga, gas)) /** * @category do notation * @since 1.0.0 */ export const andThenBind = (F: SemiProduct): { ( name: Exclude, that: Kind ): ( self: Kind ) => Kind ( self: Kind, name: Exclude, that: Kind ): Kind } => dual(3, ( self: Kind, name: Exclude, that: Kind ): Kind => F.imap( F.product(self, that), ([a, b]) => Object.assign({}, a, { [name]: b }) as any, ({ [name]: b, ...rest }) => [rest, b] as any )) /** * Appends an element to the end of a tuple. * * @since 1.0.0 */ export const appendElement = (F: SemiProduct): { ( that: Kind ): >( self: Kind ) => Kind , R2, O2, E2, B>( self: Kind, that: Kind ): Kind } => dual(2, , R2, O2, E2, B>( self: Kind, that: Kind ): Kind => F.imap(F.product(self, that), ([a, b]) => [...a, b], ab => [ab.slice(0, -1), ab[ab.length - 1]] as any)) /** * @since 1.0.0 */ export const nonEmptyTuple = (F: SemiProduct) => , ...Array>]>( ...elements: T ): Kind< F, ([T[number]] extends [Kind] ? R : never), ([T[number]] extends [Kind] ? O : never), ([T[number]] extends [Kind] ? E : never), { [I in keyof T]: [T[I]] extends [Kind] ? A : never } > => F.productMany(elements[0], elements.slice(1)) as any type EnforceNonEmptyRecord = keyof R extends never ? never : R /** * @since 1.0.0 */ export const nonEmptyStruct = (F: SemiProduct) => }>( fields: EnforceNonEmptyRecord & { readonly [x: string]: Kind } ): Kind< F, ([R[keyof R]] extends [Kind] ? R : never), ([R[keyof R]] extends [Kind] ? O : never), ([R[keyof R]] extends [Kind] ? E : never), { [K in keyof R]: [R[K]] extends [Kind] ? A : never } > => { const keys = Object.keys(fields) return F.imap( F.productMany(fields[keys[0]], keys.slice(1).map(k => fields[k])), ([value, ...values]) => { const out: any = { [keys[0]]: value } for (let i = 0; i < values.length; i++) { out[keys[i + 1]] = values[i] } return out }, (r) => keys.map(k => r[k]) as any ) } ================================================ FILE: src/typeclass/Semigroup.ts ================================================ /** * @since 1.0.0 */ import { dual } from "@fp-ts/core/Function" import type { TypeLambda } from "@fp-ts/core/HKT" import { fromIterable } from "@fp-ts/core/internal/ReadonlyArray" import * as readonlyArray from "@fp-ts/core/internal/ReadonlyArray" import type * as invariant from "@fp-ts/core/typeclass/Invariant" import type { Order } from "@fp-ts/core/typeclass/Order" import * as product_ from "@fp-ts/core/typeclass/Product" import type * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" /** * @category type class * @since 1.0.0 */ export interface Semigroup { readonly combine: (self: A, that: A) => A readonly combineMany: (self: A, collection: Iterable) => A } /** * @category type lambdas * @since 1.0.0 */ export interface SemigroupTypeLambda extends TypeLambda { readonly type: Semigroup } /** * @param combineMany - Useful when `combineMany` can be optimised * * @category constructors * @since 1.0.0 */ export const make = ( combine: Semigroup["combine"], combineMany: Semigroup["combineMany"] = (self, collection) => fromIterable(collection).reduce(combine, self) ): Semigroup => ({ combine, combineMany }) /** * @category instances * @since 1.0.0 */ export const string: Semigroup = make((self, that) => self + that) /** * `number` semigroup under addition. * * @category instances * @since 1.0.0 */ export const numberSum: Semigroup = make((self, that) => self + that) /** * `number` semigroup under multiplication. * * @category instances * @since 1.0.0 */ export const numberMultiply: Semigroup = make( (self, that) => self * that, (self, collection) => { if (self === 0) { return 0 } let out = self for (const n of collection) { if (n === 0) { return 0 } out = out * n } return out } ) /** * `bigint` semigroup under addition. * * @category instances * @since 1.0.0 */ export const bigintSum: Semigroup = make((self, that) => self + that) /** * `bigint` semigroup under multiplication. * * @category instances * @since 1.0.0 */ export const bigintMultiply: Semigroup = make( (self, that) => self * that, (self, collection) => { if (self === 0n) { return 0n } let out = self for (const n of collection) { if (n === 0n) { return 0n } out = out * n } return out } ) /** * `boolean` semigroup under conjunction. * * @category instances * @since 1.0.0 */ export const booleanAll: Semigroup = make( (self, that) => self && that, (self, collection) => { if (self === false) { return false } for (const b of collection) { if (b === false) { return false } } return true } ) /** * `boolean` semigroup under disjunction. * * @category instances * @since 1.0.0 */ export const booleanAny: Semigroup = make( (self, that) => self || that, (self, collection) => { if (self === true) { return true } for (const b of collection) { if (b === true) { return true } } return false } ) /** * `boolean` semigroup under exclusive disjunction. * * @category instances * @since 1.0.0 */ export const booleanXor: Semigroup = make((self, that) => self !== that) /** * `boolean` semigroup under equivalence. * * @category instances * @since 1.0.0 */ export const booleanEqv: Semigroup = make((self, that) => self === that) /** * `Semigroup` that returns last minimum of elements. * * @category constructors * @since 1.0.0 */ export const min = (O: Order): Semigroup => make((self, that) => O.compare(self, that) === -1 ? self : that) /** * `Semigroup` that returns last maximum of elements. * * @category constructors * @since 1.0.0 */ export const max = (O: Order): Semigroup => make((self, that) => O.compare(self, that) === 1 ? self : that) /** * @category constructors * @since 1.0.0 */ export const constant = (a: A): Semigroup => make(() => a, () => a) /** * The dual of a `Semigroup`, obtained by flipping the arguments of `combine`. * * @since 1.0.0 */ export const reverse = (S: Semigroup): Semigroup => make( (self, that) => S.combine(that, self), (self, collection) => { const reversed = Array.from(collection).reverse() return reversed.length > 0 ? S.combine(S.combineMany(reversed[0], reversed.slice(1)), self) : self } ) /** * @since 1.0.0 */ export const intercalate: { (separator: A): (S: Semigroup) => Semigroup (S: Semigroup, separator: A): Semigroup } = dual( 2, (S: Semigroup, separator: A): Semigroup => make((self, that) => S.combineMany(self, [separator, that])) ) /** * Always return the first argument. * * @category instances * @since 1.0.0 */ export const first = (): Semigroup => make((a) => a, (a) => a) /** * Always return the last argument. * * @category instances * @since 1.0.0 */ export const last = (): Semigroup => make( (_, second) => second, (self, collection) => { let a: A = self // eslint-disable-next-line no-empty for (a of collection) {} return a } ) /** * @since 1.0.0 */ export const imap: { (to: (a: A) => B, from: (b: B) => A): (self: Semigroup) => Semigroup (self: Semigroup, to: (a: A) => B, from: (b: B) => A): Semigroup } = dual(3, (S: Semigroup, to: (a: A) => B, from: (b: B) => A): Semigroup => make( (self, that) => to(S.combine(from(self), from(that))), (self, collection) => to(S.combineMany(from(self), (fromIterable(collection)).map(from))) )) /** * @category instances * @since 1.0.0 */ export const Invariant: invariant.Invariant = { imap } const product = (self: Semigroup, that: Semigroup): Semigroup<[A, B]> => make(([xa, xb], [ya, yb]) => [self.combine(xa, ya), that.combine(xb, yb)]) const productAll = (collection: Iterable>): Semigroup> => { const semigroups = readonlyArray.fromIterable(collection) return make((x, y) => { const len = Math.min(x.length, y.length, semigroups.length) const out: Array = [] for (let i = 0; i < len; i++) { out.push(semigroups[i].combine(x[i], y[i])) } return out }) } const productMany = ( self: Semigroup, collection: Iterable> ): Semigroup<[A, ...Array]> => { const semigroup = productAll(collection) return make((x, y) => [self.combine(x[0], y[0]), ...semigroup.combine(x.slice(1), y.slice(1))]) } /** * @category instances * @since 1.0.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } const of: (a: A) => Semigroup = constant /** * @category instances * @since 1.0.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll } /** * Similar to `Promise.all` but operates on `Semigroup`s. * * ``` * [Semigroup, Semigroup, ...] -> Semigroup<[A, B, ...]> * ``` * * This function creates and returns a new `Semigroup` for a tuple of values based on the given `Semigroup`s for each element in the tuple. * The returned `Semigroup` combines two tuples of the same type by applying the corresponding `Semigroup` passed as arguments to each element in the tuple. * * It is useful when you need to combine two tuples of the same type and you have a specific way of combining each element of the tuple. * * @category combinators * @since 1.0.0 */ export const tuple: >>( ...elements: T ) => Semigroup<{ readonly [I in keyof T]: [T[I]] extends [Semigroup] ? A : never }> = product_.tuple(Product) /** * Given a type `A`, this function creates and returns a `Semigroup` for `ReadonlyArray`. * The returned `Semigroup` combines two arrays by concatenating them. * * @category combinators * @since 1.0.0 */ export const array = (): Semigroup> => make((self, that) => self.concat(that)) /** * This function creates and returns a new `Semigroup` for a struct of values based on the given `Semigroup`s for each property in the struct. * The returned `Semigroup` combines two structs of the same type by applying the corresponding `Semigroup` passed as arguments to each property in the struct. * * It is useful when you need to combine two structs of the same type and you have a specific way of combining each property of the struct. * * @category combinators * @since 1.0.0 */ export const struct: }>( fields: R ) => Semigroup<{ readonly [K in keyof R]: [R[K]] extends [Semigroup] ? A : never }> = product_.struct(Product) ================================================ FILE: src/typeclass/Traversable.ts ================================================ /** * @since 1.0.0 */ import { dual, identity } from "@fp-ts/core/Function" import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" import type { Applicative } from "@fp-ts/core/typeclass/Applicative" /** * @category type class * @since 1.0.0 */ export interface Traversable extends TypeClass { readonly traverse: ( F: Applicative ) => { ( f: (a: A) => Kind ): (self: Kind) => Kind> ( self: Kind, f: (a: A) => Kind ): Kind> } } /** * Returns a default binary `traverse` composition. * * @since 1.0.0 */ export const traverseComposition = ( T: Traversable, G: Traversable ) => (F: Applicative) => ( self: Kind>, f: (a: A) => Kind ): Kind>> => T.traverse(F)(self, G.traverse(F)(f)) /** * Returns a default `sequence` implementation. * * @since 1.0.0 */ export const sequence = (T: Traversable) => (F: Applicative) => ( self: Kind> ): Kind> => T.traverse(F)(self, identity) /** * Given a function which returns a `F` effect, thread this effect * through the running of this function on all the values in `T`, * returning an `T` in a `F` context, ignoring the values * returned by the provided function. * * @since 1.0.0 */ export const traverseTap = (T: Traversable) => (F: Applicative): { ( f: (a: A) => Kind ): (self: Kind) => Kind> ( self: Kind, f: (a: A) => Kind ): Kind> } => dual(2, ( self: Kind, f: (a: A) => Kind ): Kind> => T.traverse(F)(self, a => F.map(f(a), () => a))) ================================================ FILE: src/typeclass/TraversableFilterable.ts ================================================ /** * `TraversableFilterable` represents data structures which can be _partitioned_ with effects in some `Applicative` functor. * * @since 1.0.0 */ import type { Either } from "@fp-ts/core/Either" import * as E from "@fp-ts/core/Either" import { dual } from "@fp-ts/core/Function" import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" import type { Option } from "@fp-ts/core/Option" import * as O from "@fp-ts/core/Option" import type { TraversableFilterable } from "@fp-ts/core/ReadonlyArray" import type { Applicative } from "@fp-ts/core/typeclass/Applicative" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" import * as filterable from "@fp-ts/core/typeclass/Filterable" import type { Filterable } from "@fp-ts/core/typeclass/Filterable" import type { Traversable } from "@fp-ts/core/typeclass/Traversable" /** * @category models * @since 1.0.0 */ export interface TraversableFilterable extends TypeClass { readonly traversePartitionMap: ( F: Applicative ) => { ( f: (a: A) => Kind> ): ( self: Kind ) => Kind, Kind]> ( self: Kind, f: (a: A) => Kind> ): Kind, Kind]> } readonly traverseFilterMap: ( F: Applicative ) => { ( f: (a: A) => Kind> ): (self: Kind) => Kind> ( self: Kind, f: (a: A) => Kind> ): Kind> } } /** * Returns a default binary `traversePartitionMap` implementation. * * @since 1.0.0 */ export const traversePartitionMap = ( T: Traversable & Covariant & Filterable ): ( F: Applicative ) => ( self: Kind, f: (a: A) => Kind> ) => Kind, Kind]> => (F) => (self, f) => F.map(T.traverse(F)(self, f), filterable.separate(T)) /** * Returns a default binary `traverseFilterMap` implementation. * * @since 1.0.0 */ export const traverseFilterMap = ( T: Traversable & Filterable ): ( F: Applicative ) => ( self: Kind, f: (a: A) => Kind> ) => Kind> => (F) => (self, f) => F.map(T.traverse(F)(self, f), filterable.compact(T)) /** * @since 1.0.0 */ export const traverseFilter = ( T: TraversableFilterable ) => ( F: Applicative ): { ( predicate: (a: A) => Kind ): ( self: Kind ) => Kind> ( self: Kind, predicate: (a: A) => Kind ): Kind> } => dual(2, ( self: Kind, predicate: (a: A) => Kind ): Kind> => T.traverseFilterMap(F)(self, (b) => F.map(predicate(b), (keep) => (keep ? O.some(b) : O.none())))) /** * @since 1.0.0 */ export const traversePartition = ( T: TraversableFilterable ) => ( F: Applicative ): { ( predicate: (a: A) => Kind ): ( self: Kind ) => Kind, Kind]> ( self: Kind, predicate: (a: A) => Kind ): Kind, Kind]> } => dual(2, (self, predicate) => T.traversePartitionMap(F)(self, (b) => F.map(predicate(b), (keep) => (keep ? E.right(b) : E.left(b))))) ================================================ FILE: test/Bigint.ts ================================================ import * as Bigint from "@fp-ts/core/Bigint" import { pipe } from "@fp-ts/core/Function" import { deepStrictEqual } from "@fp-ts/core/test/util" describe.concurrent("Bigint", () => { it("exports", () => { expect(Bigint.SemigroupMax).exists expect(Bigint.SemigroupMin).exists expect(Bigint.sumAll).exists expect(Bigint.multiplyAll).exists expect(Bigint.lessThan).exists expect(Bigint.lessThanOrEqualTo).exists expect(Bigint.greaterThan).exists expect(Bigint.greaterThanOrEqualTo).exists expect(Bigint.between).exists expect(Bigint.clamp).exists expect(Bigint.min).exists expect(Bigint.max).exists }) it("sign", () => { assert.deepStrictEqual(Bigint.sign(-5n), -1) assert.deepStrictEqual(Bigint.sign(0n), 0) assert.deepStrictEqual(Bigint.sign(5n), 1) }) it("isBigint", () => { expect(Bigint.isBigint(1n)).toEqual(true) expect(Bigint.isBigint(1)).toEqual(false) expect(Bigint.isBigint("a")).toEqual(false) expect(Bigint.isBigint(true)).toEqual(false) }) it("sum", () => { deepStrictEqual(pipe(1n, Bigint.sum(2n)), 3n) }) it("multiply", () => { deepStrictEqual(pipe(2n, Bigint.multiply(3n)), 6n) }) it("subtract", () => { deepStrictEqual(pipe(3n, Bigint.subtract(1n)), 2n) }) it("divide", () => { deepStrictEqual(pipe(6n, Bigint.divide(2n)), 3n) }) it("increment", () => { deepStrictEqual(Bigint.increment(2n), 3n) }) it("decrement", () => { deepStrictEqual(Bigint.decrement(2n), 1n) }) it("Equivalence", () => { expect(Bigint.Equivalence(1n, 1n)).toBe(true) expect(Bigint.Equivalence(1n, 2n)).toBe(false) }) it("Order", () => { deepStrictEqual(Bigint.Order.compare(1n, 2n), -1) deepStrictEqual(Bigint.Order.compare(2n, 1n), 1) deepStrictEqual(Bigint.Order.compare(2n, 2n), 0) }) it("SemigroupSum", () => { deepStrictEqual(Bigint.SemigroupSum.combine(2n, 3n), 5n) }) it("MonoidSum", () => { deepStrictEqual(Bigint.MonoidSum.combineAll([1n, 2n, 3n]), 6n) }) it("SemigroupMultiply", () => { deepStrictEqual(Bigint.SemigroupMultiply.combine(2n, 3n), 6n) deepStrictEqual(Bigint.SemigroupMultiply.combineMany(0n, [1n, 2n, 3n]), 0n) deepStrictEqual(Bigint.SemigroupMultiply.combineMany(2n, [1n, 0n, 3n]), 0n) }) it("MonoidMultiply", () => { deepStrictEqual(Bigint.MonoidMultiply.combineAll([2n, 3n, 4n]), 24n) }) }) ================================================ FILE: test/Boolean.ts ================================================ import * as Boolean from "@fp-ts/core/Boolean" import { pipe } from "@fp-ts/core/Function" import { deepStrictEqual } from "@fp-ts/core/test/util" describe.concurrent("Boolean", () => { it("exports", () => { expect(Boolean.SemigroupAll).exist expect(Boolean.MonoidAll).exist expect(Boolean.SemigroupAny).exist expect(Boolean.MonoidAny).exist expect(Boolean.SemigroupXor).exist expect(Boolean.MonoidXor).exist expect(Boolean.SemigroupEqv).exist expect(Boolean.MonoidEqv).exist expect(Boolean.all).exist expect(Boolean.any).exist expect(Boolean.xor).exist expect(Boolean.eqv).exist expect(Boolean.nand).exist expect(Boolean.nor).exist expect(Boolean.implies).exist }) it("isBoolean", () => { expect(Boolean.isBoolean(true)).toEqual(true) expect(Boolean.isBoolean(false)).toEqual(true) expect(Boolean.isBoolean("a")).toEqual(false) expect(Boolean.isBoolean(1)).toEqual(false) }) it("and", () => { deepStrictEqual(pipe(true, Boolean.and(true)), true) deepStrictEqual(pipe(true, Boolean.and(false)), false) deepStrictEqual(pipe(false, Boolean.and(true)), false) deepStrictEqual(pipe(false, Boolean.and(false)), false) }) it("nand", () => { deepStrictEqual(pipe(true, Boolean.nand(true)), false) deepStrictEqual(pipe(true, Boolean.nand(false)), true) deepStrictEqual(pipe(false, Boolean.nand(true)), true) deepStrictEqual(pipe(false, Boolean.nand(false)), true) }) it("or", () => { deepStrictEqual(pipe(true, Boolean.or(true)), true) deepStrictEqual(pipe(true, Boolean.or(false)), true) deepStrictEqual(pipe(false, Boolean.or(true)), true) deepStrictEqual(pipe(false, Boolean.or(false)), false) }) it("nor", () => { deepStrictEqual(pipe(true, Boolean.nor(true)), false) deepStrictEqual(pipe(true, Boolean.nor(false)), false) deepStrictEqual(pipe(false, Boolean.nor(true)), false) deepStrictEqual(pipe(false, Boolean.nor(false)), true) }) it("xor", () => { deepStrictEqual(pipe(true, Boolean.xor(true)), false) deepStrictEqual(pipe(true, Boolean.xor(false)), true) deepStrictEqual(pipe(false, Boolean.xor(true)), true) deepStrictEqual(pipe(false, Boolean.xor(false)), false) }) it("eqv", () => { deepStrictEqual(pipe(true, Boolean.eqv(true)), true) deepStrictEqual(pipe(true, Boolean.eqv(false)), false) deepStrictEqual(pipe(false, Boolean.eqv(true)), false) deepStrictEqual(pipe(false, Boolean.eqv(false)), true) }) it("implies", () => { deepStrictEqual(pipe(true, Boolean.implies(true)), true) deepStrictEqual(pipe(true, Boolean.implies(false)), false) deepStrictEqual(pipe(false, Boolean.implies(true)), true) deepStrictEqual(pipe(false, Boolean.implies(false)), true) }) it("not", () => { deepStrictEqual(pipe(true, Boolean.not), false) deepStrictEqual(pipe(false, Boolean.not), true) }) describe.concurrent("MonoidXor", () => { it("baseline", () => { deepStrictEqual(Boolean.MonoidXor.combineMany(true, []), true) deepStrictEqual(Boolean.MonoidXor.combineMany(false, []), false) deepStrictEqual(Boolean.MonoidXor.combineMany(false, [true]), true) deepStrictEqual(Boolean.MonoidXor.combineMany(false, [false]), false) deepStrictEqual(Boolean.MonoidXor.combineMany(true, [true]), false) deepStrictEqual(Boolean.MonoidXor.combineMany(true, [false]), true) deepStrictEqual(Boolean.MonoidXor.combineMany(true, [true, false]), false) deepStrictEqual(Boolean.MonoidXor.combineMany(true, [false, true]), false) deepStrictEqual(Boolean.MonoidXor.combineAll([true, false]), true) deepStrictEqual(Boolean.MonoidXor.combineAll([false, true]), true) }) it("should handle iterables", () => { deepStrictEqual(Boolean.MonoidXor.combineAll(new Set([true, true])), true) deepStrictEqual(Boolean.MonoidXor.combineAll(new Set([true, false])), true) deepStrictEqual(Boolean.MonoidXor.combineAll(new Set([false, false])), false) }) }) describe.concurrent("MonoidEqv", () => { it("baseline", () => { deepStrictEqual(Boolean.MonoidEqv.combineMany(true, []), true) deepStrictEqual(Boolean.MonoidEqv.combineMany(false, []), false) deepStrictEqual(Boolean.MonoidEqv.combineMany(false, [true]), false) deepStrictEqual(Boolean.MonoidEqv.combineMany(false, [false]), true) deepStrictEqual(Boolean.MonoidEqv.combineMany(true, [true]), true) deepStrictEqual(Boolean.MonoidEqv.combineMany(true, [false]), false) deepStrictEqual(Boolean.MonoidEqv.combineMany(true, [true, false]), false) deepStrictEqual(Boolean.MonoidEqv.combineMany(true, [false, true]), false) deepStrictEqual(Boolean.MonoidEqv.combineAll([true, false]), false) deepStrictEqual(Boolean.MonoidEqv.combineAll([false, true]), false) }) it("should handle iterables", () => { deepStrictEqual(Boolean.MonoidEqv.combineAll(new Set([true, true])), true) deepStrictEqual(Boolean.MonoidEqv.combineAll(new Set([true, false])), false) deepStrictEqual(Boolean.MonoidEqv.combineAll(new Set([false, false])), false) }) }) describe.concurrent("MonoidAll", () => { it("baseline", () => { deepStrictEqual(Boolean.MonoidAll.combineMany(true, [true, true]), true) deepStrictEqual(Boolean.MonoidAll.combineMany(true, [true, false]), false) deepStrictEqual(Boolean.MonoidAll.combineMany(false, [true, false]), false) deepStrictEqual(Boolean.MonoidAll.combineAll([true, true, true]), true) deepStrictEqual(Boolean.MonoidAll.combineAll([true, true, false]), false) }) it("should handle iterables", () => { deepStrictEqual(Boolean.MonoidAll.combineAll(new Set([true, true])), true) deepStrictEqual(Boolean.MonoidAll.combineAll(new Set([true, false])), false) deepStrictEqual(Boolean.MonoidAll.combineAll(new Set([false, false])), false) }) }) describe.concurrent("MonoidAny", () => { it("baseline", () => { deepStrictEqual(Boolean.MonoidAny.combineMany(true, [true, true]), true) deepStrictEqual(Boolean.MonoidAny.combineMany(true, [true, false]), true) deepStrictEqual(Boolean.MonoidAny.combineMany(false, [false, false]), false) deepStrictEqual(Boolean.MonoidAny.combineAll([true, true, true]), true) deepStrictEqual(Boolean.MonoidAny.combineAll([true, true, false]), true) deepStrictEqual(Boolean.MonoidAny.combineAll([false, false, false]), false) }) it("should handle iterables", () => { deepStrictEqual(Boolean.MonoidAny.combineAll(new Set([true, true])), true) deepStrictEqual(Boolean.MonoidAny.combineAll(new Set([true, false])), true) deepStrictEqual(Boolean.MonoidAny.combineAll(new Set([false, false])), false) }) }) it("match", () => { const match = Boolean.match(() => "false", () => "true") deepStrictEqual(match(true), "true") deepStrictEqual(match(false), "false") }) it("Equivalence", () => { expect(Boolean.Equivalence(true, true)).toBe(true) expect(Boolean.Equivalence(false, false)).toBe(true) expect(Boolean.Equivalence(true, false)).toBe(false) expect(Boolean.Equivalence(false, true)).toBe(false) }) it("Order", () => { deepStrictEqual(Boolean.Order.compare(false, true), -1) deepStrictEqual(Boolean.Order.compare(true, false), 1) deepStrictEqual(Boolean.Order.compare(true, true), 0) }) }) ================================================ FILE: test/Either.ts ================================================ import * as E from "@fp-ts/core/Either" import { flow, identity, pipe } from "@fp-ts/core/Function" import { structural } from "@fp-ts/core/internal/effect" import * as N from "@fp-ts/core/Number" import * as O from "@fp-ts/core/Option" import * as S from "@fp-ts/core/String" import * as Util from "@fp-ts/core/test/util" describe.concurrent("Either", () => { it("exports", () => { expect(E.toOption).exist expect(E.getRight).exist expect(E.getLeft).exist expect(E.Invariant).exist expect(E.tupled).exist expect(E.bindTo).exist expect(E.Covariant).exist expect(E.map).exist expect(E.let).exist expect(E.flap).exist expect(E.as).exist expect(E.asUnit).exist expect(E.Bicovariant).exist expect(E.bimap).exist expect(E.mapLeft).exist expect(E.Of).exist expect(E.of).exist expect(E.unit).exist expect(E.Do).exist expect(E.Pointed).exist expect(E.FlatMap).exist expect(E.flatMap).exist expect(E.flatten).exist expect(E.andThen).exist expect(E.composeKleisliArrow).exist expect(E.Chainable).exist expect(E.bind).exist expect(E.tap).exist expect(E.andThenDiscard).exist expect(E.Monad).exist expect(E.SemiProduct).exist expect(E.Product).exist expect(E.all).exist expect(E.tuple).exist expect(E.struct).exist expect(E.SemiApplicative).exist expect(E.getFirstLeftSemigroup).exist // liftSemigroup expect(E.lift2).exist expect(E.ap).exist expect(E.andThenDiscard).exist expect(E.andThen).exist expect(E.Applicative).exist expect(E.getFirstLeftMonoid).exist // liftMonoid expect(E.SemiCoproduct).exist expect(E.getFirstRightSemigroup).exist // getSemigroup expect(E.SemiAlternative).exist expect(E.Foldable).exist expect(E.Traversable).exist expect(E.traverse).exist expect(E.sequence).exist expect(E.traverseTap).exist }) it("structural tracking", () => { expect(Util.ownKeys(E.left("a"))).toEqual(["_tag", "left"]) expect(Util.ownKeys(E.right(1))).toEqual(["_tag", "right"]) expect(Object.prototype.hasOwnProperty.call(E.left("a"), structural)).toEqual(false) expect(Object.prototype.hasOwnProperty.call(E.right(1), structural)).toEqual(false) expect(Util.isStructural(E.left("a"))).toEqual(true) expect(Util.isStructural(E.right(1))).toEqual(true) }) it("toRefinement", () => { const f = (s: string | number): E.Either => typeof s === "string" ? E.right(s) : E.left("not a string") const isString = E.toRefinement(f) Util.deepStrictEqual(isString("s"), true) Util.deepStrictEqual(isString(1), false) type A = { readonly type: "A" } type B = { readonly type: "B" } type C = A | B const isA = E.toRefinement(( c: C ) => (c.type === "A" ? E.right(c) : E.left("not as A"))) Util.deepStrictEqual(isA({ type: "A" }), true) Util.deepStrictEqual(isA({ type: "B" }), false) }) it("isEither", () => { Util.deepStrictEqual(pipe(E.right(1), E.isEither), true) Util.deepStrictEqual(pipe(E.left("e"), E.isEither), true) Util.deepStrictEqual(pipe(O.some(1), E.isEither), false) }) it("orElseFail", () => { Util.deepStrictEqual(pipe(E.right(1), E.orElseFail(() => "e2")), E.right(1)) Util.deepStrictEqual(pipe(E.left("e1"), E.orElseFail(() => "e2")), E.left("e2")) }) it("reduce", () => { Util.deepStrictEqual(pipe(E.right("bar"), E.Foldable.reduce("foo", (b, a) => b + a)), "foobar") Util.deepStrictEqual(pipe(E.left("bar"), E.Foldable.reduce("foo", (b, a) => b + a)), "foo") }) it("getRight", () => { Util.deepStrictEqual(pipe(E.right(1), E.getRight), O.some(1)) Util.deepStrictEqual(pipe(E.left("a"), E.getRight), O.none()) }) it("getLeft", () => { Util.deepStrictEqual(pipe(E.right(1), E.getLeft), O.none()) Util.deepStrictEqual(pipe(E.left("e"), E.getLeft), O.some("e")) }) it("getOrNull", () => { Util.deepStrictEqual(pipe(E.right(1), E.getOrNull), 1) Util.deepStrictEqual(pipe(E.left("a"), E.getOrNull), null) }) it("getOrUndefined", () => { Util.deepStrictEqual(pipe(E.right(1), E.getOrUndefined), 1) Util.deepStrictEqual(pipe(E.left("a"), E.getOrUndefined), undefined) }) it("compact", () => { Util.deepStrictEqual(pipe(E.right(O.some(1)), E.compact(() => "e2")), E.right(1)) Util.deepStrictEqual(pipe(E.right(O.none()), E.compact(() => "e2")), E.left("e2")) Util.deepStrictEqual(pipe(E.left("e1"), E.compact(() => "e2")), E.left("e1")) }) it("inspectRight", () => { const log: Array = [] pipe(E.right(1), E.inspectRight((e) => log.push(e))) pipe(E.left("e"), E.inspectRight((e) => log.push(e))) Util.deepStrictEqual(log, [1]) }) it("tapError", () => { Util.deepStrictEqual(pipe(E.right(1), E.tapError(() => E.right(2))), E.right(1)) Util.deepStrictEqual(pipe(E.left("a"), E.tapError(() => E.right(2))), E.left("a")) Util.deepStrictEqual(pipe(E.left("a"), E.tapError(() => E.left("b"))), E.left("b")) }) it("inspectLeft", () => { const log: Array = [] pipe(E.right(1), E.inspectLeft((e) => log.push(e))) pipe(E.left("e"), E.inspectLeft((e) => log.push(e))) Util.deepStrictEqual(log, ["e"]) }) it("getOrThrow", () => { expect(pipe(E.right(1), E.getOrThrow)).toEqual(1) expect(() => pipe(E.left("e"), E.getOrThrow)).toThrowError( new Error("getOrThrow called on a Left") ) }) it("getOrThrowWith", () => { expect(pipe(E.right(1), E.getOrThrowWith((e) => new Error(`Unexpected Left: ${e}`)))).toEqual(1) expect(() => pipe(E.left("e"), E.getOrThrowWith((e) => new Error(`Unexpected Left: ${e}`)))) .toThrowError( new Error("Unexpected Left: e") ) }) it("andThenDiscard", () => { Util.deepStrictEqual(pipe(E.right(1), E.andThenDiscard(E.right("a"))), E.right(1)) Util.deepStrictEqual(pipe(E.right(1), E.andThenDiscard(E.left(true))), E.left(true)) Util.deepStrictEqual(pipe(E.left(1), E.andThenDiscard(E.right("a"))), E.left(1)) Util.deepStrictEqual(pipe(E.left(1), E.andThenDiscard(E.left(true))), E.left(1)) }) it("andThen", () => { Util.deepStrictEqual(pipe(E.right(1), E.andThen(E.right("a"))), E.right("a")) Util.deepStrictEqual(pipe(E.right(1), E.andThen(E.left(true))), E.left(true)) Util.deepStrictEqual(pipe(E.left(1), E.andThen(E.right("a"))), E.left(1)) Util.deepStrictEqual(pipe(E.left(1), E.andThen(E.left(true))), E.left(1)) }) it("orElse", () => { Util.deepStrictEqual(pipe(E.right(1), E.orElse(() => E.right(2))), E.right(1)) Util.deepStrictEqual(pipe(E.right(1), E.orElse(() => E.left("b"))), E.right(1)) Util.deepStrictEqual(pipe(E.left("a"), E.orElse(() => E.right(2))), E.right(2)) Util.deepStrictEqual(pipe(E.left("a"), E.orElse(() => E.left("b"))), E.left("b")) }) it("orElseEither", () => { expect(pipe(E.right(1), E.orElseEither(() => E.right(2)))).toEqual(E.right(E.left(1))) expect(pipe(E.right(1), E.orElseEither(() => E.left("b")))).toEqual(E.right(E.left(1))) expect(pipe(E.left("a"), E.orElseEither(() => E.right(2)))).toEqual(E.right(E.right(2))) expect(pipe(E.left("a"), E.orElseEither(() => E.left("b")))).toEqual(E.left("b")) }) it("map", () => { const f = E.map(S.length) Util.deepStrictEqual(pipe(E.right("abc"), f), E.right(3)) Util.deepStrictEqual(pipe(E.left("s"), f), E.left("s")) }) it("flatMap", () => { const f = E.flatMap(flow(S.length, E.right)) Util.deepStrictEqual(pipe(E.right("abc"), f), E.right(3)) Util.deepStrictEqual(pipe(E.left("maError"), f), E.left("maError")) }) it("bimap", () => { const f = E.bimap(S.length, (n: number) => n > 2) Util.deepStrictEqual(pipe(E.right(1), f), E.right(false)) }) it("mapLeft", () => { const f = E.mapLeft(Util.double) Util.deepStrictEqual(pipe(E.right("a"), f), E.right("a")) Util.deepStrictEqual(pipe(E.left(1), f), E.left(2)) }) it("traverse", () => { const traverse = E.traverse(O.Applicative)(( n: number ) => (n >= 2 ? O.some(n) : O.none())) Util.deepStrictEqual(pipe(E.left("a"), traverse), O.some(E.left("a"))) Util.deepStrictEqual(pipe(E.right(1), traverse), O.none()) Util.deepStrictEqual(pipe(E.right(3), traverse), O.some(E.right(3))) }) it("sequence", () => { const sequence = E.sequence(O.Applicative) Util.deepStrictEqual(sequence(E.right(O.some(1))), O.some(E.right(1))) Util.deepStrictEqual(sequence(E.left("a")), O.some(E.left("a"))) Util.deepStrictEqual(sequence(E.right(O.none())), O.none()) }) it("match", () => { const f = (s: string) => `left${s.length}` const g = (s: string) => `right${s.length}` const match = E.match(f, g) Util.deepStrictEqual(match(E.left("abc")), "left3") Util.deepStrictEqual(match(E.right("abc")), "right3") }) it("getOrElse", () => { Util.deepStrictEqual(pipe(E.right(12), E.getOrElse(() => 17)), 12) Util.deepStrictEqual(pipe(E.left("a"), E.getOrElse(() => 17)), 17) }) it("contains", () => { const contains = E.contains(N.Equivalence) Util.deepStrictEqual(pipe(E.left("a"), contains(2)), false) Util.deepStrictEqual(pipe(E.right(2), contains(2)), true) Util.deepStrictEqual(pipe(E.right(2), contains(1)), false) }) it("filter", () => { const predicate = (n: number) => n > 10 Util.deepStrictEqual(pipe(E.right(12), E.filter(predicate, () => -1)), E.right(12)) Util.deepStrictEqual(pipe(E.right(7), E.filter(predicate, () => -1)), E.left(-1)) Util.deepStrictEqual(pipe(E.left(12), E.filter(predicate, () => -1)), E.left(12)) }) it("isLeft", () => { Util.deepStrictEqual(E.isLeft(E.right(1)), false) Util.deepStrictEqual(E.isLeft(E.left(1)), true) }) it("isRight", () => { Util.deepStrictEqual(E.isRight(E.right(1)), true) Util.deepStrictEqual(E.isRight(E.left(1)), false) }) it("swap", () => { Util.deepStrictEqual(E.reverse(E.right("a")), E.left("a")) Util.deepStrictEqual(E.reverse(E.left("b")), E.right("b")) }) it("liftPredicate", () => { const f = E.liftPredicate((n: number) => n >= 2, () => "e") Util.deepStrictEqual(f(3), E.right(3)) Util.deepStrictEqual(f(1), E.left("e")) }) it("fromNullable", () => { Util.deepStrictEqual(E.fromNullable(() => "default")(null), E.left("default")) Util.deepStrictEqual(E.fromNullable(() => "default")(undefined), E.left("default")) Util.deepStrictEqual(E.fromNullable(() => "default")(1), E.right(1)) }) it("filterMap", () => { const p = (n: number) => n > 2 const f = (n: number) => (p(n) ? O.some(n + 1) : O.none()) Util.deepStrictEqual(pipe(E.left("123"), E.filterMap(f, () => "")), E.left("123")) Util.deepStrictEqual(pipe(E.right(1), E.filterMap(f, () => "")), E.left(S.Monoid.empty)) Util.deepStrictEqual(pipe(E.right(3), E.filterMap(f, () => "")), E.right(4)) }) it("fromIterable", () => { Util.deepStrictEqual(E.fromIterable(() => "e")([]), E.left("e")) Util.deepStrictEqual(E.fromIterable(() => "e")(["a"]), E.right("a")) }) it("firstRightOf", () => { Util.deepStrictEqual(pipe(E.right(1), E.firstRightOf([])), E.right(1)) Util.deepStrictEqual(pipe(E.left("e"), E.firstRightOf([])), E.left("e")) Util.deepStrictEqual( pipe(E.left("e1"), E.firstRightOf([E.left("e2"), E.left("e3"), E.left("e4"), E.right(1)])), E.right(1) ) Util.deepStrictEqual( pipe(E.left("e1"), E.firstRightOf([E.left("e2"), E.left("e3"), E.left("e4")])), E.left("e4") ) }) it("fromOption", () => { Util.deepStrictEqual(E.fromOption(() => "none")(O.none()), E.left("none")) Util.deepStrictEqual(E.fromOption(() => "none")(O.some(1)), E.right(1)) }) it("liftOption", () => { const f = E.liftOption((n: number) => (n > 0 ? O.some(n) : O.none()), () => "a") Util.deepStrictEqual(f(1), E.right(1)) Util.deepStrictEqual(f(-1), E.left("a")) }) it("flatMapOption", () => { const f = E.flatMapOption((n: number) => (n > 0 ? O.some(n) : O.none()), () => "a") Util.deepStrictEqual(f(E.right(1)), E.right(1)) Util.deepStrictEqual(f(E.right(-1)), E.left("a")) Util.deepStrictEqual(f(E.left("b")), E.left("b")) }) it("exists", () => { const gt2 = E.exists((n: number) => n > 2) Util.deepStrictEqual(gt2(E.left("a")), false) Util.deepStrictEqual(gt2(E.right(1)), false) Util.deepStrictEqual(gt2(E.right(3)), true) }) it("do notation", () => { Util.deepStrictEqual( pipe( E.right(1), E.bindTo("a"), E.bind("b", () => E.right("b")), E.let("c", ({ a, b }) => [a, b]) ), E.right({ a: 1, b: "b", c: [1, "b"] }) ) }) it("andThenBind", () => { Util.deepStrictEqual( pipe(E.right(1), E.bindTo("a"), E.andThenBind("b", E.right("b"))), E.right({ a: 1, b: "b" }) ) }) it("product", () => { const product = E.SemiProduct.product Util.deepStrictEqual(product(E.right(1), E.right("a")), E.right([1, "a"])) Util.deepStrictEqual(product(E.right(1), E.left("e2")), E.left("e2")) Util.deepStrictEqual(product(E.left("e1"), E.right("a")), E.left("e1")) Util.deepStrictEqual(product(E.left("e1"), E.left("2")), E.left("e1")) }) it("productMany", () => { const productMany: ( self: E.Either, collection: Iterable> ) => E.Either]> = E.SemiProduct.productMany Util.deepStrictEqual(productMany(E.right(1), []), E.right([1])) Util.deepStrictEqual( productMany(E.right(1), [E.right(2), E.right(3)]), E.right([1, 2, 3]) ) Util.deepStrictEqual( productMany(E.right(1), [E.left("e"), E.right(3)]), E.left("e") ) expect( productMany(E.left("e"), [E.right(2), E.right(3)]) ).toEqual(E.left("e")) }) it("productAll", () => { const productAll = E.Product.productAll Util.deepStrictEqual(productAll([]), E.right([])) Util.deepStrictEqual( productAll([E.right(1), E.right(2), E.right(3)]), E.right([1, 2, 3]) ) Util.deepStrictEqual( productAll([E.left("e"), E.right(2), E.right(3)]), E.left("e") ) }) it("coproduct", () => { const coproduct = E.SemiCoproduct.coproduct Util.deepStrictEqual(coproduct(E.right(1), E.right(2)), E.right(1)) Util.deepStrictEqual(coproduct(E.right(1), E.left("e2")), E.right(1)) Util.deepStrictEqual(coproduct(E.left("e1"), E.right(2)), E.right(2)) Util.deepStrictEqual(coproduct(E.left("e1"), E.left("e2")), E.left("e2")) }) it("coproductMany", () => { const coproductMany = E.SemiCoproduct.coproductMany Util.deepStrictEqual(coproductMany(E.right(1), [E.right(2)]), E.right(1)) Util.deepStrictEqual( coproductMany(E.right(1), [E.left("e2")]), E.right(1) ) Util.deepStrictEqual(coproductMany(E.left("e1"), [E.right(2)]), E.right(2)) Util.deepStrictEqual(coproductMany(E.left("e1"), [E.left("e2")]), E.left("e2")) }) it("element", () => { expect(pipe(E.right(1), E.tupled, E.appendElement(E.right("b")))).toEqual( E.right([1, "b"]) ) }) it("liftNullable", () => { const f = E.liftNullable((n: number) => (n > 0 ? n : null), () => "error") Util.deepStrictEqual(f(1), E.right(1)) Util.deepStrictEqual(f(-1), E.left("error")) }) it("flatMapNullable", () => { const f = E.flatMapNullable((n: number) => (n > 0 ? n : null), () => "error") Util.deepStrictEqual(f(E.right(1)), E.right(1)) Util.deepStrictEqual(f(E.right(-1)), E.left("error")) Util.deepStrictEqual(f(E.left("a")), E.left("a")) }) it("merge", () => { Util.deepStrictEqual(E.merge(E.right(1)), 1) Util.deepStrictEqual(E.merge(E.left("a")), "a") }) it("liftThrowable", () => { const f = E.liftThrowable((s: string) => { const len = s.length if (len > 0) { return len } throw new Error("empty string") }, identity) Util.deepStrictEqual(f("a"), E.right(1)) Util.deepStrictEqual(f(""), E.left(new Error("empty string"))) }) it("zipWith", () => { expect(pipe(E.left("a"), E.zipWith(E.right(2), (a, b) => a + b))).toEqual(E.left("a")) expect(pipe(E.right(1), E.zipWith(E.left("a"), (a, b) => a + b))).toEqual(E.left("a")) expect(pipe(E.right(1), E.zipWith(E.right(2), (a, b) => a + b))).toEqual(E.right(3)) }) it("sum", () => { expect(pipe(E.left("a"), E.sum(E.right(2)))).toEqual(E.left("a")) expect(pipe(E.right(1), E.sum(E.left("a")))).toEqual(E.left("a")) expect(pipe(E.right(2), E.sum(E.right(3)))).toEqual(E.right(5)) }) it("multiply", () => { expect(pipe(E.left("a"), E.multiply(E.right(2)))).toEqual(E.left("a")) expect(pipe(E.right(1), E.multiply(E.left("a")))).toEqual(E.left("a")) expect(pipe(E.right(2), E.multiply(E.right(3)))).toEqual(E.right(6)) }) it("subtract", () => { expect(pipe(E.left("a"), E.subtract(E.right(2)))).toEqual(E.left("a")) expect(pipe(E.right(1), E.subtract(E.left("a")))).toEqual(E.left("a")) expect(pipe(E.right(2), E.subtract(E.right(3)))).toEqual(E.right(-1)) }) it("divide", () => { expect(pipe(E.left("a"), E.divide(E.right(2)))).toEqual(E.left("a")) expect(pipe(E.right(1), E.divide(E.left("a")))).toEqual(E.left("a")) expect(pipe(E.right(6), E.divide(E.right(3)))).toEqual(E.right(2)) }) it("getOptionalSemigroup", () => { const OS = E.getOptionalSemigroup(S.Semigroup) Util.deepStrictEqual(OS.combine(E.left("e"), E.left("e")), E.left("e")) Util.deepStrictEqual(OS.combine(E.left("e"), E.right("a")), E.right("a")) Util.deepStrictEqual(OS.combine(E.right("a"), E.left("e")), E.right("a")) Util.deepStrictEqual(OS.combine(E.right("b"), E.right("a")), E.right("ba")) Util.deepStrictEqual(OS.combine(E.right("a"), E.right("b")), E.right("ab")) Util.deepStrictEqual(OS.combineMany(E.right("a"), [E.right("b")]), E.right("ab")) Util.deepStrictEqual(OS.combineMany(E.left("e"), [E.right("b")]), E.right("b")) Util.deepStrictEqual(OS.combineMany(E.right("a"), [E.left("e")]), E.right("a")) }) it("getEquivalence", () => { const isEquivalent = E.getEquivalence(S.Equivalence, N.Equivalence) Util.deepStrictEqual(isEquivalent(E.right(1), E.right(1)), true) Util.deepStrictEqual(isEquivalent(E.right(1), E.right(2)), false) Util.deepStrictEqual(isEquivalent(E.right(1), E.left("foo")), false) Util.deepStrictEqual(isEquivalent(E.left("foo"), E.left("foo")), true) Util.deepStrictEqual(isEquivalent(E.left("foo"), E.left("bar")), false) Util.deepStrictEqual(isEquivalent(E.left("foo"), E.right(1)), false) }) it("toArray", () => { expect(E.toArray(E.right(1))).toEqual([1]) expect(E.toArray(E.left("error"))).toEqual([]) }) }) ================================================ FILE: test/Function.ts ================================================ import * as _ from "@fp-ts/core/Function" import * as String from "@fp-ts/core/String" import { deepStrictEqual, double } from "@fp-ts/core/test/util" import * as assert from "assert" const f = (n: number): number => n + 1 const g = double describe.concurrent("Function", () => { it("apply", () => { deepStrictEqual(_.pipe(String.length, _.apply("a")), 1) }) it("compose", () => { deepStrictEqual(_.pipe(String.length, _.compose(double))("aaa"), 6) deepStrictEqual(_.compose(String.length, double)("aaa"), 6) }) it("flip", () => { const f = (a: number) => (b: string) => a - b.length const g = (a: number, i = 0) => (b: number) => a ** b + i deepStrictEqual(_.flip(f)("aaa")(2), -1) deepStrictEqual(_.flip(g)(2)(2, 1), 5) }) it("unsafeCoerce", () => { deepStrictEqual(_.unsafeCoerce, _.identity) }) it("constant", () => { deepStrictEqual(_.constant("a")(), "a") }) it("constTrue", () => { deepStrictEqual(_.constTrue(), true) }) it("constFalse", () => { deepStrictEqual(_.constFalse(), false) }) it("constNull", () => { deepStrictEqual(_.constNull(), null) }) it("constUndefined", () => { deepStrictEqual(_.constUndefined(), undefined) }) it("constVoid", () => { deepStrictEqual(_.constVoid(), undefined) }) it("absurd", () => { assert.throws(() => _.absurd(null as any as never)) }) it("hole", () => { assert.throws(() => _.hole()) }) it("SK", () => { expect(_.SK(1, 2)).toEqual(2) }) it("flow", () => { deepStrictEqual(_.flow(f)(2), 3) deepStrictEqual(_.flow(f, g)(2), 6) deepStrictEqual(_.flow(f, g, f)(2), 7) deepStrictEqual(_.flow(f, g, f, g)(2), 14) deepStrictEqual(_.flow(f, g, f, g, f)(2), 15) deepStrictEqual(_.flow(f, g, f, g, f, g)(2), 30) deepStrictEqual(_.flow(f, g, f, g, f, g, f)(2), 31) deepStrictEqual(_.flow(f, g, f, g, f, g, f, g)(2), 62) deepStrictEqual(_.flow(f, g, f, g, f, g, f, g, f)(2), 63) // this is just to satisfy noImplicitReturns and 100% coverage deepStrictEqual((_.flow as any)(...[f, g, f, g, f, g, f, g, f, g]), undefined) }) it("tupled", () => { const f1 = (a: number): number => a * 2 const f2 = (a: number, b: number): number => a + b const u1 = _.tupled(f1) const u2 = _.tupled(f2) deepStrictEqual(u1([1]), 2) deepStrictEqual(u2([1, 2]), 3) }) it("untupled", () => { const f1 = (a: readonly [number]): number => a[0] * 2 const f2 = (a: readonly [number, number]): number => a[0] + a[1] const u1 = _.untupled(f1) const u2 = _.untupled(f2) deepStrictEqual(u1(1), 2) deepStrictEqual(u2(1, 2), 3) }) it("pipe", () => { deepStrictEqual(_.pipe(2), 2) deepStrictEqual(_.pipe(2, f), 3) deepStrictEqual(_.pipe(2, f, g), 6) deepStrictEqual(_.pipe(2, f, g, f), 7) deepStrictEqual(_.pipe(2, f, g, f, g), 14) deepStrictEqual(_.pipe(2, f, g, f, g, f), 15) deepStrictEqual(_.pipe(2, f, g, f, g, f, g), 30) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f), 31) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g), 62) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f), 63) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g), 126) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f), 127) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f, g), 254) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f, g, f), 255) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f, g, f, g), 510) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f), 511) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g), 1022) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f), 1023) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g), 2046) deepStrictEqual(_.pipe(2, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f), 2047) deepStrictEqual( (_.pipe as any)(...[2, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g, f, g]), 4094 ) }) it("dual", () => { const f = _.dual< (that: number) => (self: number) => number, (self: number, that: number) => number >(2, (a: number, b: number): number => a - b) deepStrictEqual(f(3, 2), 1) deepStrictEqual(_.pipe(3, f(2)), 1) }) }) ================================================ FILE: test/Identity.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as _ from "@fp-ts/core/Identity" import * as O from "@fp-ts/core/Option" import * as String from "@fp-ts/core/String" import * as U from "./util" describe.concurrent("Identity", () => { it("instances and derived exports", () => { expect(_.Invariant).exist expect(_.Covariant).exist expect(_.Of).exist expect(_.Pointed).exist expect(_.FlatMap).exist expect(_.Chainable).exist expect(_.Monad).exist expect(_.SemiProduct).exist expect(_.Product).exist expect(_.SemiApplicative).exist expect(_.Applicative).exist expect(_.Foldable).exist expect(_.Traversable).exist expect(_.bindTo).exist expect(_.let).exist expect(_.Do).exist expect(_.bind).exist }) it("Of", () => { U.deepStrictEqual(_.Of.of("a"), "a") }) it("SemiProduct", () => { U.deepStrictEqual(_.SemiProduct.productMany("a", ["b", "c"]), ["a", "b", "c"]) }) it("Product", () => { U.deepStrictEqual(_.Product.productAll([]), []) U.deepStrictEqual(_.Product.productAll(["a", "b", "c"]), ["a", "b", "c"]) }) it("Covariant", () => { assert.deepStrictEqual(_.Covariant.map(1, n => n * 2), 2) }) it("FlatMap", () => { U.deepStrictEqual( pipe("a", _.FlatMap.flatMap((a) => a + "b")), "ab" ) }) it("SemiProduct", () => { const product = _.SemiProduct.product U.deepStrictEqual(product("a", "b"), ["a", "b"]) }) it("getSemiCoproduct", () => { const F = _.getSemiCoproduct(String.Semigroup) U.deepStrictEqual(F.coproduct("a", "b"), "ab") U.deepStrictEqual(F.coproductMany("a", ["b", "c"]), "abc") }) it("getSemiAlternative", () => { const F = _.getSemiAlternative(String.Semigroup) U.deepStrictEqual(F.coproduct("a", "b"), "ab") U.deepStrictEqual(F.coproductMany("a", ["b", "c"]), "abc") }) it("Foldable", () => { U.deepStrictEqual(pipe("b", _.Foldable.reduce("a", (b, a) => b + a)), "ab") }) it("Traversable", () => { U.deepStrictEqual(pipe(1, _.Traversable.traverse(O.Applicative)(O.some)), O.some(1)) U.deepStrictEqual(pipe(1, _.Traversable.traverse(O.Applicative)(() => O.none())), O.none()) }) }) ================================================ FILE: test/Number.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as Number from "@fp-ts/core/Number" import { deepStrictEqual } from "@fp-ts/core/test/util" describe.concurrent("Number", () => { it("exports", () => { expect(Number.SemigroupMax).exists expect(Number.SemigroupMin).exists expect(Number.MonoidMax).exists expect(Number.MonoidMin).exists expect(Number.sumAll).exists expect(Number.multiplyAll).exists expect(Number.lessThan).exists expect(Number.lessThanOrEqualTo).exists expect(Number.greaterThan).exists expect(Number.greaterThanOrEqualTo).exists expect(Number.between).exists expect(Number.clamp).exists expect(Number.min).exists expect(Number.max).exists }) it("isNumber", () => { expect(Number.isNumber(1)).toEqual(true) expect(Number.isNumber("a")).toEqual(false) expect(Number.isNumber(true)).toEqual(false) }) it("sum", () => { deepStrictEqual(pipe(1, Number.sum(2)), 3) }) it("multiply", () => { deepStrictEqual(pipe(2, Number.multiply(3)), 6) }) it("subtract", () => { deepStrictEqual(pipe(3, Number.subtract(1)), 2) }) it("divide", () => { deepStrictEqual(pipe(6, Number.divide(2)), 3) }) it("increment", () => { deepStrictEqual(Number.increment(2), 3) }) it("decrement", () => { deepStrictEqual(Number.decrement(2), 1) }) it("Equivalence", () => { expect(Number.Equivalence(1, 1)).toBe(true) expect(Number.Equivalence(1, 2)).toBe(false) }) it("Order", () => { deepStrictEqual(Number.Order.compare(1, 2), -1) deepStrictEqual(Number.Order.compare(2, 1), 1) deepStrictEqual(Number.Order.compare(2, 2), 0) }) it("Bounded", () => { expect(Number.Bounded.maxBound).toEqual(Infinity) expect(Number.Bounded.minBound).toEqual(-Infinity) }) it("SemigroupSum", () => { deepStrictEqual(Number.SemigroupSum.combine(2, 3), 5) }) it("MonoidSum", () => { deepStrictEqual(Number.MonoidSum.combineAll([1, 2, 3]), 6) }) it("SemigroupMultiply", () => { deepStrictEqual(Number.SemigroupMultiply.combine(2, 3), 6) deepStrictEqual(Number.SemigroupMultiply.combineMany(0, [1, 2, 3]), 0) deepStrictEqual(Number.SemigroupMultiply.combineMany(2, [1, 0, 3]), 0) }) it("MonoidMultiply", () => { deepStrictEqual(Number.MonoidMultiply.combineAll([2, 3, 4]), 24) }) it("sign", () => { deepStrictEqual(Number.sign(0), 0) deepStrictEqual(Number.sign(0.0), 0) deepStrictEqual(Number.sign(-0.1), -1) deepStrictEqual(Number.sign(-10), -1) deepStrictEqual(Number.sign(10), 1) deepStrictEqual(Number.sign(0.1), 1) }) it("remainder", () => { assert.deepStrictEqual(Number.remainder(2, 2), 0) assert.deepStrictEqual(Number.remainder(3, 2), 1) assert.deepStrictEqual(Number.remainder(4, 2), 0) assert.deepStrictEqual(Number.remainder(2.5, 2), 0.5) assert.deepStrictEqual(Number.remainder(-2, 2), -0) assert.deepStrictEqual(Number.remainder(-3, 2), -1) assert.deepStrictEqual(Number.remainder(-4, 2), -0) assert.deepStrictEqual(Number.remainder(-2.8, -.2), -0) assert.deepStrictEqual(Number.remainder(-2, -.2), -0) assert.deepStrictEqual(Number.remainder(-1.5, -.2), -0.1) assert.deepStrictEqual(Number.remainder(0, -.2), 0) assert.deepStrictEqual(Number.remainder(1, -.2), 0) assert.deepStrictEqual(Number.remainder(2.6, -.2), 0) assert.deepStrictEqual(Number.remainder(3.1, -.2), 0.1) }) }) ================================================ FILE: test/Option.ts ================================================ import { equivalence } from "@fp-ts/core" import * as E from "@fp-ts/core/Either" import { pipe } from "@fp-ts/core/Function" import { structural } from "@fp-ts/core/internal/effect" import * as N from "@fp-ts/core/Number" import * as _ from "@fp-ts/core/Option" import * as ReadonlyArray from "@fp-ts/core/ReadonlyArray" import * as S from "@fp-ts/core/String" import * as Util from "@fp-ts/core/test/util" const p = (n: number): boolean => n > 2 describe.concurrent("Option", () => { it("exports", () => { expect(_.toEither).exist expect(_.getRight).exist expect(_.getLeft).exist expect(_.Invariant).exist expect(_.tupled).exist expect(_.bindTo).exist expect(_.Covariant).exist expect(_.map).exist expect(_.let).exist expect(_.flap).exist expect(_.as).exist expect(_.asUnit).exist expect(_.Of).exist expect(_.of).exist expect(_.Do).exist expect(_.Pointed).exist expect(_.FlatMap).exist expect(_.flatMap).exist expect(_.flatten).exist expect(_.andThen).exist expect(_.composeKleisliArrow).exist expect(_.Chainable).exist expect(_.bind).exist expect(_.tap).exist expect(_.andThenDiscard).exist expect(_.Monad).exist expect(_.SemiProduct).exist expect(_.Product).exist expect(_.all).exist expect(_.tuple).exist expect(_.struct).exist expect(_.SemiApplicative).exist expect(_.getFailureSemigroup).exist // liftSemigroup expect(_.lift2).exist expect(_.ap).exist expect(_.andThenDiscard).exist expect(_.andThen).exist expect(_.Applicative).exist expect(_.getFailureMonoid).exist // liftMonoid expect(_.SemiCoproduct).exist expect(_.getFirstSomeSemigroup).exist // getSemigroup expect(_.Coproduct).exist expect(_.SemiAlternative).exist expect(_.Alternative).exist expect(_.Foldable).exist expect(_.reduceCompact).exist expect(_.toArray).exist expect(_.Traversable).exist expect(_.traverse).exist expect(_.sequence).exist expect(_.traverseTap).exist expect(_.Filterable).exist expect(_.filterMap).exist expect(_.filter).exist }) it("structural tracking", () => { expect(Util.ownKeys(_.none())).toEqual(["_tag"]) expect(Util.ownKeys(_.some(1))).toEqual(["_tag", "value"]) expect(Object.prototype.hasOwnProperty.call(_.none(), structural)).toEqual(false) expect(Object.prototype.hasOwnProperty.call(_.some(1), structural)).toEqual(false) expect(Util.isStructural(_.none())).toEqual(true) expect(Util.isStructural(_.some(1))).toEqual(true) }) it("toRefinement", () => { const f = ( s: string | number ): _.Option => (typeof s === "string" ? _.some(s) : _.none()) const isString = _.toRefinement(f) Util.deepStrictEqual(isString("s"), true) Util.deepStrictEqual(isString(1), false) type A = { readonly type: "A" } type B = { readonly type: "B" } type C = A | B const isA = _.toRefinement((c) => (c.type === "A" ? _.some(c) : _.none())) Util.deepStrictEqual(isA({ type: "A" }), true) Util.deepStrictEqual(isA({ type: "B" }), false) }) it("isOption", () => { Util.deepStrictEqual(pipe(_.some(1), _.isOption), true) Util.deepStrictEqual(pipe(_.none(), _.isOption), true) Util.deepStrictEqual(pipe(E.right(1), _.isOption), false) }) it("coproductMany", () => { const coproductMany = _.SemiCoproduct.coproductMany Util.deepStrictEqual(coproductMany(_.some(1), []), _.some(1)) Util.deepStrictEqual(coproductMany(_.none(), []), _.none()) Util.deepStrictEqual( coproductMany(_.none(), [_.none(), _.none(), _.none(), _.some(1)]), _.some(1) ) Util.deepStrictEqual( coproductMany(_.none(), [_.none(), _.none(), _.none()]), _.none() ) }) it("firstSomeOf", () => { Util.deepStrictEqual(_.firstSomeOf([]), _.none()) Util.deepStrictEqual(_.firstSomeOf([_.some(1)]), _.some(1)) Util.deepStrictEqual(_.firstSomeOf([_.none()]), _.none()) Util.deepStrictEqual( _.firstSomeOf([_.none(), _.none(), _.none(), _.none(), _.some(1)]), _.some(1) ) Util.deepStrictEqual( _.firstSomeOf([_.none(), _.none(), _.none(), _.none()]), _.none() ) }) it("orElseEither", () => { expect(pipe(_.some(1), _.orElseEither(() => _.some(2)))).toEqual(_.some(E.left(1))) expect(pipe(_.some(1), _.orElseEither(() => _.none()))).toEqual(_.some(E.left(1))) expect(pipe(_.none(), _.orElseEither(() => _.some(2)))).toEqual(_.some(E.right(2))) expect(pipe(_.none(), _.orElseEither(() => _.none()))).toEqual(_.none()) }) it("inspectSome", () => { const log: Array = [] pipe( _.some(1), _.inspectSome(() => log.push(1)) ) pipe( _.none(), _.inspectSome(() => log.push(2)) ) Util.deepStrictEqual( log, [1] ) }) it("inspectNone", () => { const log: Array = [] pipe( _.some(1), _.inspectNone(() => log.push(1)) ) pipe( _.none(), _.inspectNone(() => log.push(2)) ) Util.deepStrictEqual( log, [2] ) }) it("getOrThrow", () => { expect(pipe(_.some(1), _.getOrThrow)).toEqual(1) expect(() => pipe(_.none(), _.getOrThrow)).toThrowError( new Error("getOrThrow called on a None") ) }) it("getOrThrowWith", () => { expect(pipe(_.some(1), _.getOrThrowWith(() => new Error("Unexpected None")))).toEqual(1) expect(() => pipe(_.none(), _.getOrThrowWith(() => new Error("Unexpected None")))).toThrowError( new Error("Unexpected None") ) }) it("of", () => { Util.deepStrictEqual(_.of(1), _.some(1)) }) it("Foldable", () => { expect(pipe(_.none(), _.Foldable.reduce("a", (s, n: number) => s + String(n)))).toEqual("a") expect(pipe(_.some(1), _.Foldable.reduce("a", (s, n: number) => s + String(n)))).toEqual( "a1" ) }) it("coproductAll", () => { const coproductAll = _.Coproduct.coproductAll Util.deepStrictEqual(coproductAll([]), _.none()) Util.deepStrictEqual(coproductAll([_.some(1)]), _.some(1)) Util.deepStrictEqual(coproductAll([_.none(), _.some(1)]), _.some(1)) Util.deepStrictEqual(coproductAll([_.some(1), _.some(2)]), _.some(1)) }) it("unit", () => { Util.deepStrictEqual(_.unit, _.some(undefined)) }) it("product", () => { const product = _.SemiProduct.product Util.deepStrictEqual(product(_.none(), _.none()), _.none()) Util.deepStrictEqual(product(_.some(1), _.none()), _.none()) Util.deepStrictEqual(product(_.none(), _.some("a")), _.none()) Util.deepStrictEqual( product(_.some(1), _.some("a")), _.some([1, "a"]) ) }) it("productMany", () => { const productMany = _.SemiProduct.productMany Util.deepStrictEqual(productMany(_.none(), []), _.none()) Util.deepStrictEqual(productMany(_.some(1), []), _.some([1])) Util.deepStrictEqual(productMany(_.some(1), [_.none()]), _.none()) Util.deepStrictEqual(productMany(_.some(1), [_.some(2)]), _.some([1, 2])) }) it("productAll", () => { const productAll = _.Applicative.productAll Util.deepStrictEqual(productAll([]), _.some([])) Util.deepStrictEqual(productAll([_.none()]), _.none()) Util.deepStrictEqual(productAll([_.some(1), _.some(2)]), _.some([1, 2])) Util.deepStrictEqual(productAll([_.some(1), _.none()]), _.none()) }) it("SemiCoproduct", () => { const coproduct = _.SemiCoproduct.coproduct Util.deepStrictEqual(coproduct(_.none(), _.none()), _.none()) Util.deepStrictEqual(coproduct(_.none(), _.some(2)), _.some(2)) Util.deepStrictEqual(coproduct(_.some(1), _.none()), _.some(1)) Util.deepStrictEqual(coproduct(_.some(1), _.some(2)), _.some(1)) const coproductMany = _.SemiCoproduct.coproductMany Util.deepStrictEqual(coproductMany(_.none(), []), _.none()) Util.deepStrictEqual(coproductMany(_.none(), [_.none()]), _.none()) Util.deepStrictEqual(coproductMany(_.none(), [_.some(2)]), _.some(2)) Util.deepStrictEqual(coproductMany(_.some(1), []), _.some(1)) Util.deepStrictEqual(coproductMany(_.some(1), [_.none() as _.Option]), _.some(1)) Util.deepStrictEqual(coproductMany(_.some(1), [_.some(2)]), _.some(1)) }) it("fromIterable", () => { Util.deepStrictEqual(_.fromIterable([]), _.none()) Util.deepStrictEqual(_.fromIterable(["a"]), _.some("a")) }) it("map", () => { Util.deepStrictEqual(pipe(_.some(2), _.map(Util.double)), _.some(4)) Util.deepStrictEqual(pipe(_.none(), _.map(Util.double)), _.none()) }) it("flatMap", () => { const f = (n: number) => _.some(n * 2) const g = () => _.none() Util.deepStrictEqual(pipe(_.some(1), _.flatMap(f)), _.some(2)) Util.deepStrictEqual(pipe(_.none(), _.flatMap(f)), _.none()) Util.deepStrictEqual(pipe(_.some(1), _.flatMap(g)), _.none()) Util.deepStrictEqual(pipe(_.none(), _.flatMap(g)), _.none()) }) it("orElse", () => { const assertAlt = ( a: _.Option, b: _.Option, expected: _.Option ) => { Util.deepStrictEqual(pipe(a, _.orElse(() => b)), expected) } assertAlt(_.some(1), _.some(2), _.some(1)) assertAlt(_.some(1), _.none(), _.some(1)) assertAlt(_.none(), _.some(2), _.some(2)) assertAlt(_.none(), _.none(), _.none()) }) it("partitionMap", () => { const f = (n: number) => (p(n) ? E.right(n + 1) : E.left(n - 1)) assert.deepStrictEqual(pipe(_.none(), _.partitionMap(f)), [_.none(), _.none()]) assert.deepStrictEqual(pipe(_.some(1), _.partitionMap(f)), [_.some(0), _.none()]) assert.deepStrictEqual(pipe(_.some(3), _.partitionMap(f)), [_.none(), _.some(4)]) }) it("filterMap", () => { const f = (n: number) => (p(n) ? _.some(n + 1) : _.none()) Util.deepStrictEqual(pipe(_.none(), _.filterMap(f)), _.none()) Util.deepStrictEqual(pipe(_.some(1), _.filterMap(f)), _.none()) Util.deepStrictEqual(pipe(_.some(3), _.filterMap(f)), _.some(4)) }) it("traverse", () => { Util.deepStrictEqual( pipe( _.some("hello"), _.traverse(ReadonlyArray.Applicative)(() => []) ), [] ) Util.deepStrictEqual( pipe( _.some("hello"), _.traverse(ReadonlyArray.Applicative)((s) => [s.length]) ), [_.some(5)] ) Util.deepStrictEqual( pipe( _.none(), _.traverse(ReadonlyArray.Applicative)((s) => [s]) ), [_.none()] ) }) it("toEither", () => { Util.deepStrictEqual(pipe(_.none(), _.toEither(() => "e")), E.left("e")) Util.deepStrictEqual(pipe(_.some(1), _.toEither(() => "e")), E.right(1)) }) it("match", () => { const f = () => "none" const g = (s: string) => `some${s.length}` const match = _.match(f, g) Util.deepStrictEqual(match(_.none()), "none") Util.deepStrictEqual(match(_.some("abc")), "some3") }) it("getOrElse", () => { Util.deepStrictEqual(pipe(_.some(1), _.getOrElse(() => 0)), 1) Util.deepStrictEqual(pipe(_.none(), _.getOrElse(() => 0)), 0) }) it("getOrNull", () => { Util.deepStrictEqual(_.getOrNull(_.none()), null) Util.deepStrictEqual(_.getOrNull(_.some(1)), 1) }) it("getOrUndefined", () => { Util.deepStrictEqual(_.getOrUndefined(_.none()), undefined) Util.deepStrictEqual(_.getOrUndefined(_.some(1)), 1) }) it("getOrder", () => { const OS = _.getOrder(S.Order) Util.deepStrictEqual(OS.compare(_.none(), _.none()), 0) Util.deepStrictEqual(OS.compare(_.some("a"), _.none()), 1) Util.deepStrictEqual(OS.compare(_.none(), _.some("a")), -1) Util.deepStrictEqual(OS.compare(_.some("a"), _.some("a")), 0) Util.deepStrictEqual(OS.compare(_.some("a"), _.some("b")), -1) Util.deepStrictEqual(OS.compare(_.some("b"), _.some("a")), 1) }) it("flatMapNullable", () => { interface X { readonly a?: { readonly b?: { readonly c?: { readonly d: number } } } } const x1: X = { a: {} } const x2: X = { a: { b: {} } } const x3: X = { a: { b: { c: { d: 1 } } } } Util.deepStrictEqual( pipe( _.fromNullable(x1.a), _.flatMapNullable((x) => x.b), _.flatMapNullable((x) => x.c), _.flatMapNullable((x) => x.d) ), _.none() ) Util.deepStrictEqual( pipe( _.fromNullable(x2.a), _.flatMapNullable((x) => x.b), _.flatMapNullable((x) => x.c), _.flatMapNullable((x) => x.d) ), _.none() ) Util.deepStrictEqual( pipe( _.fromNullable(x3.a), _.flatMapNullable((x) => x.b), _.flatMapNullable((x) => x.c), _.flatMapNullable((x) => x.d) ), _.some(1) ) }) it("getOptionalMonoid", () => { const M = _.getOptionalMonoid(S.Semigroup) Util.deepStrictEqual(M.combine(_.none(), _.none()), _.none()) Util.deepStrictEqual(M.combine(_.none(), _.some("a")), _.some("a")) Util.deepStrictEqual(M.combine(_.some("a"), _.none()), _.some("a")) Util.deepStrictEqual(M.combine(_.some("b"), _.some("a")), _.some("ba")) Util.deepStrictEqual(M.combine(_.some("a"), _.some("b")), _.some("ab")) Util.deepStrictEqual(M.combineMany(_.some("a"), [_.some("b")]), _.some("ab")) Util.deepStrictEqual(M.combineMany(_.none(), [_.some("b")]), _.some("b")) Util.deepStrictEqual(M.combineMany(_.some("a"), [_.none()]), _.some("a")) Util.deepStrictEqual(pipe(M.combineAll([])), _.none()) Util.deepStrictEqual(pipe(M.combineAll([_.some("a")])), _.some("a")) Util.deepStrictEqual(pipe(M.combineAll([_.some("a"), _.some("b")])), _.some("ab")) Util.deepStrictEqual(pipe(M.combineAll([_.some("a"), _.none()])), _.some("a")) }) it("fromNullable", () => { Util.deepStrictEqual(_.fromNullable(2), _.some(2)) Util.deepStrictEqual(_.fromNullable(null), _.none()) Util.deepStrictEqual(_.fromNullable(undefined), _.none()) }) it("liftPredicate", () => { const f = _.liftPredicate(p) Util.deepStrictEqual(f(1), _.none()) Util.deepStrictEqual(f(3), _.some(3)) type Direction = "asc" | "desc" const parseDirection = _.liftPredicate((s: string): s is Direction => s === "asc" || s === "desc" ) Util.deepStrictEqual(parseDirection("asc"), _.some("asc")) Util.deepStrictEqual(parseDirection("foo"), _.none()) }) it("contains", () => { const contains = _.contains(equivalence.number) Util.deepStrictEqual(pipe(_.none(), contains(2)), false) Util.deepStrictEqual(pipe(_.some(2), contains(2)), true) Util.deepStrictEqual(pipe(_.some(2), contains(1)), false) }) it("isNone", () => { Util.deepStrictEqual(_.isNone(_.none()), true) Util.deepStrictEqual(_.isNone(_.some(1)), false) }) it("isSome", () => { Util.deepStrictEqual(_.isSome(_.none()), false) Util.deepStrictEqual(_.isSome(_.some(1)), true) }) it("exists", () => { const predicate = (a: number) => a === 2 Util.deepStrictEqual(pipe(_.none(), _.exists(predicate)), false) Util.deepStrictEqual(pipe(_.some(1), _.exists(predicate)), false) Util.deepStrictEqual(pipe(_.some(2), _.exists(predicate)), true) }) it("fromEither", () => { Util.deepStrictEqual(_.fromEither(E.right(1)), _.some(1)) Util.deepStrictEqual(_.fromEither(E.left("e")), _.none()) }) it("do notation", () => { Util.deepStrictEqual( pipe( _.some(1), _.bindTo("a"), _.bind("b", () => _.some("b")) ), _.some({ a: 1, b: "b" }) ) }) it("andThenBind", () => { Util.deepStrictEqual( pipe(_.some(1), _.bindTo("a"), _.andThenBind("b", _.some("b"))), _.some({ a: 1, b: "b" }) ) }) it("element", () => { expect(pipe(_.some(1), _.tupled, _.appendElement(_.some("b")))).toEqual( _.some([1, "b"]) ) }) it("liftNullable", () => { const f = _.liftNullable((n: number) => (n > 0 ? n : null)) Util.deepStrictEqual(f(1), _.some(1)) Util.deepStrictEqual(f(-1), _.none()) }) it("liftThrowable", () => { const parse = _.liftThrowable(JSON.parse) Util.deepStrictEqual(parse("1"), _.some(1)) Util.deepStrictEqual(parse(""), _.none()) }) it("liftEither", () => { const f = _.liftEither((n: number) => (n > 0 ? E.right(n) : E.left("e"))) Util.deepStrictEqual(f(1), _.some(1)) Util.deepStrictEqual(f(-1), _.none()) }) it("flatMapEither", () => { const f = _.flatMapEither((n: number) => (n > 0 ? E.right(n) : E.left("e"))) Util.deepStrictEqual(pipe(_.none(), f), _.none()) Util.deepStrictEqual(pipe(_.some(0), f), _.none()) Util.deepStrictEqual(pipe(_.some(1), f), _.some(1)) }) it("guard", () => { Util.deepStrictEqual( pipe( _.Do, _.bind("x", () => _.some("a")), _.bind("y", () => _.some("a")), _.filter(({ x, y }) => x === y) ), _.some({ x: "a", y: "a" }) ) Util.deepStrictEqual( pipe( _.Do, _.bind("x", () => _.some("a")), _.bind("y", () => _.some("b")), _.filter(({ x, y }) => x === y) ), _.none() ) }) it("zipWith", () => { expect(pipe(_.none(), _.zipWith(_.some(2), (a, b) => a + b))).toEqual(_.none()) expect(pipe(_.some(1), _.zipWith(_.none(), (a, b) => a + b))).toEqual(_.none()) expect(pipe(_.some(1), _.zipWith(_.some(2), (a, b) => a + b))).toEqual(_.some(3)) }) it("reduceCompact", () => { const sumCompact = _.reduceCompact(0, N.sum) expect(sumCompact([])).toEqual(0) expect(sumCompact([_.some(2), _.some(3)])).toEqual(5) expect(sumCompact([_.some(2), _.none(), _.some(3)])).toEqual(5) }) it("sum", () => { expect(pipe(_.none(), _.sum(_.some(2)))).toEqual(_.none()) expect(pipe(_.some(1), _.sum(_.none()))).toEqual(_.none()) expect(pipe(_.some(2), _.sum(_.some(3)))).toEqual(_.some(5)) }) it("multiply", () => { expect(pipe(_.none(), _.multiply(_.some(2)))).toEqual(_.none()) expect(pipe(_.some(1), _.multiply(_.none()))).toEqual(_.none()) expect(pipe(_.some(2), _.multiply(_.some(3)))).toEqual(_.some(6)) }) it("subtract", () => { expect(pipe(_.none(), _.subtract(_.some(2)))).toEqual(_.none()) expect(pipe(_.some(1), _.subtract(_.none()))).toEqual(_.none()) expect(pipe(_.some(2), _.subtract(_.some(3)))).toEqual(_.some(-1)) }) it("divide", () => { expect(pipe(_.none(), _.divide(_.some(2)))).toEqual(_.none()) expect(pipe(_.some(1), _.divide(_.none()))).toEqual(_.none()) expect(pipe(_.some(6), _.divide(_.some(3)))).toEqual(_.some(2)) }) it("reduce", () => { expect(pipe(_.none(), _.Foldable.reduce(0, (b, a) => b + a))).toEqual(0) expect(pipe(_.some(1), _.Foldable.reduce(0, (b, a) => b + a))).toEqual(1) }) it("sumCompact", () => { expect(_.sumCompact([])).toEqual(0) expect(_.sumCompact([_.some(2), _.some(3)])).toEqual(5) expect(_.sumCompact([_.some(2), _.none(), _.some(3)])).toEqual(5) }) it("multiplyCompact", () => { expect(_.multiplyCompact([])).toEqual(1) expect(_.multiplyCompact([_.some(2), _.some(3)])).toEqual(6) expect(_.multiplyCompact([_.some(2), _.none(), _.some(3)])).toEqual(6) expect(_.multiplyCompact([_.some(2), _.some(0), _.some(3)])).toEqual(0) }) it("getEquivalence", () => { const isEquivalent = _.getEquivalence(N.Equivalence) expect(isEquivalent(_.none(), _.none())).toEqual(true) expect(isEquivalent(_.none(), _.some(1))).toEqual(false) expect(isEquivalent(_.some(1), _.none())).toEqual(false) expect(isEquivalent(_.some(2), _.some(1))).toEqual(false) expect(isEquivalent(_.some(1), _.some(2))).toEqual(false) expect(isEquivalent(_.some(2), _.some(2))).toEqual(true) }) }) ================================================ FILE: test/Ordering.ts ================================================ import * as _ from "@fp-ts/core/Ordering" import { deepStrictEqual } from "./util" describe("Ordering", () => { it("match", () => { const f = _.match( () => "lt", () => "eq", () => "gt" ) deepStrictEqual(f(-1), "lt") deepStrictEqual(f(0), "eq") deepStrictEqual(f(1), "gt") }) it("reverse", () => { deepStrictEqual(_.reverse(-1), 1) deepStrictEqual(_.reverse(0), 0) deepStrictEqual(_.reverse(1), -1) }) it("Semigroup", () => { deepStrictEqual(_.Semigroup.combine(0, 0), 0) deepStrictEqual(_.Semigroup.combine(0, 1), 1) deepStrictEqual(_.Semigroup.combine(1, -1), 1) deepStrictEqual(_.Semigroup.combine(-1, 1), -1) deepStrictEqual(_.Semigroup.combineMany(0, []), 0) deepStrictEqual(_.Semigroup.combineMany(1, []), 1) deepStrictEqual(_.Semigroup.combineMany(-1, []), -1) deepStrictEqual(_.Semigroup.combineMany(0, [0, 0, 0]), 0) deepStrictEqual(_.Semigroup.combineMany(0, [0, 0, 1]), 1) deepStrictEqual(_.Semigroup.combineMany(1, [0, 0, -1]), 1) deepStrictEqual(_.Semigroup.combineMany(-1, [0, 0, 1]), -1) }) it("Monoid", () => { deepStrictEqual(_.Monoid.combine(_.Monoid.empty, 0), 0) deepStrictEqual(_.Monoid.combine(_.Monoid.empty, 1), 1) deepStrictEqual(_.Monoid.combine(_.Monoid.empty, -1), -1) deepStrictEqual(_.Monoid.combine(0, _.Monoid.empty), 0) deepStrictEqual(_.Monoid.combine(1, _.Monoid.empty), 1) deepStrictEqual(_.Monoid.combine(-1, _.Monoid.empty), -1) }) }) ================================================ FILE: test/Predicate.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as _ from "@fp-ts/core/Predicate" import { deepStrictEqual } from "@fp-ts/core/test/util" const isPositive: _.Predicate = (n) => n > 0 const isNegative: _.Predicate = (n) => n < 0 const isLessThan2: _.Predicate = (n) => n < 2 const isString: _.Refinement = (u: unknown): u is string => typeof u === "string" interface NonEmptyStringBrand { readonly NonEmptyString: unique symbol } type NonEmptyString = string & NonEmptyStringBrand const NonEmptyString: _.Refinement = (s): s is NonEmptyString => s.length > 0 describe.concurrent("Predicate", () => { it("instances and derived exports", () => { expect(_.Invariant).exist expect(_.tupled).exist expect(_.bindTo).exist expect(_.Contravariant).exist expect(_.contramap).exist expect(_.Of).exist expect(_.of).exist expect(_.unit).exist expect(_.Do).exist expect(_.SemiProduct).exist expect(_.andThenBind).exist expect(_.appendElement).exist expect(_.Product).exist expect(_.tuple).exist expect(_.struct).exist }) it("compose", () => { const refinement = pipe(isString, _.compose(NonEmptyString)) deepStrictEqual(refinement("a"), true) deepStrictEqual(refinement(null), false) deepStrictEqual(refinement(""), false) }) it("contramap", () => { type A = { readonly a: number } const predicate = pipe( isPositive, _.contramap((a: A) => a.a) ) deepStrictEqual(predicate({ a: -1 }), false) deepStrictEqual(predicate({ a: 0 }), false) deepStrictEqual(predicate({ a: 1 }), true) }) it("product", () => { const product = _.SemiProduct.product const p = product(isPositive, isNegative) deepStrictEqual(p([1, -1]), true) deepStrictEqual(p([1, 1]), false) deepStrictEqual(p([-1, -1]), false) deepStrictEqual(p([-1, 1]), false) }) it("productMany", () => { const productMany = _.SemiProduct.productMany const p = productMany(isPositive, [isNegative]) deepStrictEqual(p([1, -1]), true) deepStrictEqual(p([1, 1]), false) deepStrictEqual(p([-1, -1]), false) deepStrictEqual(p([-1, 1]), false) }) it("productAll", () => { const p = _.Product.productAll([isPositive, isNegative]) deepStrictEqual(p([1]), true) deepStrictEqual(p([1, -1]), true) deepStrictEqual(p([1, 1]), false) deepStrictEqual(p([-1, -1]), false) deepStrictEqual(p([-1, 1]), false) }) it("not", () => { const p = _.not(isPositive) deepStrictEqual(p(1), false) deepStrictEqual(p(0), true) deepStrictEqual(p(-1), true) }) it("or", () => { const p = pipe(isPositive, _.or(isNegative)) deepStrictEqual(p(-1), true) deepStrictEqual(p(1), true) deepStrictEqual(p(0), false) }) it("and", () => { const p = pipe(isPositive, _.and(isLessThan2)) deepStrictEqual(p(1), true) deepStrictEqual(p(-1), false) deepStrictEqual(p(3), false) }) it("getSemigroupAny", () => { const S = _.getSemigroupAny() const p1 = S.combine(isPositive, isNegative) deepStrictEqual(p1(0), false) deepStrictEqual(p1(-1), true) deepStrictEqual(p1(1), true) const p2 = S.combineMany(isPositive, [isNegative]) deepStrictEqual(p2(0), false) deepStrictEqual(p2(-1), true) deepStrictEqual(p2(1), true) }) it("getMonoidAny", () => { const M = _.getMonoidAny() const predicate = M.combine(isPositive, M.empty) deepStrictEqual(predicate(0), isPositive(0)) deepStrictEqual(predicate(-1), isPositive(-1)) deepStrictEqual(predicate(1), isPositive(1)) }) it("getSemigroupAll", () => { const S = _.getSemigroupAll() const p1 = S.combine(isPositive, isLessThan2) deepStrictEqual(p1(0), false) deepStrictEqual(p1(-2), false) deepStrictEqual(p1(1), true) const p2 = S.combineMany(isPositive, [isLessThan2]) deepStrictEqual(p2(0), false) deepStrictEqual(p2(-2), false) deepStrictEqual(p2(1), true) }) it("getMonoidAll", () => { const M = _.getMonoidAll() const predicate = M.combine(isPositive, M.empty) deepStrictEqual(predicate(0), isPositive(0)) deepStrictEqual(predicate(-1), isPositive(-1)) deepStrictEqual(predicate(1), isPositive(1)) }) it("any", () => { const predicate = _.any([isPositive, isNegative]) deepStrictEqual(predicate(0), false) deepStrictEqual(predicate(-1), true) deepStrictEqual(predicate(1), true) }) it("all", () => { const predicate = _.all([isPositive, isLessThan2]) deepStrictEqual(predicate(0), false) deepStrictEqual(predicate(-2), false) deepStrictEqual(predicate(1), true) }) it("isFunction", () => { assert.deepStrictEqual(_.isFunction(_.isFunction), true) assert.deepStrictEqual(_.isFunction("function"), false) }) it("isUndefined", () => { assert.deepStrictEqual(_.isUndefined(undefined), true) assert.deepStrictEqual(_.isUndefined(null), false) assert.deepStrictEqual(_.isUndefined("undefined"), false) }) it("isNotUndefined", () => { assert.deepStrictEqual(_.isNotUndefined(undefined), false) assert.deepStrictEqual(_.isNotUndefined(null), true) assert.deepStrictEqual(_.isNotUndefined("undefined"), true) }) it("isNull", () => { assert.deepStrictEqual(_.isNull(null), true) assert.deepStrictEqual(_.isNull(undefined), false) assert.deepStrictEqual(_.isNull("null"), false) }) it("isNotNull", () => { assert.deepStrictEqual(_.isNotNull(null), false) assert.deepStrictEqual(_.isNotNull(undefined), true) assert.deepStrictEqual(_.isNotNull("null"), true) }) it("isNever", () => { assert.deepStrictEqual(_.isNever(null), false) assert.deepStrictEqual(_.isNever(undefined), false) assert.deepStrictEqual(_.isNever({}), false) assert.deepStrictEqual(_.isNever([]), false) }) it("isUnknown", () => { assert.deepStrictEqual(_.isUnknown(null), true) assert.deepStrictEqual(_.isUnknown(undefined), true) assert.deepStrictEqual(_.isUnknown({}), true) assert.deepStrictEqual(_.isUnknown([]), true) }) it("isObject", () => { assert.deepStrictEqual(_.isObject({}), true) assert.deepStrictEqual(_.isObject([]), true) assert.deepStrictEqual(_.isObject(null), false) assert.deepStrictEqual(_.isObject(undefined), false) }) it("isNullable", () => { assert.deepStrictEqual(_.isNullable(null), true) assert.deepStrictEqual(_.isNullable(undefined), true) assert.deepStrictEqual(_.isNullable({}), false) assert.deepStrictEqual(_.isNullable([]), false) }) it("isNotNullable", () => { assert.deepStrictEqual(_.isNotNullable({}), true) assert.deepStrictEqual(_.isNotNullable([]), true) assert.deepStrictEqual(_.isNotNullable(null), false) assert.deepStrictEqual(_.isNotNullable(undefined), false) }) it("isError", () => { assert.deepStrictEqual(_.isError(new Error()), true) assert.deepStrictEqual(_.isError(null), false) assert.deepStrictEqual(_.isError({}), false) }) it("isDate", () => { assert.deepStrictEqual(_.isDate(new Date()), true) assert.deepStrictEqual(_.isDate(null), false) assert.deepStrictEqual(_.isDate({}), false) }) it("isRecord", () => { assert.deepStrictEqual(_.isRecord({}), true) assert.deepStrictEqual(_.isRecord({ a: 1 }), true) assert.deepStrictEqual(_.isRecord([]), false) assert.deepStrictEqual(_.isRecord([1, 2, 3]), false) assert.deepStrictEqual(_.isRecord(null), false) assert.deepStrictEqual(_.isRecord(undefined), false) }) it("isReadonlyRecord", () => { assert.deepStrictEqual(_.isReadonlyRecord({}), true) assert.deepStrictEqual(_.isReadonlyRecord({ a: 1 }), true) assert.deepStrictEqual(_.isReadonlyRecord([]), false) assert.deepStrictEqual(_.isReadonlyRecord([1, 2, 3]), false) assert.deepStrictEqual(_.isReadonlyRecord(null), false) assert.deepStrictEqual(_.isReadonlyRecord(undefined), false) }) }) ================================================ FILE: test/ReadonlyArray.ts ================================================ import * as E from "@fp-ts/core/Either" import { identity, pipe } from "@fp-ts/core/Function" import * as Number from "@fp-ts/core/Number" import * as O from "@fp-ts/core/Option" import type { Predicate } from "@fp-ts/core/Predicate" import * as RA from "@fp-ts/core/ReadonlyArray" import * as String from "@fp-ts/core/String" import { deepStrictEqual, double, strictEqual } from "@fp-ts/core/test/util" import * as Order from "@fp-ts/core/typeclass/Order" import * as assert from "assert" import * as fc from "fast-check" describe.concurrent("ReadonlyArray", () => { it("exports", () => { expect(RA.Invariant).exist expect(RA.tupled).exist expect(RA.bindTo).exist expect(RA.Covariant).exist expect(RA.map).exist expect(RA.let).exist expect(RA.flap).exist expect(RA.as).exist expect(RA.Of).exist expect(RA.of).exist expect(RA.Do).exist expect(RA.Pointed).exist expect(RA.FlatMap).exist expect(RA.flatMap).exist expect(RA.flatten).exist expect(RA.composeKleisliArrow).exist expect(RA.Chainable).exist expect(RA.bind).exist expect(RA.Monad).exist expect(RA.SemiProduct).exist expect(RA.andThenBind).exist expect(RA.Product).exist expect(RA.SemiApplicative).exist expect(RA.lift2).exist expect(RA.ap).exist expect(RA.Applicative).exist expect(RA.liftMonoid).exist expect(RA.Foldable).exist expect(RA.reduce).exist expect(RA.reduceRight).exist expect(RA.reduceKind).exist expect(RA.coproductMapKind).exist expect(RA.Traversable).exist expect(RA.traverse).exist expect(RA.sequence).exist expect(RA.traverseTap).exist expect(RA.compact).exist expect(RA.Filterable).exist expect(RA.filterMap).exist expect(RA.filter).exist expect(RA.partition).exist expect(RA.partitionMap).exist expect(RA.TraversableFilterable).exist expect(RA.traverseFilter).exist expect(RA.traversePartition).exist expect(RA.liftPredicate).exist expect(RA.liftOption).exist expect(RA.liftNullable).exist expect(RA.flatMapNullable).exist }) it("fromIterable/Array should return the same reference if the iterable is an Array", () => { const i = [1, 2, 3] expect(RA.fromIterable(i) === i).toEqual(true) }) it("fromIterable/Iterable", () => { expect(RA.fromIterable(new Set([1, 2, 3]))).toEqual([1, 2, 3]) }) describe("iterable inputs", () => { it("prepend", () => { deepStrictEqual(pipe([1, 2, 3], RA.prepend(0)), [0, 1, 2, 3]) deepStrictEqual(pipe([[2]], RA.prepend([1])), [[1], [2]]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.prepend(0)), [0, 1, 2, 3]) deepStrictEqual(pipe(new Set([[2]]), RA.prepend([1])), [[1], [2]]) }) it("prependAll", () => { deepStrictEqual(pipe([3, 4], RA.prependAll([1, 2])), [1, 2, 3, 4]) deepStrictEqual(pipe([3, 4], RA.prependAll(new Set([1, 2]))), [1, 2, 3, 4]) deepStrictEqual(pipe(new Set([3, 4]), RA.prependAll([1, 2])), [1, 2, 3, 4]) }) it("prependAllNonEmpty", () => { deepStrictEqual(pipe([3, 4], RA.prependAllNonEmpty([1, 2])), [1, 2, 3, 4]) deepStrictEqual(pipe(RA.make(3, 4), RA.prependAllNonEmpty(new Set([1, 2]))), [1, 2, 3, 4]) deepStrictEqual(pipe(new Set([3, 4]), RA.prependAllNonEmpty([1, 2])), [1, 2, 3, 4]) }) it("append", () => { deepStrictEqual(pipe([1, 2, 3], RA.append(4)), [1, 2, 3, 4]) deepStrictEqual(pipe([[1]], RA.append([2])), [[1], [2]]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.append(4)), [1, 2, 3, 4]) deepStrictEqual(pipe(new Set([[1]]), RA.append([2])), [[1], [2]]) }) it("appendAll", () => { deepStrictEqual(pipe([1, 2], RA.appendAll([3, 4])), [1, 2, 3, 4]) deepStrictEqual(pipe([1, 2], RA.appendAll(new Set([3, 4]))), [1, 2, 3, 4]) deepStrictEqual(pipe(new Set([1, 2]), RA.appendAll([3, 4])), [1, 2, 3, 4]) }) it("appendAllNonEmpty", () => { deepStrictEqual(pipe([1, 2], RA.appendAllNonEmpty([3, 4])), [1, 2, 3, 4]) deepStrictEqual(pipe(RA.make(1, 2), RA.appendAllNonEmpty(new Set([3, 4]))), [1, 2, 3, 4]) deepStrictEqual(pipe(new Set([1, 2]), RA.appendAllNonEmpty([3, 4])), [1, 2, 3, 4]) }) it("scan", () => { const f = (b: number, a: number) => b - a deepStrictEqual(pipe([1, 2, 3], RA.scan(10, f)), [10, 9, 7, 4]) deepStrictEqual(pipe([0], RA.scan(10, f)), [10, 10]) deepStrictEqual(pipe([], RA.scan(10, f)), [10]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.scan(10, f)), [10, 9, 7, 4]) deepStrictEqual(pipe(new Set([0]), RA.scan(10, f)), [10, 10]) deepStrictEqual(pipe(new Set([]), RA.scan(10, f)), [10]) }) it("scanRight", () => { const f = (b: number, a: number) => a - b deepStrictEqual(pipe([1, 2, 3], RA.scanRight(10, f)), [-8, 9, -7, 10]) deepStrictEqual(pipe([0], RA.scanRight(10, f)), [-10, 10]) deepStrictEqual(pipe([], RA.scanRight(10, f)), [10]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.scanRight(10, f)), [-8, 9, -7, 10]) deepStrictEqual(pipe(new Set([0]), RA.scanRight(10, f)), [-10, 10]) deepStrictEqual(pipe(new Set([]), RA.scanRight(10, f)), [10]) }) it("tail", () => { deepStrictEqual(RA.tail([1, 2, 3]), O.some([2, 3])) deepStrictEqual(RA.tail([]), O.none()) deepStrictEqual(RA.tail(new Set([1, 2, 3])), O.some([2, 3])) deepStrictEqual(RA.tail(new Set([])), O.none()) }) it("init", () => { deepStrictEqual(RA.init([1, 2, 3]), O.some([1, 2])) deepStrictEqual(RA.init([]), O.none()) deepStrictEqual(RA.init(new Set([1, 2, 3])), O.some([1, 2])) deepStrictEqual(RA.init(new Set([])), O.none()) }) it("take", () => { expect(pipe([1, 2, 3, 4], RA.take(2))).toEqual([1, 2]) expect(pipe([1, 2, 3, 4], RA.take(0))).toEqual([]) // out of bounds expect(pipe([1, 2, 3, 4], RA.take(-10))).toEqual([]) expect(pipe([1, 2, 3, 4], RA.take(10))).toEqual([1, 2, 3, 4]) expect(pipe(new Set([1, 2, 3, 4]), RA.take(2))).toEqual([1, 2]) expect(pipe(new Set([1, 2, 3, 4]), RA.take(0))).toEqual([]) // out of bounds expect(pipe(new Set([1, 2, 3, 4]), RA.take(-10))).toEqual([]) expect(pipe(new Set([1, 2, 3, 4]), RA.take(10))).toEqual([1, 2, 3, 4]) }) it("takeRight", () => { deepStrictEqual(pipe(RA.empty(), RA.takeRight(0)), []) deepStrictEqual(pipe([1, 2], RA.takeRight(0)), []) deepStrictEqual(pipe([1, 2], RA.takeRight(1)), [2]) deepStrictEqual(pipe([1, 2], RA.takeRight(2)), [1, 2]) // out of bound deepStrictEqual(pipe(RA.empty(), RA.takeRight(1)), []) deepStrictEqual(pipe(RA.empty(), RA.takeRight(-1)), []) deepStrictEqual(pipe([1, 2], RA.takeRight(3)), [1, 2]) deepStrictEqual(pipe([1, 2], RA.takeRight(-1)), []) deepStrictEqual(pipe(new Set(), RA.takeRight(0)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.takeRight(0)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.takeRight(1)), [2]) deepStrictEqual(pipe(new Set([1, 2]), RA.takeRight(2)), [1, 2]) // out of bound deepStrictEqual(pipe(new Set(), RA.takeRight(1)), []) deepStrictEqual(pipe(new Set(), RA.takeRight(-1)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.takeRight(3)), [1, 2]) deepStrictEqual(pipe(new Set([1, 2]), RA.takeRight(-1)), []) }) it("takeWhile", () => { const f = (n: number) => n % 2 === 0 deepStrictEqual(pipe([2, 4, 3, 6], RA.takeWhile(f)), [2, 4]) deepStrictEqual(pipe(RA.empty(), RA.takeWhile(f)), []) deepStrictEqual(pipe([1, 2, 4], RA.takeWhile(f)), []) deepStrictEqual(pipe([2, 4], RA.takeWhile(f)), [2, 4]) deepStrictEqual(pipe(new Set([2, 4, 3, 6]), RA.takeWhile(f)), [2, 4]) deepStrictEqual(pipe(new Set(), RA.takeWhile(f)), []) deepStrictEqual(pipe(new Set([1, 2, 4]), RA.takeWhile(f)), []) deepStrictEqual(pipe(new Set([2, 4]), RA.takeWhile(f)), [2, 4]) }) it("span", () => { const f = RA.span((n: number) => n % 2 === 1) const assertSpan = ( input: Iterable, expectedInit: ReadonlyArray, expectedRest: ReadonlyArray ) => { const [init, rest] = f(input) deepStrictEqual(init, expectedInit) deepStrictEqual(rest, expectedRest) } assertSpan([1, 3, 2, 4, 5], [1, 3], [2, 4, 5]) assertSpan(RA.empty(), RA.empty(), RA.empty()) assertSpan([1, 3], [1, 3], RA.empty()) assertSpan([2, 4], RA.empty(), [2, 4]) assertSpan(new Set([1, 3, 2, 4, 5]), [1, 3], [2, 4, 5]) assertSpan(new Set(), RA.empty(), RA.empty()) assertSpan(new Set([1, 3]), [1, 3], RA.empty()) assertSpan(new Set([2, 4]), RA.empty(), [2, 4]) }) it("drop", () => { deepStrictEqual(pipe(RA.empty(), RA.drop(0)), []) deepStrictEqual(pipe([1, 2], RA.drop(0)), [1, 2]) deepStrictEqual(pipe([1, 2], RA.drop(1)), [2]) deepStrictEqual(pipe([1, 2], RA.drop(2)), []) // out of bound deepStrictEqual(pipe(RA.empty(), RA.drop(1)), []) deepStrictEqual(pipe(RA.empty(), RA.drop(-1)), []) deepStrictEqual(pipe([1, 2], RA.drop(3)), []) deepStrictEqual(pipe([1, 2], RA.drop(-1)), [1, 2]) deepStrictEqual(pipe(new Set(), RA.drop(0)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.drop(0)), [1, 2]) deepStrictEqual(pipe(new Set([1, 2]), RA.drop(1)), [2]) deepStrictEqual(pipe(new Set([1, 2]), RA.drop(2)), []) // out of bound deepStrictEqual(pipe(new Set(), RA.drop(1)), []) deepStrictEqual(pipe(new Set(), RA.drop(-1)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.drop(3)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.drop(-1)), [1, 2]) }) it("dropRight", () => { deepStrictEqual(pipe([], RA.dropRight(0)), []) deepStrictEqual(pipe([1, 2], RA.dropRight(0)), [1, 2]) deepStrictEqual(pipe([1, 2], RA.dropRight(1)), [1]) deepStrictEqual(pipe([1, 2], RA.dropRight(2)), []) // out of bound deepStrictEqual(pipe([], RA.dropRight(1)), []) deepStrictEqual(pipe([1, 2], RA.dropRight(3)), []) deepStrictEqual(pipe([], RA.dropRight(-1)), []) deepStrictEqual(pipe([1, 2], RA.dropRight(-1)), [1, 2]) deepStrictEqual(pipe(new Set(), RA.dropRight(0)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.dropRight(0)), [1, 2]) deepStrictEqual(pipe(new Set([1, 2]), RA.dropRight(1)), [1]) deepStrictEqual(pipe(new Set([1, 2]), RA.dropRight(2)), []) // out of bound deepStrictEqual(pipe(new Set(), RA.dropRight(1)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.dropRight(3)), []) deepStrictEqual(pipe(new Set(), RA.dropRight(-1)), []) deepStrictEqual(pipe(new Set([1, 2]), RA.dropRight(-1)), [1, 2]) }) it("dropWhile", () => { const f = RA.dropWhile((n: number) => n > 0) deepStrictEqual(f([]), []) deepStrictEqual(f([1, 2]), RA.empty()) deepStrictEqual(f([-1, -2]), [-1, -2]) deepStrictEqual(f([-1, 2]), [-1, 2]) deepStrictEqual(f([1, -2, 3]), [-2, 3]) deepStrictEqual(f(new Set()), []) deepStrictEqual(f(new Set([1, 2])), RA.empty()) deepStrictEqual(f(new Set([-1, -2])), [-1, -2]) deepStrictEqual(f(new Set([-1, 2])), [-1, 2]) deepStrictEqual(f(new Set([1, -2, 3])), [-2, 3]) }) it("findFirstIndex", () => { deepStrictEqual(pipe([], RA.findFirstIndex((n) => n % 2 === 0)), O.none()) deepStrictEqual(pipe([1, 2, 3], RA.findFirstIndex((n) => n % 2 === 0)), O.some(1)) deepStrictEqual(pipe([1, 2, 3, 1], RA.findFirstIndex((n) => n % 2 === 0)), O.some(1)) deepStrictEqual(pipe(new Set(), RA.findFirstIndex((n) => n % 2 === 0)), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.findFirstIndex((n) => n % 2 === 0)), O.some(1)) deepStrictEqual(pipe(new Set([1, 2, 3, 4]), RA.findFirstIndex((n) => n % 2 === 0)), O.some(1)) }) it("findLastIndex", () => { deepStrictEqual(pipe([], RA.findLastIndex((n) => n % 2 === 0)), O.none()) deepStrictEqual(pipe([1, 2, 3], RA.findLastIndex((n) => n % 2 === 0)), O.some(1)) deepStrictEqual(pipe([1, 2, 3, 4], RA.findLastIndex((n) => n % 2 === 0)), O.some(3)) deepStrictEqual(pipe(new Set(), RA.findLastIndex((n) => n % 2 === 0)), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.findLastIndex((n) => n % 2 === 0)), O.some(1)) deepStrictEqual(pipe(new Set([1, 2, 3, 4]), RA.findLastIndex((n) => n % 2 === 0)), O.some(3)) }) it("findFirst", () => { deepStrictEqual(pipe([], RA.findFirst((n) => n % 2 === 0)), O.none()) deepStrictEqual(pipe([1, 2, 3], RA.findFirst((n) => n % 2 === 0)), O.some(2)) deepStrictEqual(pipe([1, 2, 3, 4], RA.findFirst((n) => n % 2 === 0)), O.some(2)) deepStrictEqual(pipe(new Set(), RA.findFirst((n) => n % 2 === 0)), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.findFirst((n) => n % 2 === 0)), O.some(2)) deepStrictEqual(pipe(new Set([1, 2, 3, 4]), RA.findFirst((n) => n % 2 === 0)), O.some(2)) }) it("findLast", () => { deepStrictEqual(pipe([], RA.findLast((n) => n % 2 === 0)), O.none()) deepStrictEqual(pipe([1, 2, 3], RA.findLast((n) => n % 2 === 0)), O.some(2)) deepStrictEqual(pipe([1, 2, 3, 4], RA.findLast((n) => n % 2 === 0)), O.some(4)) deepStrictEqual(pipe(new Set(), RA.findLast((n) => n % 2 === 0)), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.findLast((n) => n % 2 === 0)), O.some(2)) deepStrictEqual(pipe(new Set([1, 2, 3, 4]), RA.findLast((n) => n % 2 === 0)), O.some(4)) }) it("insertAt", () => { deepStrictEqual(RA.insertAt(1, 1)([]), O.none()) deepStrictEqual(RA.insertAt(0, 1)([]), O.some([1])) deepStrictEqual(RA.insertAt(2, 5)([1, 2, 3, 4]), O.some([1, 2, 5, 3, 4])) // out of bound deepStrictEqual(RA.insertAt(-1, 5)([1, 2, 3, 4]), O.none()) deepStrictEqual(RA.insertAt(10, 5)([1, 2, 3, 4]), O.none()) deepStrictEqual(RA.insertAt(1, 1)(new Set([])), O.none()) deepStrictEqual(RA.insertAt(0, 1)(new Set([])), O.some([1])) deepStrictEqual(RA.insertAt(2, 5)(new Set([1, 2, 3, 4])), O.some([1, 2, 5, 3, 4])) // out of bound deepStrictEqual(RA.insertAt(-1, 5)(new Set([1, 2, 3, 4])), O.none()) deepStrictEqual(RA.insertAt(10, 5)(new Set([1, 2, 3, 4])), O.none()) }) it("replace", () => { deepStrictEqual(pipe([1, 2, 3], RA.replace(1, "a")), [1, "a", 3]) // out of bound deepStrictEqual(pipe([], RA.replace(1, "a")), []) deepStrictEqual(pipe([1, 2, 3], RA.replace(-1, "a")), [1, 2, 3]) deepStrictEqual(pipe([1, 2, 3], RA.replace(10, "a")), [1, 2, 3]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.replace(1, "a")), [1, "a", 3]) // out of bound deepStrictEqual(pipe(new Set([]), RA.replace(1, "a")), []) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.replace(-1, "a")), [1, 2, 3]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.replace(10, "a")), [1, 2, 3]) }) it("replaceOption", () => { deepStrictEqual(pipe([1, 2, 3], RA.replaceOption(1, "a")), O.some([1, "a", 3])) // out of bound deepStrictEqual(pipe([], RA.replaceOption(1, "a")), O.none()) deepStrictEqual(pipe([1, 2, 3], RA.replaceOption(-1, "a")), O.none()) deepStrictEqual(pipe([1, 2, 3], RA.replaceOption(10, "a")), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.replaceOption(1, "a")), O.some([1, "a", 3])) // out of bound deepStrictEqual(pipe(new Set([]), RA.replaceOption(1, "a")), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.replaceOption(-1, "a")), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.replaceOption(10, "a")), O.none()) }) it("modify", () => { deepStrictEqual(pipe([1, 2, 3], RA.modify(1, double)), [1, 4, 3]) // out of bound deepStrictEqual(pipe([], RA.modify(1, double)), []) deepStrictEqual(pipe([1, 2, 3], RA.modify(10, double)), [1, 2, 3]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.modify(1, double)), [1, 4, 3]) // out of bound deepStrictEqual(pipe(new Set([]), RA.modify(1, double)), []) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.modify(10, double)), [1, 2, 3]) }) it("modifyOption", () => { deepStrictEqual(pipe([1, 2, 3], RA.modifyOption(1, double)), O.some([1, 4, 3])) // out of bound deepStrictEqual(pipe([], RA.modifyOption(1, double)), O.none()) deepStrictEqual(pipe([1, 2, 3], RA.modifyOption(10, double)), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.modifyOption(1, double)), O.some([1, 4, 3])) // out of bound deepStrictEqual(pipe(new Set([]), RA.modifyOption(1, double)), O.none()) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.modifyOption(10, double)), O.none()) }) it("remove", () => { deepStrictEqual(pipe([1, 2, 3], RA.remove(0)), [2, 3]) // out of bound deepStrictEqual(pipe([], RA.remove(0)), []) deepStrictEqual(pipe([1, 2, 3], RA.remove(-1)), [1, 2, 3]) deepStrictEqual(pipe([1, 2, 3], RA.remove(10)), [1, 2, 3]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.remove(0)), [2, 3]) // out of bound deepStrictEqual(pipe(new Set([]), RA.remove(0)), []) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.remove(-1)), [1, 2, 3]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.remove(10)), [1, 2, 3]) }) it("reverse", () => { deepStrictEqual(RA.reverse([]), []) deepStrictEqual(RA.reverse([1]), [1]) deepStrictEqual(RA.reverse([1, 2, 3]), [3, 2, 1]) deepStrictEqual(RA.reverse(new Set([])), []) deepStrictEqual(RA.reverse(new Set([1])), [1]) deepStrictEqual(RA.reverse(new Set([1, 2, 3])), [3, 2, 1]) }) it("rights", () => { deepStrictEqual(RA.rights([]), []) deepStrictEqual(RA.rights([E.right(1), E.left("a"), E.right(2)]), [1, 2]) deepStrictEqual(RA.rights(new Set>()), []) deepStrictEqual(RA.rights(new Set([E.right(1), E.left("a"), E.right(2)])), [1, 2]) }) it("lefts", () => { deepStrictEqual(RA.lefts([]), []) deepStrictEqual(RA.lefts([E.right(1), E.left("a"), E.right(2)]), ["a"]) deepStrictEqual(RA.lefts(new Set>()), []) deepStrictEqual(RA.lefts(new Set([E.right(1), E.left("a"), E.right(2)])), ["a"]) }) it("sort", () => { deepStrictEqual(RA.sort(Number.Order)([]), []) deepStrictEqual(RA.sort(Number.Order)([1, 3, 2]), [1, 2, 3]) deepStrictEqual(RA.sort(Number.Order)(new Set()), []) deepStrictEqual(RA.sort(Number.Order)(new Set([1, 3, 2])), [1, 2, 3]) }) it("zip", () => { deepStrictEqual(pipe(new Set([]), RA.zip(new Set(["a", "b", "c", "d"]))), []) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.zip(new Set([]))), []) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.zip(new Set(["a", "b", "c", "d"]))), [ [1, "a"], [2, "b"], [3, "c"] ]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.zip(new Set(["a", "b", "c", "d"]))), [ [1, "a"], [2, "b"], [3, "c"] ]) }) it("zipWith", () => { deepStrictEqual( pipe(new Set([1, 2, 3]), RA.zipWith(new Set([]), (n, s) => s + n)), [] ) deepStrictEqual( pipe(new Set([]), RA.zipWith(new Set(["a", "b", "c", "d"]), (n, s) => s + n)), [] ) deepStrictEqual( pipe(new Set([]), RA.zipWith(new Set([]), (n, s) => s + n)), [] ) deepStrictEqual( pipe(new Set([1, 2, 3]), RA.zipWith(new Set(["a", "b", "c", "d"]), (n, s) => s + n)), ["a1", "b2", "c3"] ) }) it("unzip", () => { deepStrictEqual(RA.unzip(new Set([])), [[], []]) deepStrictEqual( RA.unzip( new Set([ [1, "a"], [2, "b"], [3, "c"] ]) ), [ [1, 2, 3], ["a", "b", "c"] ] ) }) it("intersperse", () => { deepStrictEqual(pipe([], RA.intersperse(0)), []) deepStrictEqual(pipe([1], RA.intersperse(0)), [1]) deepStrictEqual(pipe([1, 2, 3], RA.intersperse(0)), [1, 0, 2, 0, 3]) deepStrictEqual(pipe([1, 2], RA.intersperse(0)), [1, 0, 2]) deepStrictEqual(pipe([1, 2, 3, 4], RA.intersperse(0)), [1, 0, 2, 0, 3, 0, 4]) deepStrictEqual(pipe(new Set([]), RA.intersperse(0)), []) deepStrictEqual(pipe(new Set([1]), RA.intersperse(0)), [1]) deepStrictEqual(pipe(new Set([1, 2, 3]), RA.intersperse(0)), [1, 0, 2, 0, 3]) deepStrictEqual(pipe(new Set([1, 2]), RA.intersperse(0)), [1, 0, 2]) deepStrictEqual(pipe(new Set([1, 2, 3, 4]), RA.intersperse(0)), [1, 0, 2, 0, 3, 0, 4]) }) it("rotate", () => { deepStrictEqual(RA.rotate(0)(RA.empty()), RA.empty()) deepStrictEqual(RA.rotate(1)(RA.empty()), RA.empty()) deepStrictEqual(RA.rotate(1)([1]), [1]) deepStrictEqual(RA.rotate(2)([1]), [1]) deepStrictEqual(RA.rotate(-1)([1]), [1]) deepStrictEqual(RA.rotate(-2)([1]), [1]) deepStrictEqual(RA.rotate(2)([1, 2]), [1, 2]) deepStrictEqual(RA.rotate(0)([1, 2]), [1, 2]) deepStrictEqual(RA.rotate(-2)([1, 2]), [1, 2]) deepStrictEqual(RA.rotate(1)([1, 2]), [2, 1]) deepStrictEqual(RA.rotate(1)(new Set([1, 2, 3, 4, 5])), [5, 1, 2, 3, 4]) deepStrictEqual(RA.rotate(2)(new Set([1, 2, 3, 4, 5])), [4, 5, 1, 2, 3]) deepStrictEqual(RA.rotate(-1)(new Set([1, 2, 3, 4, 5])), [2, 3, 4, 5, 1]) deepStrictEqual(RA.rotate(-2)(new Set([1, 2, 3, 4, 5])), [3, 4, 5, 1, 2]) // out of bounds deepStrictEqual(RA.rotate(7)([1, 2, 3, 4, 5]), [4, 5, 1, 2, 3]) deepStrictEqual(RA.rotate(-7)([1, 2, 3, 4, 5]), [3, 4, 5, 1, 2]) deepStrictEqual(RA.rotate(2.2)([1, 2, 3, 4, 5]), [4, 5, 1, 2, 3]) deepStrictEqual(RA.rotate(-2.2)([1, 2, 3, 4, 5]), [3, 4, 5, 1, 2]) }) it("contains", () => { const contains = RA.contains(Number.Equivalence) deepStrictEqual(pipe([1, 2, 3], contains(2)), true) deepStrictEqual(pipe([1, 2, 3], contains(0)), false) deepStrictEqual(pipe(new Set([1, 2, 3]), contains(2)), true) deepStrictEqual(pipe(new Set([1, 2, 3]), contains(0)), false) }) it("uniq", () => { const uniq = RA.uniq(Number.Equivalence) deepStrictEqual(uniq([]), []) deepStrictEqual(uniq([-0, -0]), [-0]) deepStrictEqual(uniq([0, -0]), [0]) deepStrictEqual(uniq([1]), [1]) deepStrictEqual(uniq([2, 1, 2]), [2, 1]) deepStrictEqual(uniq([1, 2, 1]), [1, 2]) deepStrictEqual(uniq([1, 2, 3, 4, 5]), [1, 2, 3, 4, 5]) deepStrictEqual(uniq([1, 1, 2, 2, 3, 3, 4, 4, 5, 5]), [1, 2, 3, 4, 5]) deepStrictEqual(uniq([1, 2, 3, 4, 5, 1, 2, 3, 4, 5]), [1, 2, 3, 4, 5]) }) it("splitAt", () => { const assertSplitAt = ( input: ReadonlyArray, index: number, expectedInit: ReadonlyArray, expectedRest: ReadonlyArray ) => { const [init, rest] = RA.splitAt(index)(input) deepStrictEqual(init, expectedInit) deepStrictEqual(rest, expectedRest) } deepStrictEqual(RA.splitAt(1)([1, 2]), [[1], [2]]) assertSplitAt([1, 2], 2, [1, 2], []) deepStrictEqual(RA.splitAt(2)([1, 2, 3, 4, 5]), [ [1, 2], [3, 4, 5] ]) deepStrictEqual(RA.splitAt(2)(new Set([1, 2, 3, 4, 5])), [ [1, 2], [3, 4, 5] ]) assertSplitAt([], 0, [], []) assertSplitAt([1, 2], 0, [], [1, 2]) // out of bounds assertSplitAt([], -1, [], []) assertSplitAt([1, 2], -1, [], [1, 2]) assertSplitAt([1, 2], 3, [1, 2], []) assertSplitAt([], 3, [], []) }) }) it("splitNonEmptyAt", () => { deepStrictEqual(pipe(RA.make(1, 2, 3, 4), RA.splitNonEmptyAt(2)), [[1, 2], [3, 4]]) }) it("rotateNonEmpty", () => { deepStrictEqual(RA.rotateNonEmpty(2)([1, 2, 3, 4, 5]), [4, 5, 1, 2, 3]) }) it("intersperseNonEmpty", () => { deepStrictEqual(pipe(RA.make(1), RA.intersperseNonEmpty(0)), [1]) deepStrictEqual(pipe(RA.make(1, 2, 3), RA.intersperseNonEmpty(0)), [1, 0, 2, 0, 3]) }) it("sortNonEmpty", () => { deepStrictEqual(RA.sortNonEmpty(Number.Order)([1]), [1]) deepStrictEqual(RA.sortNonEmpty(Number.Order)([1, 3, 2]), [1, 2, 3]) }) describe("unsafeGet", () => { it("should throw on index out of bound", () => { expect(() => pipe([], RA.unsafeGet(100))).toThrowError(new Error("Index 100 out of bounds")) }) }) it("fromNullable", () => { deepStrictEqual(RA.fromNullable(undefined), []) deepStrictEqual(RA.fromNullable(null), []) deepStrictEqual(RA.fromNullable(1), [1]) }) it("liftNullable", () => { const f = RA.liftNullable((n: number) => (n > 0 ? n : null)) deepStrictEqual(f(1), [1]) deepStrictEqual(f(-1), []) }) it("flatMapNullable", () => { const f = RA.flatMapNullable((n: number) => (n > 0 ? n : null)) deepStrictEqual(pipe([], f), []) deepStrictEqual(pipe([1], f), [1]) deepStrictEqual(pipe([-1], f), []) }) it("liftPredicate", () => { const p = (n: number): boolean => n > 2 const f = RA.liftPredicate(p) deepStrictEqual(f(1), []) deepStrictEqual(f(3), [3]) }) it("liftOption", () => { const f = RA.liftOption((n: number) => (n > 0 ? O.some(n) : O.none())) deepStrictEqual(f(1), [1]) deepStrictEqual(f(-1), []) }) it("unprepend", () => { deepStrictEqual(RA.unprepend([0]), [0, []]) deepStrictEqual(RA.unprepend([1, 2, 3, 4]), [1, [2, 3, 4]]) }) it("unappend", () => { deepStrictEqual(RA.unappend([0]), [[], 0]) deepStrictEqual(RA.unappend([1, 2, 3, 4]), [ RA.make(1, 2, 3), 4 ]) deepStrictEqual(RA.unappend([0]), [[], 0]) deepStrictEqual(RA.unappend([1, 2, 3, 4]), [ RA.make(1, 2, 3), 4 ]) }) it("modifyNonEmptyHead", () => { const f = (s: string) => s + "!" deepStrictEqual(pipe(["a"], RA.modifyNonEmptyHead(f)), ["a!"]) deepStrictEqual(pipe(["a", "b"], RA.modifyNonEmptyHead(f)), ["a!", "b"]) deepStrictEqual(pipe(["a", "b", "c"], RA.modifyNonEmptyHead(f)), ["a!", "b", "c"]) }) it("modifyNonEmptyLast", () => { const f = (s: string) => s + "!" deepStrictEqual(pipe(["a"], RA.modifyNonEmptyLast(f)), ["a!"]) deepStrictEqual(pipe(["a", "b"], RA.modifyNonEmptyLast(f)), ["a", "b!"]) deepStrictEqual(pipe(["a", "b", "c"], RA.modifyNonEmptyLast(f)), ["a", "b", "c!"]) }) it("setNonEmptyHead", () => { deepStrictEqual(pipe(RA.make("a"), RA.setNonEmptyHead("d")), ["d"]) deepStrictEqual(pipe(RA.make("a", "b"), RA.setNonEmptyHead("d")), ["d", "b"]) deepStrictEqual(pipe(RA.make("a", "b", "c"), RA.setNonEmptyHead("d")), ["d", "b", "c"]) }) it("setNonEmptyLast", () => { deepStrictEqual(pipe(RA.make("a"), RA.setNonEmptyLast("d")), ["d"]) deepStrictEqual(pipe(RA.make("a", "b"), RA.setNonEmptyLast("d")), ["a", "d"]) deepStrictEqual(pipe(RA.make("a", "b", "c"), RA.setNonEmptyLast("d")), ["a", "b", "d"]) }) it("liftEither", () => { const f = RA.liftEither((s: string) => s.length > 2 ? E.right(s.length) : E.left("e")) deepStrictEqual(f("a"), []) deepStrictEqual(f("aaa"), [3]) }) it("headNonEmpty", () => { deepStrictEqual(RA.headNonEmpty(RA.make(1, 2)), 1) }) it("tailNonEmpty", () => { deepStrictEqual(RA.tailNonEmpty(RA.make(1, 2)), [2]) }) it("lastNonEmpty", () => { deepStrictEqual(RA.lastNonEmpty(RA.make(1, 2, 3)), 3) deepStrictEqual(RA.lastNonEmpty([1]), 1) }) it("initNonEmpty", () => { deepStrictEqual( RA.initNonEmpty(RA.make(1, 2, 3)), RA.make(1, 2) ) deepStrictEqual(RA.initNonEmpty([1]), []) }) it("traverse", () => { const traverse = RA.traverse(O.Applicative)(( n: number ): O.Option => (n % 2 === 0 ? O.none() : O.some(n))) deepStrictEqual(traverse([1, 2]), O.none()) deepStrictEqual(traverse([1, 3]), O.some([1, 3])) deepStrictEqual( pipe( ["a", "bb"], RA.traverse(O.Applicative)(( s, i ) => (s.length >= 1 ? O.some(s + i) : O.none())) ), O.some(["a0", "bb1"]) ) deepStrictEqual( pipe( ["a", "bb"], RA.traverse(O.Applicative)(( s, i ) => (s.length > 1 ? O.some(s + i) : O.none())) ), O.none() ) }) it("sequence", () => { const sequence = RA.sequence(O.Applicative) deepStrictEqual(sequence([O.some(1), O.some(3)]), O.some([1, 3])) deepStrictEqual(sequence([O.some(1), O.none()]), O.none()) }) it("get", () => { deepStrictEqual(pipe([1, 2, 3], RA.get(0)), O.some(1)) deepStrictEqual(pipe([1, 2, 3], RA.get(3)), O.none()) }) it("unfold", () => { const as = RA.unfold(5, (n) => (n > 0 ? O.some([n, n - 1]) : O.none())) deepStrictEqual(as, [5, 4, 3, 2, 1]) }) it("map", () => { deepStrictEqual( pipe( [1, 2, 3], RA.map((n) => n * 2) ), [2, 4, 6] ) deepStrictEqual( pipe( ["a", "b"], RA.map((s, i) => s + i) ), ["a0", "b1"] ) }) it("ap", () => { deepStrictEqual( pipe([(x: number) => x * 2, (x: number) => x * 3], RA.ap([1, 2, 3])), [ 2, 4, 6, 3, 6, 9 ] ) }) it("flatMap", () => { deepStrictEqual( pipe( [1, 2, 3], RA.flatMap((n) => [n, n + 1]) ), [1, 2, 2, 3, 3, 4] ) const f = RA.flatMap((n: number, i) => [n + i]) deepStrictEqual(pipe([], f), []) deepStrictEqual(pipe([1, 2, 3], f), [1, 3, 5]) }) it("extend", () => { deepStrictEqual(pipe([1, 2, 3, 4], RA.extend(Number.sumAll)), [10, 9, 7, 4]) deepStrictEqual(pipe([1, 2, 3, 4], RA.extend(identity)), [ [1, 2, 3, 4], [2, 3, 4], [3, 4], [4] ]) }) it("combineMap", () => { deepStrictEqual(pipe(["a", "b", "c"], RA.combineMap(String.Monoid)(identity)), "abc") deepStrictEqual(pipe([], RA.combineMap(String.Monoid)(identity)), "") }) it("compact", () => { assert.deepStrictEqual(RA.compact([]), []) assert.deepStrictEqual(RA.compact([O.some(1), O.some(2), O.some(3)]), [ 1, 2, 3 ]) assert.deepStrictEqual(RA.compact([O.some(1), O.none(), O.some(3)]), [ 1, 3 ]) }) it("separate", () => { assert.deepStrictEqual(RA.separate([]), [[], []]) assert.deepStrictEqual(pipe([E.right(1), E.left("e"), E.right(2)], RA.separate), [ ["e"], [1, 2] ]) }) it("filter", () => { const g = (n: number) => n % 2 === 1 deepStrictEqual(pipe([1, 2, 3], RA.filter(g)), [1, 3]) const x = pipe( [O.some(3), O.some(2), O.some(1)], RA.filter(O.isSome) ) assert.deepStrictEqual(x, [O.some(3), O.some(2), O.some(1)]) const y = pipe( [O.some(3), O.none(), O.some(1)], RA.filter(O.isSome) ) assert.deepStrictEqual(y, [O.some(3), O.some(1)]) const f = (n: number) => n % 2 === 0 deepStrictEqual(pipe(["a", "b", "c"], RA.filter((_, i) => f(i))), [ "a", "c" ]) }) it("filterMap", () => { const f = (n: number) => (n % 2 === 0 ? O.none() : O.some(n)) deepStrictEqual(pipe([1, 2, 3], RA.filterMap(f)), [1, 3]) deepStrictEqual(pipe([], RA.filterMap(f)), []) const g = (n: number, i: number) => ((i + n) % 2 === 0 ? O.none() : O.some(n)) deepStrictEqual(pipe([1, 2, 4], RA.filterMap(g)), [1, 2]) deepStrictEqual(pipe([], RA.filterMap(g)), []) }) it("combineMap", () => { deepStrictEqual( pipe( ["a", "b"], RA.combineMap(String.Monoid)((a, i) => i + a) ), "0a1b" ) }) it("partitionMap", () => { deepStrictEqual(pipe([], RA.partitionMap(identity)), [[], []]) deepStrictEqual( pipe( [E.right(1), E.left("foo"), E.right(2)], RA.partitionMap(identity) ), [["foo"], [1, 2]] ) deepStrictEqual( pipe( [E.right(1), E.left("foo"), E.right(2)], RA.partitionMap((a, i) => pipe(a, E.filter((n) => n > i, () => "err"))) ), [["foo", "err"], [1]] ) }) it("partition", () => { deepStrictEqual( pipe([], RA.partition((n) => n > 2)), [[], []] ) deepStrictEqual( pipe([1, 3], RA.partition((n) => n > 2)), [[1], [3]] ) deepStrictEqual( pipe([], RA.partition((i, n) => i + n > 2)), [[], []] ) deepStrictEqual( pipe([1, 2], RA.partition((i, n) => i + n > 2)), [[1], [2]] ) }) it("reduce", () => { deepStrictEqual(pipe(["a", "b", "c"], RA.reduce("", (b, a) => b + a)), "abc") deepStrictEqual( pipe( ["a", "b"], RA.reduce("", (b, a, i) => b + i + a) ), "0a1b" ) }) it("reduceRight", () => { const f = (b: string, a: string) => b + a deepStrictEqual(pipe(["a", "b", "c"], RA.reduceRight("", f)), "cba") deepStrictEqual(pipe([], RA.reduceRight("", f)), "") deepStrictEqual( pipe( ["a", "b"], RA.reduceRight("", (b, a, i) => b + i + a) ), "1b0a" ) }) it("traverseNonEmpty", () => { const traverseNonEmpty = RA.traverseNonEmpty(O.Applicative) deepStrictEqual( pipe( RA.make(1, 2, 3), traverseNonEmpty((n) => (n >= 0 ? O.some(n) : O.none())) ), O.some(RA.make(1, 2, 3)) ) deepStrictEqual( pipe( RA.make(1, 2, 3), traverseNonEmpty((n) => (n >= 2 ? O.some(n) : O.none())) ), O.none() ) deepStrictEqual( pipe( RA.make("a", "bb"), RA.traverseNonEmpty(O.Applicative)((s, i) => (s.length >= 1 ? O.some(s + i) : O.none())) ), O.some(RA.make("a0", "bb1")) ) deepStrictEqual( pipe( RA.make("a", "bb"), RA.traverseNonEmpty(O.Applicative)((s, i) => (s.length > 1 ? O.some(s + i) : O.none())) ), O.none() ) }) it("getMonoid", () => { const M = RA.getMonoid() deepStrictEqual(M.combine([1, 2], [3, 4]), [1, 2, 3, 4]) const x = [1, 2] deepStrictEqual(M.combine(x, M.empty), x) deepStrictEqual(M.combine(M.empty, x), x) deepStrictEqual(M.combineAll([[1, 2], [3, 4, 5], [5, 6, 7, 1]]), [1, 2, 3, 4, 5, 5, 6, 7, 1]) }) it("getOrder", () => { const O = RA.getOrder(String.Order) deepStrictEqual(O.compare([], []), 0) deepStrictEqual(O.compare(["a"], ["a"]), 0) deepStrictEqual(O.compare(["a"], ["b"]), -1) deepStrictEqual(O.compare(["b"], ["a"]), 1) deepStrictEqual(O.compare([], ["a"]), -1) deepStrictEqual(O.compare(["a"], []), 1) deepStrictEqual(O.compare(["a"], ["a", "a"]), -1) deepStrictEqual(O.compare(["b"], ["a", "a"]), 1) deepStrictEqual(O.compare(["a", "a"], ["a", "a"]), 0) deepStrictEqual(O.compare(["a", "b"], ["a", "b"]), 0) deepStrictEqual(O.compare(["a", "b"], ["a", "a"]), 1) deepStrictEqual(O.compare(["a", "a"], ["a", "b"]), -1) deepStrictEqual(O.compare(["b", "a"], ["a", "b"]), 1) deepStrictEqual(O.compare(["a", "a"], ["b", "a"]), -1) deepStrictEqual(O.compare(["a", "b"], ["b", "a"]), -1) deepStrictEqual(O.compare(["b", "a"], ["b", "b"]), -1) deepStrictEqual(O.compare(["b", "b"], ["b", "a"]), 1) }) it("isEmpty", () => { deepStrictEqual(RA.isEmpty([1, 2, 3]), false) deepStrictEqual(RA.isEmpty([]), true) }) it("isEmptyArray", () => { deepStrictEqual(RA.isEmptyArray([1, 2, 3]), false) deepStrictEqual(RA.isEmptyArray([]), true) }) it("isNotEmpty", () => { deepStrictEqual(RA.isNonEmpty([1, 2, 3]), true) deepStrictEqual(RA.isNonEmpty([]), false) }) it("isNonEmptyArray", () => { deepStrictEqual(RA.isNonEmptyArray([1, 2, 3]), true) deepStrictEqual(RA.isNonEmptyArray([]), false) }) it("head", () => { const as: ReadonlyArray = [1, 2, 3] deepStrictEqual(RA.head(as), O.some(1)) deepStrictEqual(RA.head([]), O.none()) }) it("last", () => { const as: ReadonlyArray = [1, 2, 3] deepStrictEqual(RA.last(as), O.some(3)) deepStrictEqual(RA.last([]), O.none()) }) it("zipNonEmptyWith", () => { deepStrictEqual( pipe([1, 2, 3], RA.zipNonEmptyWith(["a", "b", "c", "d"], (n, s) => s + n)), ["a1", "b2", "c3"] ) }) it("zipNonEmpty", () => { deepStrictEqual(pipe(RA.make(1, 2, 3), RA.zipNonEmpty(["a", "b", "c", "d"])), [ [1, "a"], [2, "b"], [3, "c"] ]) }) it("unzipNonEmpty", () => { deepStrictEqual( RA.unzipNonEmpty([ [1, "a"], [2, "b"], [3, "c"] ]), [ [1, 2, 3], ["a", "b", "c"] ] ) }) it("flatMapNonEmpty", () => { const f = (a: number): RA.NonEmptyReadonlyArray => [a, 4] deepStrictEqual(pipe(RA.make(1, 2), RA.flatMapNonEmpty(f)), [1, 4, 2, 4]) const g = (a: number, i: number): RA.NonEmptyReadonlyArray => [a + i, 4] deepStrictEqual(pipe(RA.make(1, 2), RA.flatMapNonEmpty(g)), [1, 4, 3, 4]) }) it("chunksOfNonEmpty", () => { deepStrictEqual(RA.chunksOfNonEmpty(2)([1, 2, 3, 4, 5]), [ RA.make(1, 2), [3, 4], [5] ]) deepStrictEqual(RA.chunksOfNonEmpty(2)([1, 2, 3, 4, 5, 6]), [ RA.make(1, 2), [3, 4], [5, 6] ]) deepStrictEqual(RA.chunksOfNonEmpty(1)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) deepStrictEqual(RA.chunksOfNonEmpty(5)([1, 2, 3, 4, 5]), [[1, 2, 3, 4, 5]]) // out of bounds deepStrictEqual(RA.chunksOfNonEmpty(0)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) deepStrictEqual(RA.chunksOfNonEmpty(-1)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) const assertSingleChunk = ( input: RA.NonEmptyReadonlyArray, n: number ) => { const chunks = RA.chunksOfNonEmpty(n)(input) strictEqual(chunks.length, 1) deepStrictEqual(RA.headNonEmpty(chunks), input) } // n = length assertSingleChunk(RA.make(1, 2), 2) // n out of bounds assertSingleChunk(RA.make(1, 2), 3) }) it("mapNonEmpty", () => { deepStrictEqual( pipe( RA.make(RA.make(1, 2), RA.make(3, 4)), RA.flattenNonEmpty ), [1, 2, 3, 4] ) deepStrictEqual( pipe(RA.make("a", "b"), RA.mapNonEmpty((s: string, i: number) => s + i)), ["a0", "b1"] ) }) it("sequenceNonEmpty", () => { const sequence = RA.sequenceNonEmpty(O.Applicative) deepStrictEqual( sequence([O.some(1), O.some(2), O.some(3)]), O.some(RA.make(1, 2, 3)) ) deepStrictEqual(sequence([O.none(), O.some(2), O.some(3)]), O.none()) }) it("mapNonEmpty", () => { deepStrictEqual( pipe( RA.make(1, 2), RA.mapNonEmpty((n) => n * 2) ), [2, 4] ) }) it("min", () => { deepStrictEqual(RA.min(Number.Order)([2, 1, 3]), 1) deepStrictEqual(RA.min(Number.Order)([3]), 3) }) it("max", () => { deepStrictEqual( RA.max(Number.Order)(RA.make(1, 2, 3)), 3 ) deepStrictEqual(RA.max(Number.Order)([1]), 1) }) it("flatten", () => { deepStrictEqual(RA.flatten([[1], [2], [3]]), [1, 2, 3]) }) it("intercalate", () => { deepStrictEqual(RA.intercalate(String.Monoid)("-")([]), "") deepStrictEqual(RA.intercalate(String.Monoid)("-")(["a"]), "a") deepStrictEqual(RA.intercalate(String.Monoid)("-")(["a", "b", "c"]), "a-b-c") deepStrictEqual(RA.intercalate(String.Monoid)("-")(["a", "", "c"]), "a--c") deepStrictEqual(RA.intercalate(String.Monoid)("-")(["a", "b"]), "a-b") deepStrictEqual(RA.intercalate(String.Monoid)("-")(["a", "b", "c", "d"]), "a-b-c-d") }) it("group", () => { const group = RA.group(Number.Equivalence) deepStrictEqual(group([1, 2, 1, 1]), [[1], [2], [1, 1]]) deepStrictEqual(group([1, 2, 1, 1, 3]), [[1], [2], [1, 1], [3]]) }) it("groupBy", () => { deepStrictEqual(RA.groupBy((_) => "")([]), {}) deepStrictEqual(RA.groupBy((a) => `${a}`)([1]), { "1": [1] }) deepStrictEqual( RA.groupBy((s: string) => `${s.length}`)(["foo", "bar", "foobar"]), { "3": ["foo", "bar"], "6": ["foobar"] } ) }) it("reverseNonEmpty", () => { deepStrictEqual(RA.reverseNonEmpty([1]), [1]) deepStrictEqual(RA.reverseNonEmpty(RA.make(1, 2, 3)), [3, 2, 1]) }) it("match", () => { const len: (as: ReadonlyArray) => number = RA.match( () => 0, (as) => 1 + len(as.slice(1)) ) deepStrictEqual(len([1, 2, 3]), 3) }) it("matchLeft", () => { const len: (as: ReadonlyArray) => number = RA.matchLeft( () => 0, (_, tail) => 1 + len(tail) ) deepStrictEqual(len([1, 2, 3]), 3) }) it("matchRight", () => { const len: (as: ReadonlyArray) => number = RA.matchRight( () => 0, (init, _) => 1 + len(init) ) deepStrictEqual(len([1, 2, 3]), 3) }) it("uniqNonEmpty", () => { const uniqNonEmpty = RA.uniqNonEmpty(String.Equivalence) deepStrictEqual(uniqNonEmpty(["a", "b", "A"]), ["a", "b", "A"]) }) it("sortBy / sortByNonEmpty", () => { interface X { readonly a: string readonly b: number readonly c: boolean } const byName = pipe( String.Order, Order.contramap((p: { readonly a: string; readonly b: number }) => p.a) ) const byAge = pipe( Number.Order, Order.contramap((p: { readonly a: string; readonly b: number }) => p.b) ) const sortByNameByAge = RA.sortBy(byName, byAge) const xs: RA.NonEmptyArray = [ { a: "a", b: 1, c: true }, { a: "b", b: 3, c: true }, { a: "c", b: 2, c: true }, { a: "b", b: 2, c: true } ] deepStrictEqual(RA.sortBy()(xs), xs) deepStrictEqual(sortByNameByAge([]), []) deepStrictEqual(sortByNameByAge(xs), [ { a: "a", b: 1, c: true }, { a: "b", b: 2, c: true }, { a: "b", b: 3, c: true }, { a: "c", b: 2, c: true } ]) deepStrictEqual(RA.sortBy()(new Set(xs)), xs) deepStrictEqual(sortByNameByAge(new Set([])), []) deepStrictEqual(sortByNameByAge(new Set(xs)), [ { a: "a", b: 1, c: true }, { a: "b", b: 2, c: true }, { a: "b", b: 3, c: true }, { a: "c", b: 2, c: true } ]) const sortByAgeByName = RA.sortByNonEmpty(byAge, byName) deepStrictEqual(sortByAgeByName(xs), [ { a: "a", b: 1, c: true }, { a: "b", b: 2, c: true }, { a: "c", b: 2, c: true }, { a: "b", b: 3, c: true } ]) }) it("copy", () => { expect(pipe([], RA.copy)).toEqual([]) expect(pipe([1, 2, 3], RA.copy)).toEqual([1, 2, 3]) }) it("intercalateNonEmpty", () => { expect(pipe(["a"], RA.intercalateNonEmpty(String.Semigroup)("b"))).toEqual("a") expect(pipe(["a1", "a2"], RA.intercalateNonEmpty(String.Semigroup)("b"))).toEqual("a1ba2") }) it("join", () => { expect(pipe([], RA.join(", "))).toEqual("") expect(pipe(["a"], RA.join(", "))).toEqual("a") expect(pipe(["a", "b"], RA.join(", "))).toEqual("a, b") }) it("chop", () => { const f = RA.chop((as) => [as[0] * 2, as.slice(1)]) const empty: ReadonlyArray = [] deepStrictEqual(f(empty), RA.empty()) deepStrictEqual(f(RA.empty()), RA.empty()) deepStrictEqual(f([1, 2, 3]), [2, 4, 6]) deepStrictEqual(RA.chopNonEmpty((as) => [as[0] * 2, as.slice(1)])([1, 2, 3]), [ 2, 4, 6 ]) }) describe.concurrent("chunksOf", () => { it("should split a `ReadonlyArray` into length-n pieces", () => { deepStrictEqual(RA.chunksOf(2)([1, 2, 3, 4, 5]), [[1, 2], [3, 4], [5]]) deepStrictEqual(RA.chunksOf(2)([1, 2, 3, 4, 5, 6]), [ [1, 2], [3, 4], [5, 6] ]) deepStrictEqual(RA.chunksOf(1)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) deepStrictEqual(RA.chunksOf(5)([1, 2, 3, 4, 5]), [[1, 2, 3, 4, 5]]) // out of bounds deepStrictEqual(RA.chunksOf(0)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) deepStrictEqual(RA.chunksOf(-1)([1, 2, 3, 4, 5]), [[1], [2], [3], [4], [5]]) const assertSingleChunk = (input: ReadonlyArray, n: number) => { const chunks = RA.chunksOf(n)(input) deepStrictEqual(chunks.length, 1) deepStrictEqual(chunks[0], input) } // n = length assertSingleChunk([1, 2], 2) // n out of bounds assertSingleChunk([1, 2], 3) }) it("returns an empty array if provided an empty array", () => { const empty: ReadonlyArray = [] deepStrictEqual(RA.chunksOf(0)(empty), RA.empty()) deepStrictEqual(RA.chunksOf(0)(RA.empty()), RA.empty()) deepStrictEqual(RA.chunksOf(1)(empty), RA.empty()) deepStrictEqual(RA.chunksOf(1)(RA.empty()), RA.empty()) deepStrictEqual(RA.chunksOf(2)(empty), RA.empty()) deepStrictEqual(RA.chunksOf(2)(RA.empty()), RA.empty()) }) it("should respect the law: chunksOf(n)(xs).concat(chunksOf(n)(ys)) == chunksOf(n)(xs.concat(ys)))", () => { const xs: ReadonlyArray = [] const ys: ReadonlyArray = [1, 2] deepStrictEqual( RA.chunksOf(2)(xs).concat(RA.chunksOf(2)(ys)), RA.chunksOf(2)(xs.concat(ys)) ) fc.assert( fc.property( fc.array(fc.integer()).filter((xs) => xs.length % 2 === 0), // Ensures `xs.length` is even fc.array(fc.integer()), fc.integer({ min: 1, max: 1 }).map((x) => x * 2), // Generates `n` to be even so that it evenly divides `xs` (xs, ys, n) => { const as = RA.chunksOf(n)(xs).concat(RA.chunksOf(n)(ys)) const bs = RA.chunksOf(n)(xs.concat(ys)) deepStrictEqual(as, bs) } ) ) }) }) it("makeBy", () => { deepStrictEqual(RA.makeBy(5, n => n * 2), [0, 2, 4, 6, 8]) deepStrictEqual(RA.makeBy(2.2, n => n * 2), [0, 2]) }) it("replicate", () => { deepStrictEqual(RA.replicate("a", 0), ["a"]) deepStrictEqual(RA.replicate("a", -1), ["a"]) deepStrictEqual(RA.replicate("a", 3), ["a", "a", "a"]) deepStrictEqual(RA.replicate("a", 2.2), ["a", "a"]) }) it("range", () => { deepStrictEqual(RA.range(0, 0), [0]) deepStrictEqual(RA.range(0, 1), [0, 1]) deepStrictEqual(RA.range(1, 5), [1, 2, 3, 4, 5]) deepStrictEqual(RA.range(10, 15), [10, 11, 12, 13, 14, 15]) deepStrictEqual(RA.range(-1, 0), [-1, 0]) deepStrictEqual(RA.range(-5, -1), [-5, -4, -3, -2, -1]) // out of bound deepStrictEqual(RA.range(2, 1), [2]) deepStrictEqual(RA.range(-1, -2), [-1]) }) it("union", () => { const union = RA.union(Number.Equivalence) const two: ReadonlyArray = [1, 2] deepStrictEqual(pipe(two, union([3, 4])), [1, 2, 3, 4]) deepStrictEqual(pipe(two, union([2, 3])), [1, 2, 3]) deepStrictEqual(pipe(two, union([1, 2])), [1, 2]) deepStrictEqual(pipe(two, union(RA.empty())), two) deepStrictEqual(pipe(RA.empty(), union(two)), two) deepStrictEqual( pipe(RA.empty(), union(RA.empty())), RA.empty() ) deepStrictEqual(RA.unionNonEmpty(Number.Equivalence)([3, 4])([1, 2]), [1, 2, 3, 4]) }) it("getSemigroup", () => { const S = RA.getSemigroup() expect(S.combine([1, 2], [2, 3])).toEqual([1, 2, 2, 3]) }) it("getUnionSemigroup", () => { const S = RA.getUnionSemigroup(Number.Equivalence) expect(S.combine([1, 2], [2, 3])).toEqual([1, 2, 3]) }) it("intersection", () => { const intersection = RA.intersection(Number.Equivalence) deepStrictEqual(pipe([1, 2], intersection([3, 4])), []) deepStrictEqual(pipe([1, 2], intersection([2, 3])), [2]) deepStrictEqual(pipe([1, 2], intersection([1, 2])), [1, 2]) }) it("difference", () => { const difference = RA.difference(Number.Equivalence) deepStrictEqual(pipe([1, 2], difference([3, 4])), [1, 2]) deepStrictEqual(pipe([1, 2], difference([2, 3])), [1]) deepStrictEqual(pipe([1, 2], difference([1, 2])), []) }) it("getUnionMonoid", () => { const M = RA.getUnionMonoid(Number.Equivalence) const two: ReadonlyArray = [1, 2] deepStrictEqual(M.combine(two, [3, 4]), [1, 2, 3, 4]) deepStrictEqual(M.combine(two, [2, 3]), [1, 2, 3]) deepStrictEqual(M.combine(two, [1, 2]), [1, 2]) deepStrictEqual(M.combine(M.empty, two), two) deepStrictEqual(M.combine(two, M.empty), two) deepStrictEqual(M.combine(M.empty, M.empty), M.empty) deepStrictEqual(M.combineAll([[1, 2], [3, 4, 5], [5, 6, 7, 1]]), [1, 2, 3, 4, 5, 6, 7]) }) it("getIntersectionSemigroup", () => { const S = RA.getIntersectionSemigroup(Number.Equivalence) deepStrictEqual(S.combine([3, 4], [1, 2]), []) deepStrictEqual(S.combine([2, 3], [1, 2]), [2]) deepStrictEqual(S.combine([1, 2], [1, 2]), [1, 2]) }) it("empty", () => { deepStrictEqual(RA.empty.length, 0) }) it("do notation", () => { deepStrictEqual( pipe( RA.Do, RA.bind("a", () => [1, 2, 3]), RA.map(({ a }) => a * 2) ), [2, 4, 6] ) deepStrictEqual( pipe( RA.Do, RA.bind("a", () => [1, 2, 3]), RA.bind("b", () => ["a", "b"]), RA.map(({ a, b }) => [a, b] as const) ), [ [1, "a"], [1, "b"], [2, "a"], [2, "b"], [3, "a"], [3, "b"] ] ) deepStrictEqual( pipe( RA.Do, RA.bind("a", () => [1, 2, 3]), RA.bind("b", () => ["a", "b"]), RA.map(({ a, b }) => [a, b] as const), RA.filter(([a, b]) => (a + b.length) % 2 === 0) ), [ [1, "a"], [1, "b"], [3, "a"], [3, "b"] ] ) }) it("every", () => { const isPositive: Predicate = (n) => n > 0 deepStrictEqual(pipe([1, 2, 3], RA.every(isPositive)), true) deepStrictEqual(pipe([1, 2, -3], RA.every(isPositive)), false) }) it("combineMapNonEmpty", () => { deepStrictEqual( pipe( RA.make("a", "b", "c"), RA.combineMapNonEmpty(String.Semigroup)(identity) ), "abc" ) deepStrictEqual( pipe( RA.make("a", "b"), RA.combineMapNonEmpty(String.Semigroup)((a, i) => i + a) ), "0a1b" ) }) it("some", () => { const isPositive: Predicate = (n) => n > 0 deepStrictEqual(pipe([-1, -2, 3], RA.some(isPositive)), true) deepStrictEqual(pipe([-1, -2, -3], RA.some(isPositive)), false) }) it("length", () => { deepStrictEqual(RA.length(RA.empty()), 0) deepStrictEqual(RA.length([]), 0) deepStrictEqual(RA.length(["a"]), 1) }) it("fromOption", () => { deepStrictEqual(RA.fromOption(O.some("hello")), ["hello"]) deepStrictEqual(RA.fromOption(O.none()), []) }) it("fromResult", () => { deepStrictEqual(RA.fromEither(E.right(1)), [1]) deepStrictEqual(RA.fromEither(E.left("a")), RA.empty()) }) test("product", () => { const product = RA.SemiProduct.product expect(product([], ["a", "b"])).toEqual([]) expect(product([1, 2], [])).toEqual([]) expect(product([1, 2], ["a", "b"])).toEqual([ [1, "a"], [1, "b"], [2, "a"], [2, "b"] ]) }) test("productAll", () => { const productAll = RA.Product.productAll expect(productAll([])).toEqual([]) expect(productAll([[1, 2, 3]])).toEqual([[1], [2], [3]]) expect(productAll([[1, 2, 3], [4, 5]])).toEqual([[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [ 3, 5 ]]) }) it("traversePartitionMap", () => { const traversePartitionMap = RA.traversePartitionMap(O.Applicative) const f = (s: string) => s.length > 1 ? O.some(E.right(s)) : s.length > 0 ? O.some(E.left(s)) : O.none() assert.deepStrictEqual(traversePartitionMap([], f), O.some([[], []])) assert.deepStrictEqual(traversePartitionMap([""], f), O.none()) assert.deepStrictEqual(traversePartitionMap(["a"], f), O.some([["a"], []])) assert.deepStrictEqual(traversePartitionMap(["aa"], f), O.some([[], ["aa"]])) assert.deepStrictEqual(traversePartitionMap(["aa", "a", ""], f), O.none()) assert.deepStrictEqual( traversePartitionMap(["aa", "a", "aaa"], f), O.some([["a"], ["aa", "aaa"]]) ) }) it("traverseFilterMap", () => { const traverseFilterMap = RA.traverseFilterMap(O.Applicative) const f = (s: string) => s.length > 1 ? O.some(O.some(s)) : s.length > 0 ? O.some(O.none()) : O.none() assert.deepStrictEqual(traverseFilterMap([], f), O.some([])) assert.deepStrictEqual(traverseFilterMap([""], f), O.none()) assert.deepStrictEqual(traverseFilterMap(["a"], f), O.some([])) assert.deepStrictEqual(traverseFilterMap(["aa"], f), O.some(["aa"])) assert.deepStrictEqual(traverseFilterMap(["aa", "a", ""], f), O.none()) assert.deepStrictEqual( traverseFilterMap(["aa", "a", "aaa"], f), O.some(["aa", "aaa"]) ) }) }) ================================================ FILE: test/ReadonlyRecord.ts ================================================ import * as E from "@fp-ts/core/Either" import { pipe } from "@fp-ts/core/Function" import * as O from "@fp-ts/core/Option" import * as RR from "@fp-ts/core/ReadonlyRecord" describe.concurrent("ReadonlyRecord", () => { it("exports", () => { expect(RR.Invariant).exist expect(RR.tupled).exist expect(RR.Covariant).exist expect(RR.flap).exist expect(RR.as).exist expect(RR.Filterable).exist expect(RR.Traversable).exist expect(RR.traverseTap).exist expect(RR.TraversableFilterable).exist expect(RR.traverseFilter).exist expect(RR.traversePartition).exist }) it("get", () => { expect(pipe({}, RR.get("a"))).toEqual(O.none()) expect(pipe({ a: 1 }, RR.get("a"))).toEqual(O.some(1)) }) it("modifyOption", () => { expect(pipe({}, RR.replaceOption("a", 2))).toEqual(O.none()) expect(pipe({ a: 1 }, RR.replaceOption("a", 2))).toEqual(O.some({ a: 2 })) expect(pipe({ a: 1 }, RR.replaceOption("a", true))).toEqual(O.some({ a: true })) }) it("modifyOption", () => { expect(pipe({}, RR.modifyOption("a", (n: number) => n + 1))).toEqual(O.none()) expect(pipe({ a: 1 }, RR.modifyOption("a", (n: number) => n + 1))).toEqual(O.some({ a: 2 })) expect(pipe({ a: 1 }, RR.modifyOption("a", (n: number) => String(n)))).toEqual( O.some({ a: "1" }) ) }) it("map", () => { expect(pipe({ a: 1, b: 2 }, RR.map(n => n * 2))).toEqual({ a: 2, b: 4 }) expect(pipe({ a: 1, b: 2 }, RR.map((n, k) => `${k}-${n}`))).toEqual({ a: "a-1", b: "b-2" }) }) it("fromIterable", () => { const input = [1, 2, 3, 4] expect(RR.fromIterable(input, a => [String(a), a * 2])).toEqual({ "1": 2, "2": 4, "3": 6, "4": 8 }) }) it("collect", () => { const x = { a: 1, b: 2, c: 3 } assert.deepStrictEqual(RR.collect(x, (key, n) => [key, n]), [["a", 1], ["b", 2], ["c", 3]]) }) it("toArray", () => { const x = { a: 1, b: 2 } assert.deepStrictEqual(RR.toArray(x), [["a", 1], ["b", 2]]) }) it("remove", () => { assert.deepStrictEqual(RR.remove({ a: 1, b: 2 }, "a"), { b: 2 }) assert.deepStrictEqual(RR.remove({ a: 1, b: 2 }, "c"), { a: 1, b: 2 }) }) describe("pop", () => { it("should return the value associated with the given key, if the key is present in the record", () => { const record = { a: 1, b: 2 } const result = RR.pop("a")(record) assert.deepStrictEqual(result, O.some([1, { b: 2 }])) }) it("should return none if the key is not present in the record", () => { const record = { a: 1, b: 2 } const result = RR.pop("c")(record) assert.deepStrictEqual(result, O.none()) }) }) describe("filterMap", () => { it("should filter the properties of an object", () => { const obj = { a: 1, b: 2, c: 3 } const filtered = RR.filterMap(obj, (value, key) => (value > 2 ? O.some(key) : O.none())) expect(filtered).toEqual({ c: "c" }) }) }) it("compact", () => { const x = { a: O.some(1), b: O.none(), c: O.some(2) } assert.deepStrictEqual(RR.compact(x), { a: 1, c: 2 }) }) it("filter", () => { const x = { a: 1, b: 2, c: 3, d: 4 } assert.deepStrictEqual(RR.filter(x, (value) => value > 2), { c: 3, d: 4 }) }) it("partitionMap", () => { const f = (n: number) => (n > 2 ? E.right(n + 1) : E.left(n - 1)) assert.deepStrictEqual(RR.partitionMap({}, f), [{}, {}]) assert.deepStrictEqual(RR.partitionMap({ a: 1, b: 3 }, f), [{ a: 0 }, { b: 4 }]) }) it("partition", () => { const f = (n: number) => n > 2 assert.deepStrictEqual(RR.partition({}, f), [{}, {}]) assert.deepStrictEqual(RR.partition({ a: 1, b: 3 }, f), [{ a: 1 }, { b: 3 }]) }) it("separate", () => { assert.deepStrictEqual( RR.separate({ a: E.left("e"), b: E.right(1) }), [{ a: "e" }, { b: 1 }] ) // should ignore non own properties const o: RR.ReadonlyRecord> = Object.create({ a: 1 }) assert.deepStrictEqual(pipe(o, RR.separate), [{}, {}]) }) it("traverse", () => { assert.deepStrictEqual( RR.traverse(O.Applicative)({ a: 1, b: 2 }, (n: number) => (n <= 2 ? O.some(n) : O.none())), O.some({ a: 1, b: 2 }) ) assert.deepStrictEqual( RR.traverse(O.Applicative)((n: number) => (n <= 2 ? O.some(n) : O.none()))({ a: 1, b: 2 }), O.some({ a: 1, b: 2 }) ) assert.deepStrictEqual( RR.traverse(O.Applicative)({ a: 1, b: 2 }, (n: number) => (n >= 2 ? O.some(n) : O.none())), O.none() ) assert.deepStrictEqual( RR.traverse(O.Applicative)((n: number) => (n >= 2 ? O.some(n) : O.none()))({ a: 1, b: 2 }), O.none() ) }) it("sequence", () => { const sequence = RR.sequence(O.Applicative) assert.deepStrictEqual(sequence({ a: O.some(1), b: O.some(2) }), O.some({ a: 1, b: 2 })) assert.deepStrictEqual(sequence({ a: O.none(), b: O.some(2) }), O.none()) }) it("empty", () => { expect(RR.empty()).toEqual({}) }) it("isEmpty", () => { assert.deepStrictEqual(RR.isEmpty({}), true) assert.deepStrictEqual(RR.isEmpty({ a: 3 }), false) }) it("size", () => { assert.deepStrictEqual(RR.size({ a: "a", b: 1, c: true }), 3) }) it("has", () => { assert.deepStrictEqual(RR.has({ a: 1, b: 2 }, "a"), true) assert.deepStrictEqual(RR.has({ a: 1, b: 2 }, "c"), false) }) it("traversePartitionMap", () => { const traversePartitionMap = RR.traversePartitionMap(O.Applicative) const f = (s: string) => s.length > 1 ? O.some(E.right(s)) : s.length > 0 ? O.some(E.left(s)) : O.none() assert.deepStrictEqual(traversePartitionMap({}, f), O.some([{}, {}])) assert.deepStrictEqual(traversePartitionMap({ "": "" }, f), O.none()) assert.deepStrictEqual(traversePartitionMap({ a: "a" }, f), O.some([{ a: "a" }, {}])) assert.deepStrictEqual(traversePartitionMap({ aa: "aa" }, f), O.some([{}, { aa: "aa" }])) assert.deepStrictEqual(traversePartitionMap({ aa: "aa", a: "a", "": "" }, f), O.none()) assert.deepStrictEqual( traversePartitionMap({ aa: "aa", a: "a", aaa: "aaa" }, f), O.some([{ a: "a" }, { aa: "aa", aaa: "aaa" }]) ) }) it("traverseFilterMap", () => { const traverseFilterMap = RR.traverseFilterMap(O.Applicative) const f = (s: string) => s.length > 1 ? O.some(O.some(s)) : s.length > 0 ? O.some(O.none()) : O.none() assert.deepStrictEqual(traverseFilterMap({}, f), O.some({})) assert.deepStrictEqual(traverseFilterMap({ "": "" }, f), O.none()) assert.deepStrictEqual(traverseFilterMap({ a: "a" }, f), O.some({})) assert.deepStrictEqual(traverseFilterMap({ aa: "aa" }, f), O.some({ aa: "aa" })) assert.deepStrictEqual(traverseFilterMap({ aa: "aa", a: "a", "": "" }, f), O.none()) assert.deepStrictEqual( traverseFilterMap({ aa: "aa", a: "a", aaa: "aaa" }, f), O.some({ aa: "aa", aaa: "aaa" }) ) }) }) ================================================ FILE: test/String.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as S from "@fp-ts/core/String" import { deepStrictEqual } from "@fp-ts/core/test/util" import * as Order from "@fp-ts/core/typeclass/Order" describe.concurrent("String", () => { it("isString", () => { expect(S.isString("a")).toEqual(true) expect(S.isString(1)).toEqual(false) expect(S.isString(true)).toEqual(false) }) it("empty", () => { expect(S.empty).toEqual("") }) it("Semigroup", () => { expect(S.Semigroup.combine("a", "b")).toEqual("ab") expect(S.Semigroup.combineMany("a", ["b", "c"])).toEqual("abc") expect(S.Semigroup.combineMany("a", [])).toEqual("a") }) it("Monoid", () => { expect(S.Monoid.combineAll([])).toEqual("") }) it("Equivalence", () => { expect(S.Equivalence("a", "a")).toBe(true) expect(S.Equivalence("a", "b")).toBe(false) }) it("Order", () => { const lessThan = Order.lessThan(S.Order) const lessThanOrEqualTo = Order.lessThanOrEqualTo(S.Order) expect(pipe("a", lessThan("b"))).toEqual(true) expect(pipe("a", lessThan("a"))).toEqual(false) expect(pipe("a", lessThanOrEqualTo("a"))).toEqual(true) expect(pipe("b", lessThan("a"))).toEqual(false) expect(pipe("b", lessThanOrEqualTo("a"))).toEqual(false) }) it("concat", () => { deepStrictEqual(pipe("a", S.concat("b")), "ab") }) it("isEmpty", () => { deepStrictEqual(S.isEmpty(""), true) deepStrictEqual(S.isEmpty("a"), false) }) it("isNonEmpty", () => { deepStrictEqual(S.isNonEmpty(""), false) deepStrictEqual(S.isNonEmpty("a"), true) }) it("length", () => { deepStrictEqual(S.length(""), 0) deepStrictEqual(S.length("a"), 1) deepStrictEqual(S.length("aaa"), 3) }) it("toUpperCase", () => { deepStrictEqual(S.toUpperCase("a"), "A") }) it("toLowerCase", () => { deepStrictEqual(S.toLowerCase("A"), "a") }) it("replace", () => { deepStrictEqual(pipe("abc", S.replace("b", "d")), "adc") }) it("split", () => { deepStrictEqual(pipe("abc", S.split("")), ["a", "b", "c"]) deepStrictEqual(pipe("", S.split("")), [""]) }) it("trim", () => { deepStrictEqual(pipe(" a ", S.trim), "a") }) it("trimStart", () => { deepStrictEqual(pipe(" a ", S.trimStart), "a ") }) it("trimEnd", () => { deepStrictEqual(pipe(" a ", S.trimEnd), " a") }) it("includes", () => { assert.deepStrictEqual(S.includes("abc", "b"), true) assert.deepStrictEqual(S.includes("abc", "d"), false) }) it("includesWithPosition", () => { assert.deepStrictEqual(S.includesWithPosition("abc", "b", 1), true) assert.deepStrictEqual(S.includesWithPosition("abc", "a", 1), false) }) it("startsWith", () => { assert.deepStrictEqual(S.startsWith("abc", "a"), true) assert.deepStrictEqual(S.startsWith("bc", "a"), false) }) it("startsWithPosition", () => { assert.deepStrictEqual(S.startsWithPosition("abc", "b", 1), true) assert.deepStrictEqual(S.startsWithPosition("bc", "a", 1), false) }) it("endsWith", () => { assert.deepStrictEqual(S.endsWith("abc", "c"), true) assert.deepStrictEqual(S.endsWith("ab", "c"), false) }) it("endsWithPosition", () => { assert.deepStrictEqual(S.endsWithPosition("abc", "b", 2), true) assert.deepStrictEqual(S.endsWithPosition("abc", "c", 2), false) }) it("slice", () => { deepStrictEqual(pipe("abcd", S.slice(1, 3)), "bc") }) describe.concurrent("takeLeft", () => { it("should take the specified number of characters from the left side of a string", () => { const string = "Hello, World!" const result = pipe(string, S.takeLeft(7)) assert.strictEqual(result, "Hello, ") }) it("should return the string for `n` larger than the string length", () => { const string = "Hello, World!" const result = pipe(string, S.takeLeft(100)) assert.strictEqual(result, string) }) it("should return the empty string for a negative `n`", () => { const string = "Hello, World!" const result = pipe(string, S.takeLeft(-1)) assert.strictEqual(result, "") }) it("should round down if `n` is a float", () => { const string = "Hello, World!" const result = pipe(string, S.takeLeft(5.5)) assert.strictEqual(result, "Hello") }) }) describe.concurrent("takeRight", () => { it("should take the specified number of characters from the right side of a string", () => { const string = "Hello, World!" const result = pipe(string, S.takeRight(7)) assert.strictEqual(result, " World!") }) it("should return the string for `n` larger than the string length", () => { const string = "Hello, World!" const result = pipe(string, S.takeRight(100)) assert.strictEqual(result, string) }) it("should return the empty string for a negative `n`", () => { const string = "Hello, World!" const result = pipe(string, S.takeRight(-1)) assert.strictEqual(result, "") }) it("should round down if `n` is a float", () => { const string = "Hello, World!" const result = pipe(string, S.takeRight(6.5)) assert.strictEqual(result, "World!") }) }) // TODO: 100% coverage tests (ask Max) // describe.concurrent("stripMargin", () => { // it("should strip a leading prefix from each line", () => { // const string = `| // |Hello, // |World! // |` // const result = pipe(string, String.stripMargin) // assert.strictEqual(result, "\nHello,\nWorld!\n") // }) // it("should strip a leading prefix from each line using a margin character", () => { // const string = `$ // $Hello, // $World! // $` // const result = pipe(string, String.stripMarginWith("$")) // assert.strictEqual(result, "\nHello,\nWorld!\n") // }) // }) }) ================================================ FILE: test/Struct.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as S from "@fp-ts/core/Struct" describe.concurrent("Struct", () => { it("exports", () => { expect(S.getEquivalence).exists expect(S.getOrder).exists expect(S.getSemigroup).exists expect(S.getMonoid).exists }) it("pick", () => { expect(pipe({ a: "a", b: 1, c: true }, S.pick("a", "b"))).toEqual({ a: "a", b: 1 }) }) it("omit", () => { expect(pipe({ a: "a", b: 1, c: true }, S.omit("c"))).toEqual({ a: "a", b: 1 }) }) }) ================================================ FILE: test/Symbol.ts ================================================ import * as S from "@fp-ts/core/Symbol" describe.concurrent("Symbol", () => { it("isSymbol", () => { expect(S.isSymbol(Symbol.for("@fp-ts/core/test/a"))).toEqual(true) expect(S.isSymbol(1n)).toEqual(false) expect(S.isSymbol(1)).toEqual(false) expect(S.isSymbol("a")).toEqual(false) expect(S.isSymbol(true)).toEqual(false) }) it("Equivalence", () => { const eq = S.Equivalence expect(eq(Symbol.for("@fp-ts/core/test/a"), Symbol.for("@fp-ts/core/test/a"))).toBe(true) expect(eq(Symbol.for("@fp-ts/core/test/a"), Symbol.for("@fp-ts/core/test/b"))).toBe(false) }) }) ================================================ FILE: test/These.ts ================================================ import * as E from "@fp-ts/core/Either" import { identity, pipe } from "@fp-ts/core/Function" import { structural } from "@fp-ts/core/internal/effect" import * as N from "@fp-ts/core/Number" import * as O from "@fp-ts/core/Option" import * as S from "@fp-ts/core/String" import * as _ from "@fp-ts/core/These" import { number } from "@fp-ts/core/typeclass/Equivalence" import * as Util from "./util" describe("These", () => { it("instances and derived exports", () => { expect(_.Invariant).exist expect(_.tupled).exist expect(_.bindTo).exist expect(_.Bicovariant).exist expect(_.mapLeft).exist expect(_.Covariant).exist expect(_.map).exist expect(_.let).exist expect(_.flap).exist expect(_.as).exist expect(_.asUnit).exist expect(_.Of).exist expect(_.of).exist expect(_.unit).exist expect(_.Do).exist expect(_.Pointed).exist expect(_.FlatMap).exist expect(_.flatMap).exist expect(_.flatten).exist expect(_.andThen).exist expect(_.composeKleisliArrow).exist expect(_.Chainable).exist expect(_.bind).exist expect(_.tap).exist expect(_.andThenDiscard).exist expect(_.Monad).exist expect(_.SemiProduct).exist expect(_.andThenBind).exist expect(_.appendElement).exist expect(_.Product).exist expect(_.tuple).exist expect(_.struct).exist expect(_.SemiApplicative).exist expect(_.getFirstLeftSemigroup).exist // liftSemigroup expect(_.lift2).exist expect(_.ap).exist expect(_.andThenDiscard).exist expect(_.andThen).exist expect(_.Applicative).exist expect(_.getFirstLeftMonoid).exist // liftMonoid expect(_.SemiCoproduct).exist // expect(_.coproduct).exist expect(_.firstRightOrBothOf).exist // coproductMany expect(_.getFirstRightOrBothSemigroup).exist // getSemigroup // expect(_.coproductEither).exist // orElseEither expect(_.SemiAlternative).exist expect(_.Foldable).exist expect(_.Traversable).exist expect(_.traverse).exist expect(_.sequence).exist expect(_.traverseTap).exist }) it("structural tracking", () => { expect(Util.ownKeys(_.left("a"))).toEqual(["_tag", "left"]) expect(Util.ownKeys(_.right(1))).toEqual(["_tag", "right"]) expect(Util.ownKeys(_.both("a", 1))).toEqual(["_tag", "left", "right"]) expect(Object.prototype.hasOwnProperty.call(_.left("a"), structural)).toEqual(false) expect(Object.prototype.hasOwnProperty.call(_.right(1), structural)).toEqual(false) expect(Object.prototype.hasOwnProperty.call(_.both("a", 1), structural)).toEqual(false) expect(Util.isStructural(_.left("a"))).toEqual(true) expect(Util.isStructural(_.right(1))).toEqual(true) expect(Util.isStructural(_.both("a", 1))).toEqual(true) }) it("reduce", () => { Util.deepStrictEqual(pipe(_.right("a"), _.Foldable.reduce("-", (b, a) => b + a)), "-a") Util.deepStrictEqual(pipe(_.left("e"), _.Foldable.reduce("-", (b, a) => b + a)), "-") Util.deepStrictEqual(pipe(_.both("e", "a"), _.Foldable.reduce("-", (b, a) => b + a)), "-a") }) it("map", () => { Util.deepStrictEqual(pipe(_.left("e"), _.map(Util.double)), _.left("e")) Util.deepStrictEqual(pipe(_.right(2), _.map(Util.double)), _.right(4)) Util.deepStrictEqual(pipe(_.both("e", 2), _.map(Util.double)), _.both("e", 4)) }) it("bimap", () => { const f = _.bimap(S.length, Util.double) Util.deepStrictEqual(pipe(_.left("e"), f), _.left(1)) Util.deepStrictEqual(pipe(_.right(2), f), _.right(4)) Util.deepStrictEqual(pipe(_.both("eee", 1), f), _.both(3, 2)) }) it("mapLeft", () => { const f = _.mapLeft(S.length) Util.deepStrictEqual(pipe(_.left("e"), f), _.left(1)) Util.deepStrictEqual(pipe(_.right(2), f), _.right(2)) Util.deepStrictEqual(pipe(_.both("eee", 1), f), _.both(3, 1)) }) it("traverse", () => { const traverse = _.traverse(O.Applicative)((n: number) => (n > 1 ? O.some(n) : O.none())) Util.deepStrictEqual(pipe(_.left("a"), traverse), O.some(_.left("a"))) Util.deepStrictEqual(pipe(_.right(2), traverse), O.some(_.right(2))) Util.deepStrictEqual(pipe(_.right(1), traverse), O.none()) Util.deepStrictEqual(pipe(_.both("a", 2), traverse), O.some(_.both("a", 2))) Util.deepStrictEqual( pipe( _.both("a", 1), _.traverse(O.Applicative)((n) => (n >= 2 ? O.some(n) : O.none())) ), O.none() ) }) it("andThenBind", () => { Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.right(1)), _.bindEither("b", () => E.right(2))), _.right({ a: 1, b: 2 }) ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.right(1)), _.bindEither("b", () => E.left("e2"))), _.fail("e2") ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.fail("e1")), _.bindEither("b", () => E.right(2))), _.fail("e1") ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.fail("e1")), _.bindEither("b", () => E.left("e2"))), _.fail("e1") ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.warn("e1", 1)), _.bindEither("b", () => E.right(2))), _.warn("e1", { a: 1, b: 2 }) ) expect( pipe(_.Do, _.bind("a", () => _.warn("e1", 1)), _.bindEither("b", () => E.left("e2"))) ).toEqual( _.left(["e1", "e2"]) ) }) it("andThenBind", () => { Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.right(1)), _.bindThese("b", () => _.right(2))), _.right({ a: 1, b: 2 }) ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.right(1)), _.bindThese("b", () => _.left("e2"))), _.fail("e2") ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.right(1)), _.bindThese("b", () => _.both("e2", 2))), _.warn("e2", { a: 1, b: 2 }) ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.fail("e1")), _.bindThese("b", () => _.right(2))), _.fail("e1") ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.fail("e1")), _.bindThese("b", () => _.left("e2"))), _.fail("e1") ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.fail("e1")), _.bindThese("b", () => _.both("e2", 2))), _.fail("e1") ) Util.deepStrictEqual( pipe(_.Do, _.bind("a", () => _.warn("e1", 1)), _.bindThese("b", () => _.right(2))), _.warn("e1", { a: 1, b: 2 }) ) expect( pipe(_.Do, _.bind("a", () => _.warn("e1", 1)), _.bindThese("b", () => _.left("e2"))) ).toEqual( _.left(["e1", "e2"]) ) expect( pipe(_.Do, _.bind("a", () => _.warn("e1", 1)), _.bindThese("b", () => _.both("e2", 2))) ).toEqual( _.both(["e1", "e2"], { a: 1, b: 2 }) ) }) it("sequence", () => { const sequence = _.sequence(O.Applicative) Util.deepStrictEqual(sequence(_.left("a")), O.some(_.left("a"))) Util.deepStrictEqual(sequence(_.right(O.some(1))), O.some(_.right(1))) Util.deepStrictEqual(sequence(_.right(O.none())), O.none()) Util.deepStrictEqual(sequence(_.both("a", O.some(1))), O.some(_.both("a", 1))) Util.deepStrictEqual(sequence(_.both("a", O.none())), O.none()) }) it("product", () => { const a = ["a"] as const const b = ["b"] as const const ab = ["a", "b"] as const const product = _.SemiProduct.product expect(product(_.right(1), _.right(2))).toEqual(_.right([1, 2])) Util.deepStrictEqual(product(_.right(1), _.left(b)), _.left(b)) expect(product(_.right(1), _.both(b, 2))).toEqual(_.both(b, [1, 2])) Util.deepStrictEqual(product(_.left(a), _.right(2)), _.left(a)) Util.deepStrictEqual(product(_.left(a), _.left(b)), _.left(a)) Util.deepStrictEqual(product(_.left(a), _.both(b, 2)), _.left(a)) expect(product(_.both(a, 1), _.right(2))).toEqual(_.both(a, [1, 2])) expect(product(_.both(a, 1), _.left(b))).toEqual(_.left(ab)) expect(product(_.both(a, 1), _.both(b, 2))).toEqual(_.both(ab, [1, 2])) }) it("productMany", () => { const a = ["a"] as const const b = ["b"] as const const ab = ["a", "b"] as const const productMany: ( self: _.Validated, collection: Iterable<_.Validated> ) => _.Validated]> = _.SemiProduct.productMany expect(productMany(_.right(1), [_.right(2)])).toEqual(_.right([1, 2])) Util.deepStrictEqual( productMany(_.right(1), [_.left(b)]), _.left(b) ) expect( productMany(_.right(1), [_.both(b, 2)]) ).toEqual( _.both(b, [1, 2]) ) Util.deepStrictEqual(productMany(_.left(a), [_.right(2)]), _.left(a)) Util.deepStrictEqual(productMany(_.left(a), [_.left(b)]), _.left(a)) Util.deepStrictEqual( productMany(_.left(a), [_.both(b, 2)]), _.left(a) ) expect(productMany(_.both(a, 1), [_.right(2)])).toEqual(_.both(a, [1, 2])) expect(productMany(_.both(a, 1), [_.left(b)])).toEqual(_.left(ab)) expect(productMany(_.both(a, 1), [_.both(b, 2)])).toEqual( _.both(ab, [1, 2]) ) }) it("productAll", () => { const a = ["a"] as const const b = ["b"] as const const ab = ["a", "b"] as const const productAll = _.Product.productAll Util.deepStrictEqual(productAll([_.right(1), _.right(2)]), _.right([1, 2])) Util.deepStrictEqual(productAll([_.right(1), _.left(b)]), _.left(b)) Util.deepStrictEqual(productAll([_.right(1), _.both(b, 2)]), _.both(b, [1, 2])) Util.deepStrictEqual(productAll([_.left(a), _.right(2)]), _.left(a)) Util.deepStrictEqual(productAll([_.left(a), _.left(b)]), _.left(a)) Util.deepStrictEqual(productAll([_.left(a), _.both(b, 2)]), _.left(a)) Util.deepStrictEqual(productAll([_.both(a, 1), _.right(2)]), _.both(a, [1, 2])) expect(productAll([_.both(a, 1), _.left(b)])).toEqual(_.left(ab)) expect(productAll([_.both(a, 1), _.both(b, 2)])).toEqual(_.both(ab, [1, 2])) }) it("flatMap", () => { const f = ( n: number ) => (n >= 2 ? (n <= 5 ? _.right(n * 2) : _.warn("e2", n)) : _.fail("e3")) Util.deepStrictEqual( pipe(_.fail("e1"), _.flatMap(f)), _.fail("e1") ) Util.deepStrictEqual(pipe(_.right(2), _.flatMap(f)), _.right(4)) Util.deepStrictEqual(pipe(_.right(1), _.flatMap(f)), _.fail("e3")) Util.deepStrictEqual(pipe(_.right(6), _.flatMap(f)), _.warn("e2", 6)) Util.deepStrictEqual( pipe(_.warn("e1", 2), _.flatMap(f)), _.warn("e1", 4) ) expect(pipe(_.warn("e1", 1), _.flatMap(f))).toEqual(_.left(["e1", "e3"])) expect(pipe(_.warn("e1", 6), _.flatMap(f))).toEqual(_.both(["e1", "e2"], 6)) }) it("flatMapNullable", () => { const f = _.flatMapNullable((n: number) => (n > 0 ? n : null), () => "e2") Util.deepStrictEqual(f(_.right(1)), _.right(1)) Util.deepStrictEqual(f(_.right(-1)), _.fail("e2")) Util.deepStrictEqual(f(_.fail("e1")), _.fail("e1")) Util.deepStrictEqual(f(_.warn("e1", 1)), _.warn("e1", 1)) expect(f(_.warn("e1", -1))).toEqual(_.left(["e1", "e2"])) }) it("flatMapOption", () => { const f = _.flatMapOption((n: number) => (n > 0 ? O.some(n) : O.none()), () => "e2") Util.deepStrictEqual(f(_.right(1)), _.right(1)) Util.deepStrictEqual(f(_.right(-1)), _.fail("e2")) Util.deepStrictEqual(f(_.fail("e1")), _.fail("e1")) Util.deepStrictEqual(f(_.warn("e1", 1)), _.warn("e1", 1)) expect(f(_.warn("e1", -1))).toEqual(_.left(["e1", "e2"])) }) it("flatMapEither", () => { const f = _.flatMapEither((n: number) => (n > 0 ? E.right(n) : E.left("e2"))) Util.deepStrictEqual(f(_.right(1)), _.right(1)) Util.deepStrictEqual(f(_.right(-1)), _.fail("e2")) Util.deepStrictEqual(f(_.fail("e1")), _.fail("e1")) Util.deepStrictEqual(f(_.warn("e1", 1)), _.warn("e1", 1)) expect(f(_.warn("e1", -1))).toEqual(_.left(["e1", "e2"])) }) it("flatMapThese", () => { const f = _.flatMapThese(( n: number ) => (n > 10 ? _.both("e3", n) : n > 0 ? _.right(n) : _.left("e2"))) Util.deepStrictEqual(f(_.right(1)), _.right(1)) Util.deepStrictEqual(f(_.right(-1)), _.fail("e2")) Util.deepStrictEqual(f(_.right(11)), _.warn("e3", 11)) Util.deepStrictEqual(f(_.fail("e1")), _.fail("e1")) Util.deepStrictEqual(f(_.warn("e1", 1)), _.warn("e1", 1)) expect(f(_.warn("e1", -1))).toEqual(_.left(["e1", "e2"])) expect(f(_.warn("e1", 11))).toEqual(_.both(["e1", "e3"], 11)) }) it("leftOrBoth", () => { Util.deepStrictEqual(_.leftOrBoth(() => "a")(O.none()), _.left("a")) Util.deepStrictEqual(_.leftOrBoth(() => "a")(O.some(1)), _.both("a", 1)) }) it("rightOrBoth", () => { Util.deepStrictEqual(_.rightOrBoth(() => 1)(O.none()), _.right(1)) Util.deepStrictEqual(_.rightOrBoth(() => 1)(O.some("a")), _.both("a", 1)) }) it("match", () => { const f = (s: string, n: number) => S.length(s) + Util.double(n) const match = _.match(S.length, Util.double, f) Util.deepStrictEqual(match(_.left("foo")), 3) Util.deepStrictEqual(match(_.right(1)), 2) Util.deepStrictEqual(match(_.both("foo", 1)), 5) }) it("getBothOrElse", () => { const f = _.getBothOrElse(() => "a", () => 1) Util.deepStrictEqual(pipe(_.left("b"), f), ["b", 1]) Util.deepStrictEqual(pipe(_.right(2), f), ["a", 2]) Util.deepStrictEqual(pipe(_.both("b", 2), f), ["b", 2]) }) it("getBoth", () => { Util.deepStrictEqual(pipe(_.left("e"), _.getBoth), O.none()) Util.deepStrictEqual(pipe(_.right(1), _.getBoth), O.none()) expect(pipe(_.both("e", 1), _.getBoth)).toEqual(O.some(["e", 1])) }) it("getLeft", () => { Util.deepStrictEqual(_.getLeft(_.left("e")), O.some("e")) Util.deepStrictEqual(_.getLeft(_.right(1)), O.none()) Util.deepStrictEqual(_.getLeft(_.both("e", 1)), O.some("e")) }) it("getRight", () => { Util.deepStrictEqual(_.getRight(_.left("e")), O.none()) Util.deepStrictEqual(_.getRight(_.right(1)), O.some(1)) Util.deepStrictEqual(_.getRight(_.both("e", 1)), O.some(1)) }) it("getLeftOnly", () => { Util.deepStrictEqual(_.getLeftOnly(_.left("e")), O.some("e")) Util.deepStrictEqual(_.getLeftOnly(_.right(1)), O.none()) Util.deepStrictEqual(_.getLeftOnly(_.both("e", 1)), O.none()) }) it("getRightOnly", () => { Util.deepStrictEqual(_.getRightOnly(_.left("e")), O.none()) Util.deepStrictEqual(_.getRightOnly(_.right(1)), O.some(1)) Util.deepStrictEqual(_.getRightOnly(_.both("e", 1)), O.none()) }) it("isLeft", () => { Util.deepStrictEqual(_.isLeft(_.left("e")), true) Util.deepStrictEqual(_.isLeft(_.right(1)), false) Util.deepStrictEqual(_.isLeft(_.both("e", 1)), false) }) it("isLeftOrBoth", () => { Util.deepStrictEqual(_.isLeftOrBoth(_.left("e")), true) Util.deepStrictEqual(_.isLeftOrBoth(_.right(1)), false) Util.deepStrictEqual(_.isLeftOrBoth(_.both("e", 1)), true) }) it("isRight", () => { Util.deepStrictEqual(_.isRight(_.left("e")), false) Util.deepStrictEqual(_.isRight(_.right(1)), true) Util.deepStrictEqual(_.isRight(_.both("", 1)), false) }) it("isRightOrBoth", () => { Util.deepStrictEqual(_.isRightOrBoth(_.left("e")), false) Util.deepStrictEqual(_.isRightOrBoth(_.right(1)), true) Util.deepStrictEqual(_.isRightOrBoth(_.both("e", 1)), true) }) it("isThese", () => { Util.deepStrictEqual(_.isThese(_.left("e")), true) Util.deepStrictEqual(_.isThese(_.right(1)), true) Util.deepStrictEqual(_.isThese(_.both("e", 1)), true) Util.deepStrictEqual(_.isThese(E.left("e")), true) Util.deepStrictEqual(_.isThese(E.right(1)), true) Util.deepStrictEqual(_.isThese(O.some(1)), false) }) it("isBoth", () => { Util.deepStrictEqual(_.isBoth(_.left("e")), false) Util.deepStrictEqual(_.isBoth(_.right(1)), false) Util.deepStrictEqual(_.isBoth(_.both("e", 1)), true) }) it("liftThrowable", () => { const f = _.liftThrowable((s: string) => { const len = s.length if (len > 0) { return len } throw new Error("empty string") }, identity) Util.deepStrictEqual(f("a"), _.right(1)) Util.deepStrictEqual(f(""), _.left(new Error("empty string"))) }) it("inspectRight", () => { const log: Array = [] pipe(_.right(1), _.inspectRight((a) => log.push(a))) pipe(_.left("e1"), _.inspectRight((a) => log.push(a))) pipe(_.both("e2", 1), _.inspectRight((a) => log.push(a))) Util.deepStrictEqual(log, [1]) }) it("inspectRightOrBoth", () => { const log: Array = [] pipe(_.right(1), _.inspectRightOrBoth((a) => log.push(a))) pipe(_.left("e1"), _.inspectRightOrBoth((a) => log.push(a))) pipe(_.both("e2", 2), _.inspectRightOrBoth((a) => log.push(a))) Util.deepStrictEqual(log, [1, 2]) }) it("inspectBoth", () => { const log: Array = [] pipe(_.right(1), _.inspectBoth((e, a) => log.push(e, a))) pipe(_.left("e1"), _.inspectBoth((e, a) => log.push(e, a))) pipe(_.both("e2", 2), _.inspectBoth((e, a) => log.push(e, a))) Util.deepStrictEqual(log, ["e2", 2]) }) it("inspectLeft", () => { const log: Array = [] pipe(_.right(1), _.inspectLeft((e) => log.push(e))) pipe(_.left("e1"), _.inspectLeft((e) => log.push(e))) pipe(_.both("e2", 1), _.inspectLeft((e) => log.push(e))) Util.deepStrictEqual(log, ["e1"]) }) it("getOrThrow", () => { expect(pipe(_.right(1), _.getOrThrow)).toEqual(1) expect(pipe(_.both("e", 1), _.getOrThrow)).toEqual(1) expect(() => pipe(_.left("e"), _.getOrThrow)).toThrowError( new Error("getOrThrow called on a Left") ) }) it("getOrThrowWith", () => { expect(pipe(_.right(1), _.getOrThrowWith((e) => new Error(`Unexpected Left: ${e}`)))).toEqual(1) expect(pipe(_.both("w", 1), _.getOrThrowWith((e) => new Error(`Unexpected Left: ${e}`)))) .toEqual(1) expect(() => pipe(_.left("e"), _.getOrThrowWith((e) => new Error(`Unexpected Left: ${e}`)))) .toThrowError( new Error("Unexpected Left: e") ) }) it("getRightOnlyOrThrow", () => { expect(pipe(_.right(1), _.getRightOnlyOrThrow)).toEqual(1) expect(() => pipe(_.left("e"), _.getRightOnlyOrThrow)).toThrow( new Error("getRightOnlyOrThrow called on a Left or a Both") ) expect(() => pipe(_.both("e", 1), _.getRightOnlyOrThrow)).toThrow( new Error("getRightOnlyOrThrow called on a Left or a Both") ) }) it("getRightOnlyOrThrowWith", () => { expect( pipe(_.right(1), _.getRightOnlyOrThrowWith((e) => new Error(`Unexpected Left or Both: ${e}`))) ).toEqual(1) expect(() => pipe( _.left("e"), _.getRightOnlyOrThrowWith((e) => new Error(`Unexpected Left or Both: ${e}`)) ) ).toThrow( new Error("Unexpected Left or Both: e") ) expect(() => pipe( _.both("e", 1), _.getRightOnlyOrThrowWith((e) => new Error(`Unexpected Left or Both: ${e}`)) ) ).toThrow( new Error("Unexpected Left or Both: e") ) }) it("getOrElse", () => { Util.deepStrictEqual(pipe(_.right(1), _.getOrElse(() => 2)), 1) Util.deepStrictEqual(pipe(_.left("e"), _.getOrElse(() => 2)), 2) Util.deepStrictEqual(pipe(_.both("e", 1), _.getOrElse(() => 2)), 1) }) it("getOrNull", () => { Util.deepStrictEqual(pipe(_.right(1), _.getOrNull), 1) Util.deepStrictEqual(pipe(_.left("e"), _.getOrNull), null) Util.deepStrictEqual(pipe(_.both("e", 1), _.getOrNull), 1) }) it("getOrUndefined", () => { Util.deepStrictEqual(pipe(_.right(1), _.getOrUndefined), 1) Util.deepStrictEqual(pipe(_.left("e"), _.getOrUndefined), undefined) Util.deepStrictEqual(pipe(_.both("e", 1), _.getOrUndefined), 1) }) it("fromNullable", () => { Util.deepStrictEqual(_.fromNullable(() => "default")(null), _.left("default")) Util.deepStrictEqual(_.fromNullable(() => "default")(undefined), _.left("default")) Util.deepStrictEqual(_.fromNullable(() => "default")(1), _.right(1)) }) it("liftNullable", () => { const f = _.liftNullable((n: number) => (n > 0 ? n : null), () => "error") Util.deepStrictEqual(f(1), _.right(1)) Util.deepStrictEqual(f(-1), _.left("error")) }) it("liftPredicate", () => { const f = _.liftPredicate((n: number) => n >= 2, () => "e") Util.deepStrictEqual(f(3), _.right(3)) Util.deepStrictEqual(f(1), _.left("e")) }) it("fromIterable", () => { Util.deepStrictEqual(_.fromIterable(() => "e")([]), _.left("e")) Util.deepStrictEqual(_.fromIterable(() => "e")(["a"]), _.right("a")) }) it("fromOption", () => { Util.deepStrictEqual(_.fromOption(() => "e")(O.none()), _.left("e")) Util.deepStrictEqual(_.fromOption(() => "e")(O.some(1)), _.right(1)) }) it("fromEither", () => { Util.deepStrictEqual(_.fromEither(E.right(1)), _.right(1)) expect(_.fromEither(E.left("e"))).toEqual(_.left(["e"])) }) it("toValidated", () => { Util.deepStrictEqual(_.toValidated(_.right(1)), _.right(1)) Util.deepStrictEqual(_.toValidated(_.left("e")), _.fail("e")) Util.deepStrictEqual(_.toValidated(_.both("e", 1)), _.warn("e", 1)) }) it("toEither", () => { expect(_.toEither).exist }) it("absolve", () => { Util.deepStrictEqual(_.absolve(_.right(1)), E.right(1)) Util.deepStrictEqual(_.absolve(_.left("e")), E.left("e")) Util.deepStrictEqual(_.absolve(_.both("e", 1)), E.right(1)) }) it("condemn", () => { Util.deepStrictEqual(_.condemn(_.right(1)), E.right(1)) Util.deepStrictEqual(_.condemn(_.left("e")), E.left("e")) Util.deepStrictEqual(_.condemn(_.both("e", 1)), E.left("e")) }) it("liftOption", () => { const f = _.liftOption((n: number) => (n > 0 ? O.some(n) : O.none()), () => "e") Util.deepStrictEqual(f(1), _.right(1)) Util.deepStrictEqual(f(-1), _.left("e")) }) it("liftEither", () => { const f = _.liftEither((n: number) => (n > 0 ? E.right(n) : E.left("e"))) Util.deepStrictEqual(f(1), _.right(1)) Util.deepStrictEqual(f(-1), _.fail("e")) }) it("liftThese", () => { const f = _.liftThese((n: number) => (n > 0 ? _.right(n) : _.left("e"))) Util.deepStrictEqual(f(1), _.right(1)) Util.deepStrictEqual(f(-1), _.fail("e")) }) it("fromTuple", () => { expect(pipe(["e", 1] as [string, number], _.fromTuple)).toEqual(_.both("e", 1)) }) it("reverse", () => { Util.deepStrictEqual(_.reverse(_.left("e")), _.right("e")) Util.deepStrictEqual(_.reverse(_.right(1)), _.left(1)) Util.deepStrictEqual(_.reverse(_.both("e", 1)), _.both(1, "e")) }) it("exists", () => { const gt2 = _.exists((n: number) => n > 2) Util.deepStrictEqual(gt2(_.left("a")), false) Util.deepStrictEqual(gt2(_.right(1)), false) Util.deepStrictEqual(gt2(_.right(3)), true) Util.deepStrictEqual(gt2(_.both("a", 1)), false) Util.deepStrictEqual(gt2(_.both("a", 3)), true) }) it("contains", () => { const contains = _.contains(number) Util.deepStrictEqual(contains(2)(_.left("a")), false) Util.deepStrictEqual(contains(2)(_.right(2)), true) Util.deepStrictEqual(contains(1)(_.right(2)), false) Util.deepStrictEqual(contains(2)(_.both("a", 2)), true) Util.deepStrictEqual(contains(1)(_.both("a", 2)), false) }) it("of", () => { Util.deepStrictEqual(_.of(1), _.right(1)) }) it("orElse", () => { Util.deepStrictEqual(pipe(_.right(1), _.orElse(() => _.right(2))), _.right(1)) Util.deepStrictEqual(pipe(_.right(1), _.orElse(() => _.left("b"))), _.right(1)) Util.deepStrictEqual(pipe(_.right(1), _.orElse(() => _.both("b", 2))), _.right(1)) Util.deepStrictEqual(pipe(_.left("a"), _.orElse(() => _.right(2))), _.right(2)) Util.deepStrictEqual(pipe(_.left("a"), _.orElse(() => _.left("b"))), _.left("b")) Util.deepStrictEqual(pipe(_.left("a"), _.orElse(() => _.both("b", 2))), _.both("b", 2)) Util.deepStrictEqual(pipe(_.both("a", 1), _.orElse(() => _.right(2))), _.both("a", 1)) Util.deepStrictEqual(pipe(_.both("a", 1), _.orElse(() => _.left("b"))), _.both("a", 1)) Util.deepStrictEqual(pipe(_.both("a", 1), _.orElse(() => _.both("b", 2))), _.both("a", 1)) }) it("orElseEither", () => { expect(pipe(_.right(1), _.orElseEither(() => _.right(2)))).toEqual(_.right(E.left(1))) expect(pipe(_.right(1), _.orElseEither(() => _.left("b")))).toEqual(_.right(E.left(1))) expect(pipe(_.right(1), _.orElseEither(() => _.both("b", 2)))).toEqual(_.right(E.left(1))) expect(pipe(_.left("a"), _.orElseEither(() => _.right(2)))).toEqual(_.right(E.right(2))) expect(pipe(_.left("a"), _.orElseEither(() => _.left("b")))).toEqual(_.left("b")) expect(pipe(_.left("a"), _.orElseEither(() => _.both("b", 2)))).toEqual(_.both("b", E.right(2))) expect(pipe(_.both("a", 1), _.orElseEither(() => _.right(2)))).toEqual(_.both("a", E.left(1))) expect(pipe(_.both("a", 1), _.orElseEither(() => _.left("b")))).toEqual(_.both("a", E.left(1))) expect(pipe(_.both("a", 1), _.orElseEither(() => _.both("b", 2)))).toEqual( _.both("a", E.left(1)) ) }) it("orElseFail", () => { Util.deepStrictEqual(pipe(_.right(1), _.orElseFail(() => "e2")), _.right(1)) Util.deepStrictEqual(pipe(_.left("e1"), _.orElseFail(() => "e2")), _.left("e2")) Util.deepStrictEqual(pipe(_.both("e1", 1), _.orElseFail(() => "e2")), _.both("e1", 1)) }) it("firstSuccessOf", () => { Util.deepStrictEqual(pipe(_.right(1), _.firstRightOrBothOf([])), _.right(1)) Util.deepStrictEqual(pipe(_.left("e"), _.firstRightOrBothOf([])), _.left("e")) Util.deepStrictEqual( pipe( _.left("e1"), _.firstRightOrBothOf([_.left("e2"), _.left("e3"), _.left("e4"), _.right(1)]) ), _.right(1) ) Util.deepStrictEqual( pipe( _.left("e1"), _.firstRightOrBothOf([_.left("e2"), _.left("e3"), _.left("e4"), _.both("e5", 1)]) ), _.both("e5", 1) ) Util.deepStrictEqual( pipe(_.left("e1"), _.firstRightOrBothOf([_.left("e2"), _.left("e3"), _.left("e4")])), _.left("e4") ) }) it("coproduct", () => { const coproduct = _.SemiCoproduct.coproduct Util.deepStrictEqual(coproduct(_.right(1), _.right(2)), _.right(1)) Util.deepStrictEqual(coproduct(_.right(1), _.left("e2")), _.right(1)) Util.deepStrictEqual(coproduct(_.left("e1"), _.right(2)), _.right(2)) Util.deepStrictEqual(coproduct(_.left("e1"), _.left("e2")), _.left("e2")) Util.deepStrictEqual(coproduct(_.both("e1", 1), _.right(2)), _.both("e1", 1)) Util.deepStrictEqual(coproduct(_.both("e1", 1), _.left("e2")), _.both("e1", 1)) }) it("coproduct", () => { const coproductMany = _.SemiCoproduct.coproductMany Util.deepStrictEqual(coproductMany(_.right(1), [_.right(2)]), _.right(1)) Util.deepStrictEqual(coproductMany(_.right(1), [_.left("e2")]), _.right(1)) Util.deepStrictEqual(coproductMany(_.left("e1"), [_.right(2)]), _.right(2)) Util.deepStrictEqual(coproductMany(_.left("e1"), [_.left("e2")]), _.left("e2")) Util.deepStrictEqual(coproductMany(_.both("e1", 1), [_.right(2)]), _.both("e1", 1)) Util.deepStrictEqual(coproductMany(_.both("e1", 1), [_.left("e2")]), _.both("e1", 1)) }) it("compact", () => { Util.deepStrictEqual(pipe(_.right(O.some(1)), _.compact(() => "e2")), _.right(1)) Util.deepStrictEqual(pipe(_.right(O.none()), _.compact(() => "e2")), _.left("e2")) Util.deepStrictEqual(pipe(_.left("e1"), _.compact(() => "e2")), _.left("e1")) Util.deepStrictEqual(pipe(_.both("e1", O.some(1)), _.compact(() => "e2")), _.both("e1", 1)) Util.deepStrictEqual(pipe(_.both("e1", O.none()), _.compact(() => "e2")), _.left("e2")) }) it("filter", () => { const predicate = (n: number) => n > 10 Util.deepStrictEqual(pipe(_.right(12), _.filter(predicate, () => "e2")), _.right(12)) Util.deepStrictEqual(pipe(_.right(7), _.filter(predicate, () => "e2")), _.left("e2")) Util.deepStrictEqual(pipe(_.left("e1"), _.filter(predicate, () => "e2")), _.left("e1")) Util.deepStrictEqual(pipe(_.both("e1", 12), _.filter(predicate, () => "e2")), _.both("e1", 12)) Util.deepStrictEqual(pipe(_.both("e1", 7), _.filter(predicate, () => "e2")), _.left("e2")) }) it("filterMap", () => { const f = (n: number) => (n > 2 ? O.some(n + 1) : O.none()) Util.deepStrictEqual(pipe(_.left("e1"), _.filterMap(f, () => "e2")), _.left("e1")) Util.deepStrictEqual(pipe(_.right(1), _.filterMap(f, () => "e2")), _.left("e2")) Util.deepStrictEqual(pipe(_.right(3), _.filterMap(f, () => "e2")), _.right(4)) Util.deepStrictEqual(pipe(_.both("e1", 1), _.filterMap(f, () => "e2")), _.left("e2")) Util.deepStrictEqual(pipe(_.both("e1", 3), _.filterMap(f, () => "e2")), _.both("e1", 4)) }) it("zipWith", () => { const e: _.Validated = _.left(["a"]) expect(pipe(e, _.zipWith(_.right(2), (a, b) => a + b))).toEqual(e) expect(pipe(_.right(1), _.zipWith(e, (a, b) => a + b))).toEqual(e) expect(pipe(_.right(1), _.zipWith(_.right(2), (a, b) => a + b))).toEqual(_.right(3)) }) it("sum", () => { const e: _.Validated = _.left(["a"]) expect(pipe(e, _.sum(_.right(2)))).toEqual(e) expect(pipe(_.right(1), _.sum(e))).toEqual(e) expect(pipe(_.right(2), _.sum(_.right(3)))).toEqual(_.right(5)) }) it("multiply", () => { const e: _.Validated = _.left(["a"]) expect(pipe(e, _.multiply(_.right(2)))).toEqual(e) expect(pipe(_.right(1), _.multiply(e))).toEqual(e) expect(pipe(_.right(2), _.multiply(_.right(3)))).toEqual(_.right(6)) }) it("subtract", () => { const e: _.Validated = _.left(["a"]) expect(pipe(e, _.subtract(_.right(2)))).toEqual(e) expect(pipe(_.right(1), _.subtract(e))).toEqual(e) expect(pipe(_.right(2), _.subtract(_.right(3)))).toEqual(_.right(-1)) }) it("divide", () => { const e: _.Validated = _.left(["a"]) expect(pipe(e, _.divide(_.right(2)))).toEqual(e) expect(pipe(_.right(1), _.divide(e))).toEqual(e) expect(pipe(_.right(6), _.divide(_.right(3)))).toEqual(_.right(2)) }) it("getEquivalence", () => { const isEquivalent = _.getEquivalence(N.Equivalence, N.Equivalence) Util.deepStrictEqual(isEquivalent(_.left(2), _.left(2)), true) Util.deepStrictEqual(isEquivalent(_.left(2), _.left(3)), false) Util.deepStrictEqual(isEquivalent(_.left(3), _.left(2)), false) Util.deepStrictEqual(isEquivalent(_.left(2), _.right(2)), false) Util.deepStrictEqual(isEquivalent(_.left(2), _.both(2, 2)), false) Util.deepStrictEqual(isEquivalent(_.right(2), _.right(2)), true) Util.deepStrictEqual(isEquivalent(_.right(2), _.right(3)), false) Util.deepStrictEqual(isEquivalent(_.right(3), _.right(2)), false) Util.deepStrictEqual(isEquivalent(_.right(2), _.both(2, 2)), false) Util.deepStrictEqual(isEquivalent(_.both(2, 2), _.both(2, 2)), true) Util.deepStrictEqual(isEquivalent(_.both(2, 3), _.both(3, 2)), false) }) }) ================================================ FILE: test/Tuple.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as T from "@fp-ts/core/Tuple" describe.concurrent("Tuple", () => { it("exports", () => { expect(T.Bicovariant).exists expect(T.mapFirst).exists expect(T.mapSecond).exists expect(T.appendElement).exists expect(T.getEquivalence).exists expect(T.getOrder).exists expect(T.getSemigroup).exists expect(T.getMonoid).exists }) it("tuple", () => { expect(T.tuple("a", 1, true)).toEqual(["a", 1, true]) }) it("appendElement", () => { expect(pipe(T.tuple("a", 1), T.appendElement(true))).toEqual(["a", 1, true]) }) it("getFirst", () => { expect(T.getFirst(T.tuple("a", 1))).toEqual("a") }) it("getSecond", () => { expect(T.getSecond(T.tuple("a", 1))).toEqual(1) }) it("bimap", () => { expect(T.bimap(T.tuple("a", 1), s => s + "!", n => n * 2)).toEqual(["a!", 2]) }) it("swap", () => { expect(T.swap(T.tuple("a", 1))).toEqual([1, "a"]) }) }) ================================================ FILE: test/index.ts ================================================ import * as _ from "@fp-ts/core" import * as assert from "assert" import * as glob from "glob" import * as path from "path" const getExportName = (name: string): string => { if (name === "HKT") { return name.toLowerCase() } return name.substring(0, 1).toLowerCase() + name.substring(1) } function getModuleNames(): ReadonlyArray { return glob .sync("./src/**/*.ts") .map((file) => path.parse(file)) .filter((file) => !file.dir.startsWith("./src/internal")) .map((file) => file.name) } describe.concurrent("index", () => { it("check exported modules", () => { const moduleNames = getModuleNames() moduleNames.forEach((name) => { if (name !== "index") { const exportName = getExportName(name) assert.deepStrictEqual( // tslint:disable-next-line: strict-type-predicates (_ as Record)[exportName] !== undefined, true, `The "${name}" module is not exported in src/index.ts as ${exportName}` ) } }) }) }) ================================================ FILE: test/limbo/Category.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Composable } from "./Composable" /** * @category type class * @since 1.0.0 */ export interface Category extends Composable { readonly identity: () => Kind } ================================================ FILE: test/limbo/Comonad.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Extendable } from "@fp-ts/core/test/limbo/Extendable" /** * @category type class * @since 1.0.0 */ export interface Comonad extends Extendable { readonly extract: (self: Kind) => A } ================================================ FILE: test/limbo/Composable.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" /** * @category type class * @since 1.0.0 */ export interface Composable extends TypeClass { readonly compose: ( bc: Kind ) => (ab: Kind) => Kind } ================================================ FILE: test/limbo/Extendable.ts ================================================ /** * @since 1.0.0 */ import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" /** * @category type class * @since 1.0.0 */ export interface Extendable extends Covariant { readonly extend: ( f: (self: Kind) => B ) => (self: Kind) => Kind } ================================================ FILE: test/limbo/NonEmptyTraversable.ts ================================================ /** * NonEmptyTraversable describes a parameterized type T that contains one or more values of type `A`. * * @since 1.0.0 */ import { identity, pipe } from "@fp-ts/core/Function" import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" import type { Covariant } from "@fp-ts/core/typeclass/Covariant" import type { SemiApplicative } from "@fp-ts/core/typeclass/SemiApplicative" /** * @category type class * @since 1.0.0 */ export interface NonEmptyTraversable extends TypeClass { readonly traverseNonEmpty: ( F: SemiApplicative ) => ( f: (a: A) => Kind ) => ( self: Kind ) => Kind> readonly sequenceNonEmpty: ( F: SemiApplicative ) => ( self: Kind> ) => Kind> } /** * Returns a default `traverseNonEmpty` composition. * * @since 1.0.0 */ export const traverseNonEmptyComposition = ( T: NonEmptyTraversable, G: NonEmptyTraversable ) => (F: SemiApplicative) => ( f: (a: A) => Kind ): (( self: Kind> ) => Kind>>) => T.traverseNonEmpty(F)(G.traverseNonEmpty(F)(f)) /** * Returns a default `sequenceNonEmpty` composition. * * @since 1.0.0 */ export const sequenceNonEmptyComposition = ( T: NonEmptyTraversable & Covariant, G: NonEmptyTraversable ) => (F: SemiApplicative) => ( self: Kind>> ): Kind>> => T.sequenceNonEmpty(F)(pipe(self, T.map(G.sequenceNonEmpty(F)))) /** * Returns a default `sequenceNonEmpty` implementation. * * @since 1.0.0 */ export const sequenceNonEmpty = ( traverseNonEmpty: NonEmptyTraversable["traverseNonEmpty"] ): NonEmptyTraversable["sequenceNonEmpty"] => ( F: SemiApplicative ): (( self: Kind> ) => Kind>) => traverseNonEmpty(F)(identity) ================================================ FILE: test/typeclass/Applicative.ts ================================================ import * as N from "@fp-ts/core/Number" import * as O from "@fp-ts/core/Option" import * as _ from "@fp-ts/core/typeclass/Applicative" import * as U from "../util" describe("Applicative", () => { it("liftMonoid", () => { const liftMonoid = _.getMonoid(O.Applicative) const M = liftMonoid(N.MonoidSum) U.deepStrictEqual(M.combine(O.none(), O.none()), O.none()) U.deepStrictEqual(M.combine(O.some(1), O.none()), O.none()) U.deepStrictEqual(M.combine(O.none(), O.some(2)), O.none()) U.deepStrictEqual(M.combine(O.some(1), O.some(2)), O.some(3)) }) }) ================================================ FILE: test/typeclass/Bicovariant.ts ================================================ import * as E from "@fp-ts/core/Either" import { pipe } from "@fp-ts/core/Function" import * as RA from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/typeclass/Bicovariant" import * as U from "../util" describe("Bicovariant", () => { it("mapLeft", () => { const mapLeft = _.mapLeft(E.Bicovariant) const f = (s: string) => s.length U.deepStrictEqual(pipe(E.right(1), mapLeft(f)), E.right(1)) U.deepStrictEqual(pipe(E.left("eee"), mapLeft(f)), E.left(3)) }) it("map", () => { const map = _.map(E.Bicovariant) const g = (n: number) => n * 2 U.deepStrictEqual(pipe(E.right(1), map(g)), E.right(2)) U.deepStrictEqual(pipe(E.left("eee"), map(g)), E.left("eee")) }) it("bimapComposition", () => { const bimap = _.bimapComposition(RA.Covariant, E.Bicovariant) const f = (s: string) => s.length const g = (n: number) => n * 2 U.deepStrictEqual(bimap([E.right(1), E.right(2), E.left("eee")], f, g), [ E.right(2), E.right(4), E.left(3) ]) }) }) ================================================ FILE: test/typeclass/Bounded.ts ================================================ import * as Number from "@fp-ts/core/Number" import * as _ from "@fp-ts/core/typeclass/Bounded" import * as U from "../util" describe("Bounded", () => { it("clamp", () => { const clamp = _.clamp({ ...Number.Order, minBound: 1, maxBound: 10 }) U.deepStrictEqual(clamp(2), 2) U.deepStrictEqual(clamp(10), 10) U.deepStrictEqual(clamp(20), 10) U.deepStrictEqual(clamp(1), 1) U.deepStrictEqual(clamp(-10), 1) }) it("reverse", () => { const B = _.reverse({ ...Number.Order, minBound: 10, maxBound: 1 }) U.deepStrictEqual(B.maxBound, 10) U.deepStrictEqual(B.minBound, 1) }) }) ================================================ FILE: test/typeclass/Chainable.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as O from "@fp-ts/core/Option" import * as _ from "@fp-ts/core/typeclass/Chainable" import * as U from "../util" describe("Chainable", () => { it("andThenDiscard", () => { const andThenDiscard = _.andThenDiscard(O.Chainable) U.deepStrictEqual(pipe(O.none(), andThenDiscard(O.none())), O.none()) U.deepStrictEqual(pipe(O.none(), andThenDiscard(O.some(2))), O.none()) U.deepStrictEqual(pipe(O.some(1), andThenDiscard(O.none())), O.none()) U.deepStrictEqual(pipe(O.some(1), andThenDiscard(O.some(2))), O.some(1)) }) it("bind", () => { const bind = _.bind(O.Chainable) U.deepStrictEqual(pipe(O.Do, bind("a", () => O.none())), O.none()) U.deepStrictEqual(pipe(O.Do, bind("a", () => O.some(1))), O.some({ a: 1 })) }) it("tap", () => { const tap = _.tap(O.Chainable) U.deepStrictEqual(pipe(O.none(), tap(() => O.none())), O.none()) U.deepStrictEqual(pipe(O.none(), tap(() => O.some(2))), O.none()) U.deepStrictEqual(pipe(O.some(1), tap(() => O.none())), O.none()) U.deepStrictEqual(pipe(O.some(1), tap(() => O.some(2))), O.some(1)) }) }) ================================================ FILE: test/typeclass/Contravariant.ts ================================================ import * as P from "@fp-ts/core/Predicate" import * as S from "@fp-ts/core/String" import * as _ from "@fp-ts/core/typeclass/Contravariant" import * as order from "@fp-ts/core/typeclass/Order" import * as U from "../util" describe("Contravariant", () => { it("mapComposition", () => { const map = _.contramapComposition(P.Contravariant, P.Contravariant) const emptyString: P.Predicate> = p => p("") === true const a = map(emptyString, s => s.length) U.deepStrictEqual(a(S.isString), false) U.deepStrictEqual(a(n => n === 0), true) }) it("imap", () => { const O = _.imap(order.contramap)( (s: string) => [s], ([s]) => s )( S.Order ) U.deepStrictEqual(O.compare(["a"], ["b"]), -1) U.deepStrictEqual(O.compare(["a"], ["a"]), 0) U.deepStrictEqual(O.compare(["b"], ["a"]), 1) }) }) ================================================ FILE: test/typeclass/Coproduct.ts ================================================ import * as O from "@fp-ts/core/Option" import * as _ from "@fp-ts/core/typeclass/Coproduct" import * as U from "../util" describe("Coproduct", () => { it("getMonoid", () => { const M = _.getMonoid(O.Alternative)() U.deepStrictEqual(M.combine(O.none(), O.none()), O.none()) U.deepStrictEqual(M.combine(O.some(1), O.none()), O.some(1)) U.deepStrictEqual(M.combine(O.none(), O.some(2)), O.some(2)) U.deepStrictEqual(M.combine(O.some(1), O.some(2)), O.some(1)) U.deepStrictEqual(M.combine(M.empty, O.none()), O.none()) U.deepStrictEqual(M.combine(M.empty, O.some(2)), O.some(2)) U.deepStrictEqual(M.combine(O.some(1), M.empty), O.some(1)) }) }) ================================================ FILE: test/typeclass/Covariant.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as O from "@fp-ts/core/Option" import * as RA from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/typeclass/Covariant" import * as U from "../util" describe("Covariant", () => { it("mapComposition", () => { const map = _.mapComposition(RA.Covariant, RA.Covariant) const f = (a: string) => a + "!" U.deepStrictEqual(map([], f), []) U.deepStrictEqual(map([[]], f), [[]]) U.deepStrictEqual(map([["a"]], f), [["a!"]]) U.deepStrictEqual(map([["a"], ["b"]], f), [["a!"], ["b!"]]) U.deepStrictEqual(map([["a", "c"], ["b", "d", "e"]], f), [["a!", "c!"], [ "b!", "d!", "e!" ]]) }) it("flap", () => { const flap = _.flap(O.Covariant) U.deepStrictEqual(pipe(1, flap(O.none())), O.none()) U.deepStrictEqual(pipe(1, flap(O.some(U.double))), O.some(2)) }) it("as", () => { const as = _.as(O.Covariant) U.deepStrictEqual(pipe(O.none(), as(1)), O.none()) U.deepStrictEqual(pipe(O.some(1), as(2)), O.some(2)) }) it("asUnit", () => { const asUnit = _.asUnit(O.Covariant) U.deepStrictEqual(pipe(O.none(), asUnit), O.none()) U.deepStrictEqual(pipe(O.some(1), asUnit), O.some(undefined)) }) it("let", () => { const letOption = _.let(O.Covariant) U.deepStrictEqual( pipe(O.some({ a: 1, b: 2 }), letOption("c", ({ a, b }) => a + b)), O.some({ a: 1, b: 2, c: 3 }) ) }) it("imap", () => { const f = _.imap(O.map)((s: string) => [s], ([s]) => s) U.deepStrictEqual(pipe(O.none(), f), O.none()) U.deepStrictEqual(pipe(O.some("a"), f), O.some(["a"])) }) }) ================================================ FILE: test/typeclass/Equivalence.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as _ from "@fp-ts/core/typeclass/Equivalence" describe("Equivalence", () => { it("exports", () => { expect(_.Invariant).exists expect(_.Contravariant).exists expect(_.SemiProduct).exists expect(_.Product).exists expect(_.tuple).exists expect(_.struct).exists }) test("strict returns an Equivalence that uses strict equality (===) to compare values", () => { const eq = _.strict<{ a: number }>() const a = { a: 1 } expect(eq(a, a)).toBe(true) expect(eq({ a: 1 }, { a: 1 })).toBe(false) }) it("contramap", () => { interface Person { readonly name: string readonly age: number } const eqPerson = pipe(_.string, _.contramap((p: Person) => p.name)) expect(eqPerson({ name: "a", age: 1 }, { name: "a", age: 2 })).toEqual(true) expect(eqPerson({ name: "a", age: 1 }, { name: "a", age: 1 })).toEqual(true) expect(eqPerson({ name: "a", age: 1 }, { name: "b", age: 1 })).toEqual(false) expect(eqPerson({ name: "a", age: 1 }, { name: "b", age: 2 })).toEqual(false) }) it("getSemigroup", () => { type T = readonly [string, number, boolean] const S = _.getSemigroup() const E0: _.Equivalence = _.contramap((x: T) => x[0])(_.string) const E1: _.Equivalence = _.contramap((x: T) => x[1])(_.number) const eqE0E1 = S.combine(E0, E1) expect(eqE0E1(["a", 1, true], ["a", 1, true])).toEqual(true) expect(eqE0E1(["a", 1, true], ["a", 1, false])).toEqual(true) expect(eqE0E1(["a", 1, true], ["b", 1, true])).toEqual(false) expect(eqE0E1(["a", 1, true], ["a", 2, false])).toEqual(false) const E2: _.Equivalence = _.contramap((x: T) => x[2])(_.boolean) const eqE0E1E2 = S.combineMany(E0, [E1, E2]) expect(eqE0E1E2(["a", 1, true], ["a", 1, true])).toEqual(true) expect(eqE0E1E2(["a", 1, true], ["b", 1, true])).toEqual(false) expect(eqE0E1E2(["a", 1, true], ["a", 2, true])).toEqual(false) expect(eqE0E1E2(["a", 1, true], ["a", 1, false])).toEqual(false) }) it("getMonoid", () => { type T = readonly [string, number, boolean] const M = _.getMonoid() const E0: _.Equivalence = _.contramap((x: T) => x[0])(_.string) const E1: _.Equivalence = _.contramap((x: T) => x[1])(_.number) const E2: _.Equivalence = _.contramap((x: T) => x[2])(_.boolean) const eqE0E1E2 = M.combineAll([E0, E1, E2]) expect(eqE0E1E2(["a", 1, true], ["a", 1, true])).toEqual(true) expect(eqE0E1E2(["a", 1, true], ["b", 1, true])).toEqual(false) expect(eqE0E1E2(["a", 1, true], ["a", 2, true])).toEqual(false) expect(eqE0E1E2(["a", 1, true], ["a", 1, false])).toEqual(false) }) it("of", () => { const eq = _.Product.of([]) expect(eq([], [])).toEqual(true) }) it("product", () => { const eq = _.Product.product(_.string, _.string) expect(eq(["a", "b"], ["a", "b"])).toEqual(true) expect(eq(["a", "b"], ["c", "b"])).toEqual(false) expect(eq(["a", "b"], ["a", "c"])).toEqual(false) }) it("productMany", () => { const eq = _.Product.productMany(_.string, [_.string]) expect(eq(["a", "b"], ["a", "b"])).toEqual(true) expect(eq(["a", "b"], ["a", "b", "c"])).toEqual(true) expect(eq(["a", "b", "c"], ["a", "b"])).toEqual(true) expect(eq(["a", "b"], ["c", "b"])).toEqual(false) expect(eq(["a", "b"], ["a", "c"])).toEqual(false) }) it("productAll", () => { const eq = _.Product.productAll([_.string, _.string]) expect(eq(["a"], ["a"])).toEqual(true) expect(eq(["a"], ["b"])).toEqual(false) expect(eq(["a", "b"], ["a", "b"])).toEqual(true) expect(eq(["a", "b"], ["a", "c"])).toEqual(false) }) }) ================================================ FILE: test/typeclass/Filterable.ts ================================================ import * as E from "@fp-ts/core/Either" import { pipe } from "@fp-ts/core/Function" import * as O from "@fp-ts/core/Option" import * as RA from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/typeclass/Filterable" import * as U from "../util" describe("Filterable", () => { it("filterMapComposition", () => { const filterMap = _.filterMapComposition(RA.Covariant, O.Filterable) const f = (s: string) => s.length > 1 ? O.some(s.length) : O.none() U.deepStrictEqual(filterMap([], f), []) U.deepStrictEqual(filterMap([O.none()], f), [O.none()]) U.deepStrictEqual(filterMap([O.some("a")], f), [O.none()]) U.deepStrictEqual(filterMap([O.some("aa")], f), [O.some(2)]) }) it("partitionMapComposition", () => { const partitionMap = _.partitionMapComposition(RA.Covariant, O.Filterable) const f = (s: string) => s.length > 1 ? E.right(s.length) : E.left(s + "!") U.deepStrictEqual(partitionMap([], f), [[], []]) U.deepStrictEqual(partitionMap([O.none()], f), [[O.none()], [O.none()]]) U.deepStrictEqual(partitionMap([O.some("a")], f), [[O.some("a!")], [O.none()]]) U.deepStrictEqual(partitionMap([O.some("aa")], f), [[O.none()], [O.some(2)]]) }) it("filter", () => { const filter = _.filter(RA.Filterable) const f = filter((n: number) => n > 0) U.deepStrictEqual(pipe([], f), []) U.deepStrictEqual(pipe([1], f), [1]) U.deepStrictEqual(pipe([-1], f), []) U.deepStrictEqual(pipe([1, -1], f), [1]) }) it("partition", () => { const partition = _.partition(RA.Filterable) const f = partition((n: number) => n > 0) U.deepStrictEqual(pipe([], f), [[], []]) U.deepStrictEqual(pipe([1], f), [[], [1]]) U.deepStrictEqual(pipe([-1], f), [[-1], []]) U.deepStrictEqual(pipe([1, -1], f), [[-1], [1]]) }) it("compact", () => { const compact = _.compact(RA.Filterable) assert.deepStrictEqual(compact([]), []) assert.deepStrictEqual(compact([O.some(1), O.some(2), O.some(3)]), [ 1, 2, 3 ]) assert.deepStrictEqual(compact([O.some(1), O.none(), O.some(3)]), [ 1, 3 ]) }) it("separate", () => { const separate = _.separate(RA.Filterable) U.deepStrictEqual(pipe([], separate), [[], []]) U.deepStrictEqual(pipe([E.right(1), E.left("e"), E.right(2)], separate), [ ["e"], [1, 2] ]) }) }) ================================================ FILE: test/typeclass/FlatMap.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as O from "@fp-ts/core/Option" import * as _ from "@fp-ts/core/typeclass/FlatMap" import * as U from "../util" describe("FlatMap", () => { it("flatten", () => { const flatten = _.flatten(O.FlatMap) U.deepStrictEqual(pipe(O.none(), flatten), O.none()) U.deepStrictEqual(pipe(O.some(O.none()), flatten), O.none()) U.deepStrictEqual(pipe(O.some(O.some(1)), flatten), O.some(1)) }) it("andThen", () => { const andThen = _.andThen(O.FlatMap) U.deepStrictEqual(pipe(O.none(), andThen(O.none())), O.none()) U.deepStrictEqual(pipe(O.none(), andThen(O.some(2))), O.none()) U.deepStrictEqual(pipe(O.some(1), andThen(O.none())), O.none()) U.deepStrictEqual(pipe(O.some(1), andThen(O.some(2))), O.some(2)) }) it("composeKleisliArrow", () => { const composeKleisliArrow = _.composeKleisliArrow(O.FlatMap) const f = (s: string): O.Option => s.length > 0 ? O.some(s.length) : O.none() const g = (n: number): O.Option => n > 1 ? O.some(n) : O.none() const h = pipe(f, composeKleisliArrow(g)) U.deepStrictEqual(h(""), O.none()) U.deepStrictEqual(h("a"), O.none()) U.deepStrictEqual(h("aa"), O.some(2)) }) }) ================================================ FILE: test/typeclass/Foldable.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as N from "@fp-ts/core/Number" import * as O from "@fp-ts/core/Option" import * as RA from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/typeclass/Foldable" import * as U from "../util" describe("Foldable", () => { it("reduceComposition", () => { const reduce = _.reduceComposition(RA.Foldable, RA.Foldable) const f = (b: string, a: string) => b + a U.deepStrictEqual(reduce([], "-", f), "-") U.deepStrictEqual(reduce([[]], "-", f), "-") U.deepStrictEqual(reduce([["a", "c"], ["b", "d"]], "-", f), "-acbd") }) it("toArray", () => { const toArray = _.toArray(O.Foldable) U.deepStrictEqual(toArray(O.none()), []) U.deepStrictEqual(toArray(O.some(2)), [2]) }) it("toArrayMap", () => { const toArrayMap = _.toArrayMap(O.Foldable) U.deepStrictEqual(toArrayMap(O.none(), U.double), []) U.deepStrictEqual(toArrayMap(O.some(2), U.double), [4]) }) it("combineMap", () => { const combineMap = _.combineMap(RA.Foldable) U.deepStrictEqual(combineMap(N.MonoidSum)([1, 2, 3], U.double), 12) }) it("reduceKind", () => { const reduceKind = _.reduceKind(RA.Foldable)(O.Monad) U.deepStrictEqual(reduceKind([], "-", () => O.none()), O.some("-")) U.deepStrictEqual(reduceKind(["a"], "-", () => O.none()), O.none()) U.deepStrictEqual( reduceKind(["a", "b", "c"], "-", (b, a) => O.some(b + a)), O.some("-abc") ) U.deepStrictEqual( reduceKind(["a", "b", "c"], "-", (b, a) => a === "b" ? O.none() : O.some(b + a)), O.none() ) }) it("coproductMapKind", () => { const coproductMapKind = _.coproductMapKind(RA.Foldable)(O.Alternative) U.deepStrictEqual(pipe([], coproductMapKind(() => O.none())), O.none()) U.deepStrictEqual(pipe(["a"], coproductMapKind(() => O.none())), O.none()) U.deepStrictEqual(pipe(["a", "b", "c"], coproductMapKind((a) => O.some(a))), O.some("a")) U.deepStrictEqual( pipe(["a", "b", "c"], coproductMapKind((a) => a === "b" ? O.none() : O.some(a))), O.some("a") ) }) }) ================================================ FILE: test/typeclass/Invariant.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as O from "@fp-ts/core/Option" import * as P from "@fp-ts/core/Predicate" import * as String from "@fp-ts/core/String" import * as _ from "@fp-ts/core/typeclass/Invariant" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as U from "../util" describe("Invariant", () => { it("imapComposition", () => { const imap = _.imapComposition(semigroup.Invariant, O.Invariant) const S = imap(O.getOptionalMonoid(String.Semigroup), s => [s], ([s]) => s) U.deepStrictEqual(S.combine(O.none(), O.none()), O.none()) U.deepStrictEqual(S.combine(O.none(), O.some(["b"])), O.some(["b"])) U.deepStrictEqual(S.combine(O.some(["a"]), O.none()), O.some(["a"])) U.deepStrictEqual( S.combine(O.some(["a"]), O.some(["b"])), O.some(["ab"]) ) }) describe("bindTo", () => { it("Covariant (Option)", () => { const bindTo = _.bindTo(O.Invariant) U.deepStrictEqual(pipe(O.none(), bindTo("a")), O.none()) U.deepStrictEqual(pipe(O.some(1), bindTo("a")), O.some({ a: 1 })) }) it("Contravariant (Predicate)", () => { const bindTo = _.bindTo(P.Invariant) const p = pipe(String.isString, bindTo("a")) U.deepStrictEqual(p({ a: "a" }), true) U.deepStrictEqual(p({ a: 1 }), false) }) }) describe("tupled", () => { it("Covariant (Option)", () => { const tupled = _.tupled(O.Invariant) U.deepStrictEqual(pipe(O.none(), tupled), O.none()) U.deepStrictEqual(pipe(O.some(1), tupled), O.some([1])) }) it("Contravariant (Predicate)", () => { const tupled = _.tupled(P.Invariant) const p = pipe(String.isString, tupled) U.deepStrictEqual(p(["a"]), true) U.deepStrictEqual(p([1]), false) }) }) }) ================================================ FILE: test/typeclass/Monoid.ts ================================================ import * as N from "@fp-ts/core/Number" import * as String from "@fp-ts/core/String" import * as _ from "@fp-ts/core/typeclass/Monoid" import * as U from "../util" describe("Monoid", () => { it("min", () => { const M = _.min(N.Bounded) U.deepStrictEqual(M.combineAll([]), +Infinity) U.deepStrictEqual(M.combineAll([1]), 1) U.deepStrictEqual(M.combineAll([1, -1]), -1) }) it("max", () => { const M = _.max(N.Bounded) U.deepStrictEqual(M.combineAll([]), -Infinity) U.deepStrictEqual(M.combineAll([1]), 1) U.deepStrictEqual(M.combineAll([1, -1]), 1) }) it("reverse", () => { const M = _.reverse(String.Monoid) U.deepStrictEqual(M.combine("a", "b"), "ba") U.deepStrictEqual(M.combine("a", M.empty), "a") U.deepStrictEqual(M.combine(M.empty, "a"), "a") U.deepStrictEqual(M.combineMany("a", []), "a") U.deepStrictEqual(M.combineMany("a", ["b", "c", "d"]), "dcba") U.deepStrictEqual(M.combineMany("a", [M.empty]), "a") U.deepStrictEqual(M.combineMany(M.empty, ["a"]), "a") }) describe("struct", () => { it("baseline", () => { const M = _.struct({ name: String.Monoid, age: N.MonoidSum }) U.deepStrictEqual(M.empty, { name: "", age: 0 }) U.deepStrictEqual(M.combine({ name: "a", age: 10 }, { name: "b", age: 20 }), { name: "ab", age: 30 }) }) it("should ignore non own properties", () => { const monoids = Object.create({ a: 1 }) const M = _.struct(monoids) U.deepStrictEqual(M.empty, {}) }) }) it("tuple", () => { const M = _.tuple( String.Monoid, N.MonoidSum ) U.deepStrictEqual(M.empty, ["", 0]) U.deepStrictEqual(M.combine(["a", 10], ["b", 20]), ["ab", 30]) }) }) ================================================ FILE: test/typeclass/NonEmptyTraversable.ts ================================================ import { identity, pipe } from "@fp-ts/core/Function" import type { TypeLambda } from "@fp-ts/core/HKT" import * as O from "@fp-ts/core/Option" import * as RA from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/test/limbo/NonEmptyTraversable" import * as covariant from "@fp-ts/core/typeclass/Covariant" import * as U from "../util" const NonEmptyTraversable: _.NonEmptyTraversable = { // @ts-expect-error traverseNonEmpty: RA.traverseNonEmpty, // @ts-expect-error sequenceNonEmpty: F => self => pipe(self, RA.traverseNonEmpty(F)(identity)) } /** * @category type lambdas * @since 1.0.0 */ export interface NonEmptyReadonlyArrayTypeLambda extends TypeLambda { readonly type: RA.NonEmptyReadonlyArray } const imap = covariant.imap(RA.mapNonEmpty) /** * @category instances * @since 1.0.0 */ export const NonEmptyCovariant: covariant.Covariant = { imap, map: RA.mapNonEmpty } describe("NonEmptyTraversable", () => { it("traverseNonEmptyComposition", () => { const traverseNonEmpty = _.traverseNonEmptyComposition( NonEmptyTraversable, NonEmptyTraversable )(O.SemiApplicative)((n: number) => (n > 0 ? O.some(n) : O.none())) U.deepStrictEqual(traverseNonEmpty([[1]]), O.some([[1]] as const)) U.deepStrictEqual(traverseNonEmpty([[1, -1]]), O.none()) U.deepStrictEqual(traverseNonEmpty([[1, 2, 3], [4, 5]]), O.some([[1, 2, 3], [4, 5]] as const)) U.deepStrictEqual(traverseNonEmpty([[1, 2, 3], [4, -1]]), O.none()) }) it("traverseNonEmptyComposition", () => { const sequence = _.sequenceNonEmptyComposition( { ...NonEmptyTraversable, ...NonEmptyCovariant }, NonEmptyTraversable )(O.SemiApplicative) U.deepStrictEqual(sequence([[O.some(1)]]), O.some([[1]] as const)) U.deepStrictEqual(sequence([[O.some(1), O.none()]]), O.none()) U.deepStrictEqual( sequence([[O.some(1), O.some(2), O.some(3)], [O.some(4), O.some(5)]]), O.some([[1, 2, 3], [4, 5]] as const) ) U.deepStrictEqual( sequence([[O.some(1), O.some(2), O.some(3)], [O.some(4), O.none()]]), O.none() ) }) it("sequenceNonEmpty", () => { const sequenceNonEmpty = _.sequenceNonEmpty( NonEmptyTraversable.traverseNonEmpty )(O.SemiApplicative) U.deepStrictEqual(sequenceNonEmpty([O.none()]), O.none()) U.deepStrictEqual(sequenceNonEmpty([O.some(1)]), O.some([1] as const)) U.deepStrictEqual(sequenceNonEmpty([O.none()]), O.none()) U.deepStrictEqual(sequenceNonEmpty([O.some(1), O.none()]), O.none()) U.deepStrictEqual(sequenceNonEmpty([O.some(1), O.some(2)]), O.some([1, 2] as const)) }) }) ================================================ FILE: test/typeclass/Of.ts ================================================ import * as O from "@fp-ts/core/Option" import * as RA from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/typeclass/Of" import * as U from "../util" describe("Of", () => { it("ofComposition", () => { const of = _.ofComposition(RA.Of, O.Of) U.deepStrictEqual(of(1), [O.some(1)]) }) it("unit", () => { U.deepStrictEqual(_.unit(O.Pointed), O.some(undefined)) }) }) ================================================ FILE: test/typeclass/Order.ts ================================================ import { pipe } from "@fp-ts/core/Function" import { sort } from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/typeclass/Order" import * as U from "../util" describe("Order", () => { it("exports", () => { expect(_.Invariant).exist expect(_.Contravariant).exist expect(_.string).exist expect(_.number).exist expect(_.boolean).exist expect(_.bigint).exist }) it("productAll", () => { const O = _.Product.productAll([_.string, _.string]) U.deepStrictEqual(O.compare(["a"], ["b"]), -1) U.deepStrictEqual(O.compare(["a"], ["a"]), 0) U.deepStrictEqual(O.compare(["b"], ["a"]), 1) U.deepStrictEqual(O.compare(["a", "b"], ["a", "c"]), -1) U.deepStrictEqual(O.compare(["a", "b"], ["a", "b"]), 0) U.deepStrictEqual(O.compare(["a", "c"], ["a", "b"]), 1) }) it("contramap", () => { const O = _.contramap(_.number, (s: string) => s.length) U.deepStrictEqual(O.compare("a", "b"), 0) U.deepStrictEqual(O.compare("a", "bb"), -1) U.deepStrictEqual(O.compare("aa", "b"), 1) }) it("getSemigroup", () => { type T = [number, string] const tuples: Array = [ [2, "c"], [1, "b"], [2, "a"], [1, "c"] ] const S = _.getSemigroup() const sortByFst = pipe( _.number, _.contramap((x: T) => x[0]) ) const sortBySnd = pipe( _.string, _.contramap((x: T) => x[1]) ) U.deepStrictEqual(sort(S.combine(sortByFst, sortBySnd))(tuples), [ [1, "b"], [1, "c"], [2, "a"], [2, "c"] ]) U.deepStrictEqual(sort(S.combine(sortBySnd, sortByFst))(tuples), [ [2, "a"], [1, "b"], [1, "c"], [2, "c"] ]) U.deepStrictEqual(sort(S.combineMany(sortBySnd, []))(tuples), [ [2, "a"], [1, "b"], [2, "c"], [1, "c"] ]) U.deepStrictEqual(sort(S.combineMany(sortBySnd, [sortByFst]))(tuples), [ [2, "a"], [1, "b"], [1, "c"], [2, "c"] ]) }) it("getMonoid", () => { type T = [number, string] const tuples: Array = [ [2, "c"], [1, "b"], [2, "a"], [1, "c"] ] const M = _.getMonoid() const sortByFst = pipe( _.number, _.contramap((x: T) => x[0]) ) const sortBySnd = pipe( _.string, _.contramap((x: T) => x[1]) ) U.deepStrictEqual(sort(M.combineMany(M.empty, [sortByFst, sortBySnd]))(tuples), [ [1, "b"], [1, "c"], [2, "a"], [2, "c"] ]) U.deepStrictEqual(sort(M.combineMany(sortBySnd, [sortByFst, M.empty]))(tuples), [ [2, "a"], [1, "b"], [1, "c"], [2, "c"] ]) }) it("clamp", () => { const clamp = _.clamp(_.number) U.deepStrictEqual(clamp(2, 1, 10), 2) U.deepStrictEqual(clamp(10, 1, 10), 10) U.deepStrictEqual(clamp(20, 1, 10), 10) U.deepStrictEqual(clamp(1, 1, 10), 1) U.deepStrictEqual(clamp(-10, 1, 10), 1) }) it("between", () => { const between = _.between(_.number) U.deepStrictEqual(between(2, 1, 10), true) U.deepStrictEqual(between(10, 1, 10), true) U.deepStrictEqual(between(20, 1, 10), false) U.deepStrictEqual(between(1, 1, 10), true) U.deepStrictEqual(between(-10, 1, 10), false) }) it("reverse", () => { const O = _.reverse(_.number) U.deepStrictEqual(O.compare(1, 2), 1) U.deepStrictEqual(O.compare(2, 1), -1) U.deepStrictEqual(O.compare(2, 2), 0) }) it("lessThan", () => { const lessThan = _.lessThan(_.number) U.deepStrictEqual(lessThan(0, 1), true) U.deepStrictEqual(lessThan(1, 1), false) U.deepStrictEqual(lessThan(2, 1), false) }) it("lessThanOrEqualTo", () => { const lessThanOrEqualTo = _.lessThanOrEqualTo(_.number) U.deepStrictEqual(lessThanOrEqualTo(0, 1), true) U.deepStrictEqual(lessThanOrEqualTo(1, 1), true) U.deepStrictEqual(lessThanOrEqualTo(2, 1), false) }) it("greaterThan", () => { const greaterThan = _.greaterThan(_.number) U.deepStrictEqual(greaterThan(0, 1), false) U.deepStrictEqual(greaterThan(1, 1), false) U.deepStrictEqual(greaterThan(2, 1), true) }) it("greaterThanOrEqualTo", () => { const greaterThanOrEqualTo = _.greaterThanOrEqualTo(_.number) U.deepStrictEqual(greaterThanOrEqualTo(0, 1), false) U.deepStrictEqual(greaterThanOrEqualTo(1, 1), true) U.deepStrictEqual(greaterThanOrEqualTo(2, 1), true) }) it("min", () => { type A = { a: number } const min = _.min( pipe( _.number, _.contramap((a: A) => a.a) ) ) U.deepStrictEqual(min({ a: 1 }, { a: 2 }), { a: 1 }) U.deepStrictEqual(min({ a: 2 }, { a: 1 }), { a: 1 }) const first = { a: 1 } const second = { a: 1 } U.strictEqual(min(first, second), first) }) it("max", () => { type A = { a: number } const max = _.max( pipe( _.number, _.contramap((a: A) => a.a) ) ) U.deepStrictEqual(max({ a: 1 }, { a: 2 }), { a: 2 }) U.deepStrictEqual(max({ a: 2 }, { a: 1 }), { a: 2 }) const first = { a: 1 } const second = { a: 1 } U.strictEqual(max(first, second), first) }) describe("SemiProduct", () => { it("product", () => { const O = _.SemiProduct.product(_.string, _.number) U.deepStrictEqual(O.compare(["a", 1], ["a", 2]), -1) U.deepStrictEqual(O.compare(["a", 1], ["a", 1]), 0) U.deepStrictEqual(O.compare(["a", 1], ["a", 0]), 1) U.deepStrictEqual(O.compare(["a", 1], ["b", 1]), -1) }) it("productMany", () => { const O = _.SemiProduct.productMany(_.string, [_.string, _.string]) U.deepStrictEqual(O.compare(["a", "b"], ["a", "c"]), -1) U.deepStrictEqual(O.compare(["a", "b"], ["a", "b"]), 0) U.deepStrictEqual(O.compare(["a", "b"], ["a", "a"]), 1) U.deepStrictEqual(O.compare(["a", "b"], ["b", "a"]), -1) }) }) describe("Product", () => { it("of", () => { const O = _.Product.of("a") U.deepStrictEqual(O.compare("b", "a"), 0) U.deepStrictEqual(O.compare("a", "a"), 0) U.deepStrictEqual(O.compare("a", "b"), 0) }) it("productAll", () => { const O = pipe( _.Product.productAll([_.string, _.string, _.string]) ) U.deepStrictEqual(O.compare(["a", "b"], ["a", "c"]), -1) U.deepStrictEqual(O.compare(["a", "b"], ["a", "b"]), 0) U.deepStrictEqual(O.compare(["a", "b"], ["a", "a"]), 1) U.deepStrictEqual(O.compare(["a", "b"], ["b", "a"]), -1) }) }) }) ================================================ FILE: test/typeclass/Product.ts ================================================ import * as Boolean from "@fp-ts/core/Boolean" import * as Number from "@fp-ts/core/Number" import * as O from "@fp-ts/core/Option" import * as P from "@fp-ts/core/Predicate" import * as String from "@fp-ts/core/String" import * as _ from "@fp-ts/core/typeclass/Product" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as U from "../util" describe("Product", () => { describe("tuple", () => { it("Covariant (Option)", () => { const tuple = _.tuple(O.Product) U.deepStrictEqual(tuple(), O.some([])) U.deepStrictEqual(tuple(O.some("a")), O.some(["a"])) U.deepStrictEqual( tuple(O.some("a"), O.some(1), O.some(true)), O.some(["a", 1, true]) ) U.deepStrictEqual(tuple(O.some("a"), O.some(1), O.none()), O.none()) }) it("Invariant (Semigroup)", () => { const tuple = _.tuple(semigroup.Product) U.deepStrictEqual(tuple().combine([], []), []) const S = tuple(String.Semigroup, Number.SemigroupSum) U.deepStrictEqual(S.combine(["a", 2], ["b", 3]), ["ab", 5]) }) it("Contravariant (Predicate)", () => { const tuple = _.tuple(P.Product) U.deepStrictEqual(tuple()([]), true) const p = tuple(String.isString, Number.isNumber, Boolean.isBoolean) U.deepStrictEqual(p(["a", 1, true]), true) U.deepStrictEqual(p(["a", 1, "b"]), false) }) }) describe("struct", () => { it("Covariant (Option)", () => { const struct = _.struct(O.Product) U.deepStrictEqual(struct({}), O.some({})) U.deepStrictEqual(struct({ a: O.some("a") }), O.some({ a: "a" })) U.deepStrictEqual( struct({ a: O.some("a"), b: O.some(1), c: O.some(true) }), O.some({ a: "a", b: 1, c: true }) ) U.deepStrictEqual( struct({ a: O.some("a"), b: O.some(1), c: O.none() }), O.none() ) }) it("Invariant (Semigroup)", () => { const struct = _.struct(semigroup.Product) U.deepStrictEqual(struct({}).combine({}, {}), {}) const S = struct({ x: String.Semigroup, y: Number.SemigroupSum }) U.deepStrictEqual(S.combine({ x: "a", y: 2 }, { x: "b", y: 3 }), { x: "ab", y: 5 }) }) it("Contravariant (Predicate)", () => { const struct = _.struct(P.Product) U.deepStrictEqual(struct({})({}), true) const p = struct({ x: String.isString, y: Number.isNumber, z: Boolean.isBoolean }) U.deepStrictEqual(p({ x: "a", y: 1, z: true }), true) U.deepStrictEqual(p({ x: "a", y: 1, z: "b" }), false) }) }) }) ================================================ FILE: test/typeclass/SemiApplicative.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as O from "@fp-ts/core/Option" import * as String from "@fp-ts/core/String" import * as _ from "@fp-ts/core/typeclass/SemiApplicative" import * as U from "../util" describe("SemiApplicative", () => { it("ap", () => { const ap = _.ap(O.SemiApplicative) const double = (n: number) => n * 2 U.deepStrictEqual(pipe(O.none(), ap(O.none())), O.none()) U.deepStrictEqual(pipe(O.none(), ap(O.some(1))), O.none()) U.deepStrictEqual(pipe(O.some(double), ap(O.none())), O.none()) U.deepStrictEqual(pipe(O.some(double), ap(O.some(1))), O.some(2)) }) it("andThenDiscard", () => { const andThenDiscard = _.andThenDiscard(O.SemiApplicative) U.deepStrictEqual(pipe(O.none(), andThenDiscard(O.none())), O.none()) U.deepStrictEqual(pipe(O.none(), andThenDiscard(O.some(2))), O.none()) U.deepStrictEqual(pipe(O.some(1), andThenDiscard(O.none())), O.none()) U.deepStrictEqual(pipe(O.some(1), andThenDiscard(O.some(2))), O.some(1)) }) it("andThen", () => { const andThen = _.andThen(O.SemiApplicative) U.deepStrictEqual(pipe(O.none(), andThen(O.none())), O.none()) U.deepStrictEqual(pipe(O.none(), andThen(O.some(2))), O.none()) U.deepStrictEqual(pipe(O.some(1), andThen(O.none())), O.none()) U.deepStrictEqual(pipe(O.some(1), andThen(O.some(2))), O.some(2)) }) it("liftSemigroup", () => { const liftSemigroup = _.getSemigroup(O.SemiApplicative) const S = liftSemigroup(String.Semigroup) U.deepStrictEqual(S.combine(O.none(), O.none()), O.none()) U.deepStrictEqual(S.combine(O.none(), O.some("b")), O.none()) U.deepStrictEqual(S.combine(O.some("a"), O.none()), O.none()) U.deepStrictEqual(S.combine(O.some("a"), O.some("b")), O.some("ab")) U.deepStrictEqual(S.combineMany(O.some("a"), [O.some("b"), O.some("c")]), O.some("abc")) }) }) ================================================ FILE: test/typeclass/SemiCoproduct.ts ================================================ import * as E from "@fp-ts/core/Either" import * as _ from "@fp-ts/core/typeclass/SemiCoproduct" import * as U from "../util" describe("SemiCoproduct", () => { it("getSemigroup", () => { const S = _.getSemigroup(E.SemiCoproduct)() U.deepStrictEqual(S.combine(E.right(1), E.right(2)), E.right(1)) U.deepStrictEqual(S.combine(E.left("a"), E.right(2)), E.right(2)) U.deepStrictEqual(S.combine(E.right(1), E.left("b")), E.right(1)) U.deepStrictEqual(S.combine(E.left("a"), E.left("b")), E.left("b")) U.deepStrictEqual(S.combineMany(E.left("a"), [E.left("b")]), E.left("b")) }) }) ================================================ FILE: test/typeclass/SemiProduct.ts ================================================ import * as Boolean from "@fp-ts/core/Boolean" import { pipe } from "@fp-ts/core/Function" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import * as Number from "@fp-ts/core/Number" import * as O from "@fp-ts/core/Option" import * as P from "@fp-ts/core/Predicate" import * as RA from "@fp-ts/core/ReadonlyArray" import * as String from "@fp-ts/core/String" import * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as _ from "@fp-ts/core/typeclass/SemiProduct" import * as U from "../util" describe("SemiProduct", () => { it("productMany should be equivalent to `ap`", () => { const curry = (f: Function, n: number, acc: ReadonlyArray) => (x: unknown) => { const combined = Array(acc.length + 1) for (let i = 0; i < acc.length; i++) { combined[i] = acc[i] } combined[acc.length] = x return n === 0 ? f.apply(null, combined) : curry(f, n - 1, combined) } const getCurriedTupleConstructor = (len: number): (a: any) => any => curry(>(...t: T): T => t, len - 1, []) const assertSameResult = ( SemiApplicative: semiApplicative.SemiApplicative ) => (collection: Iterable>) => (self: Kind) => { const ap = semiApplicative.ap(SemiApplicative) const productManyFromAp = (collection: Iterable>) => ( self: Kind ): Kind]> => { const args = [self, ...Array.from(collection)] const len = args.length const f = getCurriedTupleConstructor(len) let fas = pipe(args[0], SemiApplicative.map(f)) for (let i = 1; i < len; i++) { fas = pipe(fas, ap(args[i])) } return fas } const actual = SemiApplicative.productMany(self, collection) const expected = pipe(self, productManyFromAp(collection)) U.deepStrictEqual(actual, expected) } assertSameResult(RA.SemiApplicative)([])([]) assertSameResult(RA.SemiApplicative)([])([1, 2, 3]) assertSameResult(RA.SemiApplicative)([[4]])([1, 2, 3]) assertSameResult(RA.SemiApplicative)([[4, 5, 6], [7, 8], [9, 10, 11]])([1, 2, 3]) }) describe("productComposition", () => { it("ReadonlyArray", () => { const product = _.productComposition(RA.SemiApplicative, O.SemiProduct) U.deepStrictEqual(product([], [O.none()]), []) U.deepStrictEqual(product([O.none()], []), []) U.deepStrictEqual(product([O.none()], [O.none()]), [O.none()]) expect(product([O.some(1)], [O.some(2)])).toEqual([O.some([1, 2])]) }) it("Option", () => { const product = _.productComposition(O.SemiApplicative, O.SemiProduct) U.deepStrictEqual(product(O.none(), O.none()), O.none()) U.deepStrictEqual(product(O.some(O.none()), O.none()), O.none()) U.deepStrictEqual(product(O.some(O.some(1)), O.none()), O.none()) U.deepStrictEqual(product(O.some(O.some(1)), O.some(O.none())), O.some(O.none())) U.deepStrictEqual(product(O.some(O.none()), O.some(O.some(2))), O.some(O.none())) U.deepStrictEqual( product(O.some(O.some(1)), O.some(O.some(2))), O.some(O.some([1, 2])) ) }) }) describe("productManyComposition", () => { it("ReadonlyArray", () => { const productMany = _.productManyComposition(RA.SemiApplicative, O.SemiProduct) expect(productMany([O.some(1), O.none()], [])).toEqual([ O.some([1]), O.none() ]) expect(productMany([O.some(1), O.none()], [[O.some(2), O.none()]])).toEqual([ O.some([1, 2]), O.none(), O.none(), O.none() ]) expect( productMany([O.some(1), O.some(2)], [[O.some(3), O.some(4)], [O.some(5)]]) ).toEqual( [ O.some([1, 3, 5]), O.some([1, 4, 5]), O.some([2, 3, 5]), O.some([2, 4, 5]) ] ) }) it("Option", () => { const productMany = _.productManyComposition(O.SemiApplicative, O.SemiProduct) U.deepStrictEqual(productMany(O.none(), []), O.none()) U.deepStrictEqual(productMany(O.some(O.none()), []), O.some(O.none())) U.deepStrictEqual(productMany(O.some(O.some(1)), []), O.some(O.some([1]))) U.deepStrictEqual(productMany(O.none(), [O.none()]), O.none()) U.deepStrictEqual(productMany(O.some(O.none()), [O.none()]), O.none()) U.deepStrictEqual(productMany(O.some(O.none()), [O.some(O.none())]), O.some(O.none())) U.deepStrictEqual( productMany(O.some(O.none()), [O.some(O.some("a"))]), O.some(O.none()) ) U.deepStrictEqual( productMany(O.some(O.some(1)), [O.some(O.some(2))]), O.some(O.some([1, 2])) ) }) }) describe("andThenBind", () => { it("Covariant (Option)", () => { const andThenBind = _.andThenBind(O.Applicative) U.deepStrictEqual(pipe(O.some({ a: 1 }), andThenBind("b", O.none())), O.none()) U.deepStrictEqual(pipe(O.some({ a: 1 }), andThenBind("b", O.some(2))), O.some({ a: 1, b: 2 })) }) it("Contravariant (Predicate)", () => { const p = pipe( P.Do, P.andThenBind("x", String.isString), P.andThenBind("y", Number.isNumber) ) U.deepStrictEqual(p({ x: "a", y: 1 }), true) U.deepStrictEqual(p({ x: "a", y: "x" }), false) }) }) describe("appendElement", () => { it("Covariant (Option)", () => { const appendElement = _.appendElement(O.SemiProduct) U.deepStrictEqual(pipe(O.some([1, 2]), appendElement(O.none())), O.none()) expect(pipe(O.some([1, 2]), appendElement(O.some(3)))).toEqual(O.some([1, 2, 3])) }) it("Contravariant (Predicate)", () => { const appendElement = _.appendElement(P.SemiProduct) const p = pipe(P.tuple(String.isString, String.isString), appendElement(Number.isNumber)) U.deepStrictEqual(p(["a", "b", 3]), true) U.deepStrictEqual(p(["a", "b", "c"]), false) U.deepStrictEqual(p([1, "b", 1]), false) }) }) describe("nonEmptyTuple", () => { it("Covariant (Option)", () => { const nonEmptyTuple = _.nonEmptyTuple(O.SemiProduct) expect(nonEmptyTuple(O.some("a"))).toEqual(O.some(["a"])) expect( nonEmptyTuple(O.some("a"), O.some(1), O.some(true)) ).toEqual( O.some(["a", 1, true]) ) U.deepStrictEqual(nonEmptyTuple(O.some("a"), O.some(1), O.none()), O.none()) }) it("Invariant (Semigroup)", () => { const nonEmptyTuple = _.nonEmptyTuple(semigroup.SemiProduct) const S = nonEmptyTuple(String.Semigroup, Number.SemigroupSum) U.deepStrictEqual(S.combine(["a", 2], ["b", 3]), ["ab", 5]) }) it("Contravariant (Predicate)", () => { const nonEmptyTuple = _.nonEmptyTuple(P.SemiProduct) const p = nonEmptyTuple(String.isString, Number.isNumber, Boolean.isBoolean) U.deepStrictEqual(p(["a", 1, true]), true) U.deepStrictEqual(p(["a", 1, "b"]), false) }) }) describe("nonEmptyStruct", () => { it("Covariant (Option)", () => { const nonEmptyStruct = _.nonEmptyStruct(O.Product) U.deepStrictEqual(nonEmptyStruct({ a: O.some("a") }), O.some({ a: "a" })) U.deepStrictEqual( nonEmptyStruct({ a: O.some("a"), b: O.some(1), c: O.some(true) }), O.some({ a: "a", b: 1, c: true }) ) U.deepStrictEqual( nonEmptyStruct({ a: O.some("a"), b: O.some(1), c: O.none() }), O.none() ) }) it("Invariant (Semigroup)", () => { const nonEmptyStruct = _.nonEmptyStruct(semigroup.Product) const S = nonEmptyStruct({ x: String.Semigroup, y: Number.SemigroupSum }) U.deepStrictEqual(S.combine({ x: "a", y: 2 }, { x: "b", y: 3 }), { x: "ab", y: 5 }) }) it("Contravariant (Predicate)", () => { const nonEmptyStruct = _.nonEmptyStruct(P.Product) const p = nonEmptyStruct({ x: String.isString, y: Number.isNumber, z: Boolean.isBoolean }) U.deepStrictEqual(p({ x: "a", y: 1, z: true }), true) U.deepStrictEqual(p({ x: "a", y: 1, z: "b" }), false) }) }) }) ================================================ FILE: test/typeclass/Semigroup.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as Number from "@fp-ts/core/Number" import * as String from "@fp-ts/core/String" import * as order from "@fp-ts/core/typeclass/Order" import * as _ from "@fp-ts/core/typeclass/Semigroup" import * as U from "../util" describe("Semigroup", () => { it("exports", () => { expect(_.Invariant).exist }) it("reverse", () => { const S = _.reverse(String.Semigroup) U.deepStrictEqual(S.combine("a", "b"), "ba") U.deepStrictEqual(S.combineMany("a", []), "a") U.deepStrictEqual(S.combineMany("a", ["b"]), "ba") U.deepStrictEqual(S.combineMany("a", ["b", "c", "d"]), "dcba") }) it("constant", () => { const S = _.constant("-") U.deepStrictEqual(S.combine("a", "b"), "-") U.deepStrictEqual(S.combineMany("a", []), "-") U.deepStrictEqual(S.combineMany("a", ["b", "c", "d"]), "-") }) it("intercalate", () => { const S = pipe(String.Semigroup, _.intercalate("|")) U.deepStrictEqual(S.combine("a", "b"), "a|b") U.deepStrictEqual(S.combineMany("a", []), "a") U.deepStrictEqual(S.combineMany("a", ["b"]), "a|b") U.deepStrictEqual(S.combineMany("a", ["b", "c", "d"]), "a|b|c|d") }) describe("min", () => { it("should return the minimum", () => { const S = _.min(Number.Order) U.deepStrictEqual(S.combineMany(1, []), 1) U.deepStrictEqual(S.combineMany(1, [3, 2]), 1) }) it("should return the last minimum", () => { type Item = { a: number } const A = _.min(pipe(Number.Order, order.contramap((_: Item) => _.a))) const item: Item = { a: 1 } U.strictEqual(A.combineMany({ a: 2 }, [{ a: 1 }, item]), item) U.strictEqual(A.combineMany(item, []), item) }) }) describe("max", () => { it("should return the maximum", () => { const S = _.max(Number.Order) U.deepStrictEqual(S.combineMany(1, []), 1) U.deepStrictEqual(S.combineMany(1, [3, 2]), 3) }) it("should return the last minimum", () => { type Item = { a: number } const S = _.max(pipe(Number.Order, order.contramap((_: Item) => _.a))) const item: Item = { a: 2 } U.strictEqual(S.combineMany({ a: 1 }, [{ a: 2 }, item]), item) U.strictEqual(S.combineMany(item, []), item) }) }) it("first", () => { const S = _.first() U.deepStrictEqual(S.combine(1, 2), 1) U.deepStrictEqual(S.combineMany(1, []), 1) U.deepStrictEqual(S.combineMany(1, [2, 3, 4, 5, 6]), 1) }) it("last", () => { const S = _.last() U.deepStrictEqual(S.combine(1, 2), 2) U.deepStrictEqual(S.combineMany(1, []), 1) U.deepStrictEqual(S.combineMany(1, [2, 3, 4, 5, 6]), 6) }) it("imap", () => { const imap = _.imap const S1 = imap((s: string) => [s], ([s]) => s)(String.Semigroup) U.deepStrictEqual(S1.combine(["a"], ["b"]), ["ab"]) U.deepStrictEqual(S1.combineMany(["a"], []), ["a"]) U.deepStrictEqual(S1.combineMany(["a"], [["b"]]), ["ab"]) U.deepStrictEqual(S1.combineMany(["a"], [["b"], ["c"]]), ["abc"]) // should handle an Iterable U.deepStrictEqual(S1.combineMany(["a"], new Set([["b"], ["c"]])), ["abc"]) const S2 = pipe(String.Semigroup, _.Invariant.imap((s: string) => [s], ([s]) => s)) U.deepStrictEqual(S2.combineMany(["a"], [["b"], ["c"]]), ["abc"]) }) it("product", () => { const S = pipe( _.SemiProduct.product( _.SemiProduct.product(String.Semigroup, Number.SemigroupSum), Number.SemigroupMultiply ), _.imap( ([[a, b], c]): [string, number, number] => [a, b, c], ([a, b, c]): [[string, number], number] => [[a, b], c] ) ) U.deepStrictEqual(S.combine(["a", 2, 3], ["b", 3, 4]), ["ab", 5, 12]) }) it("productMany", () => { const S = _.SemiProduct.productMany(String.Semigroup, [String.Semigroup, String.Semigroup]) U.deepStrictEqual(S.combine(["a", "b", "c"], ["d", "e", "f"]), ["ad", "be", "cf"]) }) it("productAll", () => { const S = _.Product.productAll([String.Semigroup, String.Semigroup]) U.deepStrictEqual(S.combine(["a1", "b1"], ["a2", "b2"]), ["a1a2", "b1b2"]) }) }) ================================================ FILE: test/typeclass/Traversable.ts ================================================ import { pipe } from "@fp-ts/core/Function" import * as O from "@fp-ts/core/Option" import * as RA from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/typeclass/Traversable" import * as U from "../util" describe("Traversable", () => { it("traverseComposition", () => { const traverse = _.traverseComposition(RA.Traversable, RA.Traversable)(O.Applicative) U.deepStrictEqual( traverse([[1, 2], [3]], (a) => (a > 0 ? O.some(a) : O.none())), O.some([[1, 2], [3]]) ) U.deepStrictEqual( traverse([[1, -2], [3]], (a) => (a > 0 ? O.some(a) : O.none())), O.none() ) }) it("traverseTap", () => { const traverseTap = _.traverseTap(RA.Traversable)(O.Applicative) U.deepStrictEqual( pipe([], traverseTap(n => n > 0 ? O.some(n) : O.none())), O.some([]) ) U.deepStrictEqual( pipe(["a", "b", "c"], traverseTap(s => s.length > 0 ? O.some(s.length) : O.none())), O.some(["a", "b", "c"]) ) U.deepStrictEqual( pipe(["a", "", "c"], traverseTap(s => s.length > 0 ? O.some(s) : O.none())), O.none() ) }) }) ================================================ FILE: test/typeclass/TraversableFilterable.ts ================================================ import * as E from "@fp-ts/core/Either" import * as O from "@fp-ts/core/Option" import * as RA from "@fp-ts/core/ReadonlyArray" import * as _ from "@fp-ts/core/typeclass/TraversableFilterable" import * as U from "../util" describe("TraversableFilterable", () => { it("traversePartitionMap", () => { const traversePartitionMap: ( self: ReadonlyArray, f: (a: A) => O.Option> ) => O.Option<[ReadonlyArray, ReadonlyArray]> = _.traversePartitionMap({ ...RA.Traversable, ...RA.Covariant, ...RA.Filterable })(O.Applicative) const f = (s: string) => s.length > 1 ? O.some(E.right(s)) : s.length > 0 ? O.some(E.left(s)) : O.none() assert.deepStrictEqual(traversePartitionMap([], f), O.some([[], []])) assert.deepStrictEqual(traversePartitionMap([""], f), O.none()) assert.deepStrictEqual(traversePartitionMap(["a"], f), O.some([["a"], []])) assert.deepStrictEqual(traversePartitionMap(["aa"], f), O.some([[], ["aa"]])) assert.deepStrictEqual(traversePartitionMap(["aa", "a", ""], f), O.none()) assert.deepStrictEqual( traversePartitionMap(["aa", "a", "aaa"], f), O.some([["a"], ["aa", "aaa"]]) ) }) it("traverseFilterMap", () => { const traverseFilterMap: ( self: ReadonlyArray, f: (a: A) => O.Option> ) => O.Option> = _.traverseFilterMap({ ...RA.Traversable, ...RA.Filterable })(O.Applicative) const f = (s: string) => s.length > 1 ? O.some(O.some(s)) : s.length > 0 ? O.some(O.none()) : O.none() assert.deepStrictEqual(traverseFilterMap([], f), O.some([])) assert.deepStrictEqual(traverseFilterMap([""], f), O.none()) assert.deepStrictEqual(traverseFilterMap(["a"], f), O.some([])) assert.deepStrictEqual(traverseFilterMap(["aa"], f), O.some(["aa"])) assert.deepStrictEqual(traverseFilterMap(["aa", "a", ""], f), O.none()) assert.deepStrictEqual( traverseFilterMap(["aa", "a", "aaa"], f), O.some(["aa", "aaa"]) ) }) it("traverseFilter", () => { const traverseFilter = _.traverseFilter( RA.TraversableFilterable )(O.Applicative) const f = traverseFilter((s: string) => s.length > 2 ? O.some(false) : s.length > 1 ? O.some(true) : O.none() ) U.deepStrictEqual(f([]), O.some([])) U.deepStrictEqual(f(["a"]), O.none()) U.deepStrictEqual(f(["a", "aa"]), O.none()) U.deepStrictEqual(f(["aa"]), O.some(["aa"])) U.deepStrictEqual(f(["aaa"]), O.some([])) U.deepStrictEqual(f(["aaa", "aa"]), O.some(["aa"])) }) it("traversePartition", () => { const traversePartition = _.traversePartition( RA.TraversableFilterable )(O.Applicative) const f = traversePartition((s: string) => s.length > 2 ? O.some(false) : s.length > 1 ? O.some(true) : O.none() ) expect(f([])).toEqual(O.some([[], []])) expect(f(["a"])).toEqual(O.none()) expect(f(["a", "aa"])).toEqual(O.none()) expect(f(["aa"])).toEqual(O.some([[], ["aa"]])) expect(f(["aaa"])).toEqual(O.some([["aaa"], []])) expect(f(["aaa", "aa"])).toEqual(O.some([["aaa"], ["aa"]])) }) }) ================================================ FILE: test/util.ts ================================================ import { structural } from "@fp-ts/core/internal/effect" import * as assert from "assert" export const deepStrictEqual = (actual: A, expected: A) => { assert.deepStrictEqual(actual, expected) } export const strictEqual = (actual: A, expected: A) => { assert.strictEqual(actual, expected) } export const double = (n: number): number => n * 2 export const ownKeys = (o: object): ReadonlyArray => (Object.keys(o) as ReadonlyArray).concat(Object.getOwnPropertySymbols(o)) export const isStructural = (u: unknown) => typeof u === "object" && u != null && structural in u ================================================ FILE: tsconfig.base.json ================================================ { "compilerOptions": { "moduleDetection": "force", "composite": true, "downlevelIteration": true, "resolveJsonModule": true, "esModuleInterop": true, "declaration": true, "skipLibCheck": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "preserveSymlinks": true, "moduleResolution": "node", "noEmit": false, "lib": ["ES2021"], "sourceMap": true, "declarationMap": true, "strict": true, "noImplicitReturns": false, "noUnusedLocals": true, "noUnusedParameters": false, "noFallthroughCasesInSwitch": true, "noEmitOnError": false, "noErrorTruncation": false, "allowJs": false, "checkJs": false, "forceConsistentCasingInFileNames": true, "suppressImplicitAnyIndexErrors": true, "stripInternal": true, "noImplicitAny": true, "noImplicitThis": true, "noUncheckedIndexedAccess": false, "strictNullChecks": true, "baseUrl": ".", "target": "ES2021", "module": "ES6", "incremental": true, "removeComments": false, "paths": { "@fp-ts/core": ["./src/index.ts"], "@fp-ts/core/test/*": ["./test/*"], "@fp-ts/core/examples/*": ["./examples/*"], "@fp-ts/core/*": ["./src/*"] }, "plugins": [{ "name": "@effect/language-service" }] }, "include": [], "exclude": ["node_modules", "build", "lib"] } ================================================ FILE: tsconfig.build-test.json ================================================ { "extends": "./tsconfig.base.json", "compilerOptions": { "tsBuildInfoFile": "build/tsbuildinfo/test.tsbuildinfo", "rootDir": "./", "noEmit": true, "types": ["vitest/globals", "node"] }, "include": ["test/**/*.ts", "src/**/*.ts"] } ================================================ FILE: tsconfig.build.json ================================================ { "extends": "./tsconfig.base.json", "compilerOptions": { "outDir": "build/esm", "declarationDir": "build/dts", "tsBuildInfoFile": "build/tsbuildinfo/esm.tsbuildinfo", "rootDir": "src" }, "include": ["src/**/*.ts"] } ================================================ FILE: tsconfig.eslint.json ================================================ { "compilerOptions": { "noEmit": true, "allowJs": true, "baseUrl": "." }, "include": [ "./src/**/*.ts", "./test/**/*.ts", "./dtslint/**/*.ts", "./examples/**/*.ts", "./vitest.config.ts", "./.eslintrc.cjs" ] } ================================================ FILE: tsconfig.json ================================================ { "extends": "./tsconfig.base.json", "references": [ { "path": "./tsconfig.build.json" }, { "path": "./tsconfig.build-test.json" } ] } ================================================ FILE: tsconfig.madge.json ================================================ { "compilerOptions": { "noEmit": true, "allowJs": true, "baseUrl": ".", "paths": { "@fp-ts/core": ["./build/esm/index.js"], "@fp-ts/core/*": ["./build/esm/*"] } }, "include": ["./build/esm/**/*.js"] } ================================================ FILE: vitest.config.ts ================================================ /// import path from "path" import { defineConfig } from "vite" export default defineConfig({ test: { include: ["./test/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], exclude: [ "./test/util.ts", "./test/limbo/*.ts" ], globals: true }, resolve: { alias: { "@fp-ts/core/test": path.resolve(__dirname, "/test"), "@fp-ts/core": path.resolve(__dirname, "/src") } } })