1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-12-09 23:11:40 +02:00

Compare commits

...

66 Commits

Author SHA1 Message Date
Dr. Carsten Leue
b2705e3adf fix: disable to version updates
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 11:39:17 +01:00
renovate[bot]
b232183e47 chore(config): migrate config renovate.json (#143)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-06 11:26:23 +01:00
Dr. Carsten Leue
0f9f89f16d doc: improve documentation
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 11:20:50 +01:00
Dr. Carsten Leue
0d3a8634b1 fix: add inline annotations
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 10:54:24 +01:00
Dr. Carsten Leue
56c8f1b034 fix: fix build
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 09:57:58 +01:00
Dr. Carsten Leue
bad86cd769 fix: try to fix build
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 09:50:03 +01:00
Dr. Carsten Leue
d0c5f32111 fix: add go 1.25 to build matrix
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 09:43:27 +01:00
renovate[bot]
77745c1348 fix(deps): update go dependencies (#142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-06 09:39:27 +01:00
李鑫
2c96cef500 feat: add array.MonadReduce() function (#132)
Signed-off-by: lixin <lixin@dustess.com>
Co-authored-by: lixin <lixin@dustess.com>
2025-11-06 09:28:20 +01:00
Carsten Leue
3385c705dc Implement v2 using type aliases (#141)
* fix: initial checkin of v2

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: slowly migrate IO

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate MonadTraverseArray and TraverseArray

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate traversal

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: complete migration of IO

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: migrate ioeither

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: refactorY

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: next step in migration

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: adjust IO generation code

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: get rid of more IO methods

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: get rid of more IO

* fix: convert iooption

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: convert reader

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: convert a bit of reader

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: new build script

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: cleanup

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: reformat

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: simplify

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: some cleanup

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: adjust Pair to Haskell semantic

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: documentation and testcases

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: some performance optimizations

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: remove coverage

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

* fix: better doc

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>

---------

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-06 09:27:00 +01:00
ibm-mend-app[bot]
7874859c4b Add .whitesource configuration file (#140)
Co-authored-by: ibm-mend-app[bot] <142626574+ibm-mend-app[bot]@users.noreply.github.com>
2025-11-06 09:22:43 +01:00
renovate[bot]
25e3d1d85c fix(deps): update module github.com/stretchr/testify to v1.11.1 (#139)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-27 22:40:53 +00:00
renovate[bot]
d7ff994fb7 fix(deps): update module github.com/stretchr/testify to v1.11.0 (#138)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-25 01:44:33 +00:00
renovate[bot]
1cdca552b2 chore(deps): update actions/checkout action to v4.3.0 (#137)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-11 18:38:27 +00:00
renovate[bot]
73480ca030 fix(deps): update module github.com/urfave/cli/v2 to v2.27.7 (#136)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-14 10:26:20 +00:00
renovate[bot]
734e2b0055 chore(deps): update actions/setup-node action to v4.4.0 (#134)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-14 10:54:36 +00:00
renovate[bot]
4c28859e89 chore(deps): update actions/setup-node action to v4.3.0 (#131)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 06:44:51 +00:00
renovate[bot]
a516849c07 fix(deps): update module github.com/urfave/cli/v2 to v2.27.6 (#130)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 22:50:57 +00:00
sarabande
29200d34dc docs(iterator): update Cycle function documentation (#128) 2025-03-02 00:21:41 +01:00
renovate[bot]
7a3989989b chore(deps): update actions/setup-node action to v4.2.0 (#127)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-27 22:04:25 +00:00
renovate[bot]
6a6d53f025 fix(deps): update module github.com/stretchr/testify to v1.10.0 (#126)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-23 15:33:28 +00:00
renovate[bot]
078da752cd chore(deps): update actions/setup-node action to v4.1.0 2024-10-24 20:12:43 +00:00
renovate[bot]
1a489fde27 chore(deps): update actions/checkout action to v4.2.2 2024-10-23 19:31:36 +00:00
renovate[bot]
a135b2acae fix(deps): update module github.com/urfave/cli/v2 to v2.27.5 2024-10-13 20:09:16 +00:00
renovate[bot]
9e9dfa1f5f chore(deps): update actions/checkout action to v4.2.1 2024-10-07 22:39:01 +00:00
renovate[bot]
dd87ea12b3 chore(deps): update actions/checkout action to v4.2.0 2024-09-25 21:29:08 +00:00
renovate[bot]
5fc0d18c97 chore(deps): update actions/setup-node action to v4.0.4 2024-09-19 20:14:45 +00:00
CRaLFa
76c1297576 fix typos in README and comment (#119)
Signed-off-by: CRaLFa <minami.smd@gmail.com>
2024-09-12 09:40:19 +02:00
Dr. Carsten Leue
68aeb4c725 fix: script
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-08-27 16:57:59 +02:00
Dr. Carsten Leue
53f3fa1828 fix: semantic release
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-08-27 16:43:21 +02:00
Dr. Carsten Leue
97e1e4d92d fix: add test for go 1.23
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-08-27 16:39:52 +02:00
Dr. Carsten Leue
ec57d5cd4a fix: go mod tidy
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-08-27 16:37:22 +02:00
renovate[bot]
0ae5b43724 fix(deps): update module github.com/urfave/cli/v2 to v2.27.4 2024-08-11 19:12:08 +00:00
renovate[bot]
e73e14c0ae fix(deps): update module github.com/urfave/cli/v2 to v2.27.3 2024-07-25 03:34:59 +00:00
renovate[bot]
325bc376f9 chore(deps): update actions/setup-node action to v4.0.3 2024-07-09 20:06:20 +00:00
Dr. Carsten Leue
f646ace9fe chore: git mod tidy
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-06-24 09:24:15 +02:00
Laglangyue
9f8161fbc1 chore: ignore fp-go file for unix machine (#115)
Signed-off-by: tangjiafu <tangjiafu@apache.org>
Co-authored-by: tangjiafu <tangjiafu@apache.org>
2024-06-24 09:22:40 +02:00
renovate[bot]
1c4f2c0403 chore(deps): update actions/checkout action to v4.1.7 2024-06-13 02:39:23 +00:00
Dr. Carsten Leue
3b3b80aed0 fix: some more tests
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-05-27 11:54:04 +02:00
Dr. Carsten Leue
fdff4e4735 fix: more tests
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-05-26 16:23:40 +02:00
Dr. Carsten Leue
391754e5a6 fix: more testing
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-05-25 15:41:32 +02:00
Dr. Carsten Leue
598a7b261b fix: add more tests
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-05-24 23:19:24 +02:00
Dr. Carsten Leue
f0f1a48965 fix: do not use v8
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-05-24 21:43:36 +02:00
Dr. Carsten Leue
e39e5e0920 fix: add missing Fold to ReaderIOEither
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-05-24 12:55:20 +02:00
李鑫
9c7a5bb24b fix: string format of pair.pairString() (#113)
Signed-off-by: lixin <lixin@dustess.com>
Co-authored-by: lixin <lixin@dustess.com>
2024-05-20 21:48:24 +02:00
renovate[bot]
89bda4f500 chore(deps): update actions/checkout action to v4.1.6 2024-05-17 05:37:34 +00:00
renovate[bot]
15dffb3256 chore(deps): update actions/checkout action to v4.1.5 2024-05-09 02:10:28 +00:00
t-hg
95fbd93696 Fix typo (#106)
Opertator -> Operator
2024-04-29 08:47:26 +02:00
renovate[bot]
6e0d5704bc fix(deps): update module github.com/urfave/cli/v2 to v2.27.2 2024-04-27 19:09:18 +00:00
renovate[bot]
0aa95e656b chore(deps): update actions/checkout action to v4.1.4 2024-04-25 18:08:51 +00:00
renovate[bot]
b3544a32fc chore(deps): update actions/checkout action to v4.1.3 2024-04-22 16:18:16 +00:00
Dr. Carsten Leue
9ad9b4a9bf fix: update dependencies
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-03-20 21:43:03 +01:00
Francis Zhou
74763bdadc correct the generic type for FromIO (#104)
Signed-off-by: francis <francis.tm@me.com>
2024-03-11 16:18:30 +01:00
renovate[bot]
9aa2ae041f fix(deps): update module github.com/stretchr/testify to v1.9.0 2024-03-02 18:23:13 +00:00
Dr. Carsten Leue
d356fa3c89 fix: more auto generated templates fo DI
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-29 16:27:23 +01:00
Dr. Carsten Leue
f61507254d fix: small changes to readall
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-22 13:58:39 +01:00
Dr. Carsten Leue
85f8071c75 fix: add ToWriter
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-20 16:10:58 +01:00
Dr. Carsten Leue
76ae6f2bec fix: more functions for StateReaderIOEither
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-19 14:34:35 +01:00
Dr. Carsten Leue
f4f4fb306c fix: add conversions for StateReaderIOEither
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-18 21:45:15 +01:00
Dr. Carsten Leue
747f477a96 fix: next small step towards StateReaderIOEither
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-18 21:01:39 +01:00
Dr. Carsten Leue
045f4e8849 fix: add basic implementation of StateReaderIOEither
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-17 23:06:52 +01:00
Dr. Carsten Leue
65e09e0e90 fix: expose Monad and Pointed for IOEither
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-16 15:54:40 +01:00
Dr. Carsten Leue
6ab6ff094b fix: correct sequence order of TraverseArraySeq for IO
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-16 15:46:12 +01:00
Dr. Carsten Leue
e6e35d643c fix: update doc
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-13 14:25:56 +01:00
Dr. Carsten Leue
01d490b710 fix: add State monad
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-13 14:23:33 +01:00
Dr. Carsten Leue
01786a054b fix: refactor Writer monad
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2024-02-13 10:44:57 +01:00
855 changed files with 106686 additions and 402 deletions

View File

@@ -4,9 +4,7 @@ on:
push:
branches:
- main
pull_request:
workflow_dispatch:
inputs:
dryRun:
@@ -15,35 +13,80 @@ on:
required: false
env:
# Currently no way to detect automatically
DEFAULT_BRANCH: main
GO_VERSION: 1.21.6 # renovate: datasource=golang-version depName=golang
NODE_VERSION: 20
LATEST_GO_VERSION: 1.25.2 # renovate: datasource=golang-version depName=golang
NODE_VERSION: 24
DRY_RUN: true
jobs:
build:
build-v1:
name: Build v1 (Go ${{ matrix.go-version }})
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [ '1.20.x', '1.21.x', '1.22.x']
go-version: ['1.20.x', '1.21.x', '1.22.x', '1.23.x', '1.24.x', '1.25.x']
fail-fast: false # Continue with other versions if one fails
steps:
# full checkout for semantic-release
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with:
fetch-depth: 0
- name: Set up go ${{ matrix.go-version }}
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
-
name: Tests
cache: true # Enable Go module caching
- name: Run tests
run: |
go mod tidy
go test -v ./...
go test -v -race -coverprofile=coverage.txt -covermode=atomic ./...
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v5
# with:
# file: ./coverage.txt
# flags: v1,go-${{ matrix.go-version }}
# name: v1-go-${{ matrix.go-version }}
# fail_ci_if_error: false
# env:
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
build-v2:
name: Build v2 (Go ${{ matrix.go-version }})
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ['1.24.x', '1.25.x']
steps:
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with:
fetch-depth: 0
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: true # Enable Go module caching
- name: Run tests
run: |
cd v2
go mod tidy
go test -v -race -coverprofile=coverage.txt -covermode=atomic ./...
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v5
# with:
# file: ./v2/coverage.txt
# flags: v2,go-${{ matrix.go-version }}
# name: v2-go-${{ matrix.go-version }}
# fail_ci_if_error: false
# env:
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
release:
needs: [build]
name: Release
needs:
- build-v1
- build-v2
if: github.repository == 'IBM/fp-go' && github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 15
@@ -51,38 +94,37 @@ jobs:
contents: write
issues: write
pull-requests: write
steps:
# full checkout for semantic-release
- name: Full checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with:
fetch-depth: 0
- name: Set up Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Set up go ${{env.GO_VERSION}}
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{env.GO_VERSION}}
go-version: ${{ env.LATEST_GO_VERSION }}
cache: true # Enable Go module caching
# The dry-run evaluation is only made for non PR events. Manual trigger w/dryRun true, main branch and any tagged branches will set DRY run to false
- name: Check dry run
- name: Determine release mode
id: release-mode
run: |
if [[ "${{github.event_name}}" == "workflow_dispatch" && "${{ github.event.inputs.dryRun }}" != "true" ]]; then
echo "DRY_RUN=false" >> $GITHUB_ENV
elif [[ "${{github.ref}}" == "refs/heads/${{env.DEFAULT_BRANCH}}" ]]; then
if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.dryRun }}" != "true" ]]; then
echo "DRY_RUN=false" >> $GITHUB_ENV
elif [[ "${{github.ref}}" =~ ^refs/heads/v[0-9]+(\.[0-9]+)?$ ]]; then
elif [[ "${{ github.ref }}" == "refs/heads/${{ env.DEFAULT_BRANCH }}" ]]; then
echo "DRY_RUN=false" >> $GITHUB_ENV
elif [[ "${{ github.ref }}" =~ ^refs/heads/v[0-9]+(\.[0-9]+)?$ ]]; then
echo "DRY_RUN=false" >> $GITHUB_ENV
fi
- name: Semantic Release
- name: Run semantic release
run: |
npx -p conventional-changelog-conventionalcommits -p semantic-release semantic-release --dry-run ${{env.DRY_RUN}}
npx -p conventional-changelog-conventionalcommits -p semantic-release semantic-release --dry-run ${{ env.DRY_RUN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
fp-go.exe
fp-go
main.exe
build/
.idea

3
.whitesource Normal file
View File

@@ -0,0 +1,3 @@
{
"settingsInheritedFrom": "ibm-mend-config/mend-config@main"
}

346
README.md
View File

@@ -1,207 +1,311 @@
# Functional programming library for golang
# fp-go: Functional Programming Library for Go
**🚧 Work in progress! 🚧** Despite major version 1 because of <https://github.com/semantic-release/semantic-release/issues/1507>. Trying to not make breaking changes, but devil is in the details.
[![Go Reference](https://pkg.go.dev/badge/github.com/IBM/fp-go.svg)](https://pkg.go.dev/github.com/IBM/fp-go)
**🚧 Work in progress! 🚧** Despite major version 1 (due to [semantic-release limitations](https://github.com/semantic-release/semantic-release/issues/1507)), we're working to minimize breaking changes.
![logo](resources/images/logo.png)
This library is strongly influenced by the awesome [fp-ts](https://github.com/gcanti/fp-ts).
A comprehensive functional programming library for Go, strongly influenced by the excellent [fp-ts](https://github.com/gcanti/fp-ts) library for TypeScript.
## Getting started
## 📚 Table of Contents
- [Getting Started](#-getting-started)
- [Design Goals](#-design-goals)
- [Core Concepts](#-core-concepts)
- [Comparison to Idiomatic Go](#comparison-to-idiomatic-go)
- [Implementation Notes](#implementation-notes)
- [Common Operations](#common-operations)
- [Resources](#-resources)
## 🚀 Getting Started
### Installation
```bash
go get github.com/IBM/fp-go
```
Refer to the [samples](./samples/).
### Quick Example
Find API documentation [here](https://pkg.go.dev/github.com/IBM/fp-go)
```go
import (
"errors"
"github.com/IBM/fp-go/either"
"github.com/IBM/fp-go/function"
)
## Design Goal
// Pure function that can fail
func divide(a, b int) either.Either[error, int] {
if b == 0 {
return either.Left[int](errors.New("division by zero"))
}
return either.Right[error](a / b)
}
This library aims to provide a set of data types and functions that make it easy and fun to write maintainable and testable code in golang. It encourages the following patterns:
// Compose operations safely
result := function.Pipe2(
divide(10, 2),
either.Map(func(x int) int { return x * 2 }),
either.GetOrElse(func() int { return 0 }),
)
// result = 10
```
- write many small, testable and pure functions, i.e. functions that produce output only depending on their input and that do not execute side effects
- offer helpers to isolate side effects into lazily executed functions (IO)
- expose a consistent set of composition to create new functions from existing ones
- for each data type there exists a small set of composition functions
- these functions are called the same across all data types, so you only have to learn a small number of function names
- the semantic of functions of the same name is consistent across all data types
### Resources
### How does this play with the [🧘🏽 Zen Of Go](https://the-zen-of-go.netlify.app/)?
- 📖 [API Documentation](https://pkg.go.dev/github.com/IBM/fp-go)
- 💡 [Code Samples](./samples/)
- 🆕 [V2 Documentation](./v2/README.md) (requires Go 1.24+)
#### 🧘🏽 Each package fulfils a single purpose
## 🎯 Design Goals
✔️ Each of the top level packages (e.g. Option, Either, ReaderIOEither, ...) fulfils the purpose of defining the respective data type and implementing the set of common operations for this data type.
This library aims to provide a set of data types and functions that make it easy and fun to write maintainable and testable code in Go. It encourages the following patterns:
#### 🧘🏽 Handle errors explicitly
### Core Principles
✔️ The library makes a clear distinction between that operations that cannot fail by design and operations that can fail. Failure is represented via the `Either` type and errors are handled explicitly by using `Either`'s monadic set of operations.
- **Pure Functions**: Write many small, testable, and pure functions that produce output only depending on their input and execute no side effects
- **Side Effect Isolation**: Isolate side effects into lazily executed functions using the `IO` monad
- **Consistent Composition**: Expose a consistent set of composition functions across all data types
- Each data type has a small set of composition functions
- Functions are named consistently across all data types
- Semantics of same-named functions are consistent across data types
#### 🧘🏽 Return early rather than nesting deeply
### 🧘🏽 Alignment with the Zen of Go
✔️ We recommend to implement simple, small functions that implement one feature and that would typically not invoke other functions. Interaction with other functions is done by function composition and the composition makes sure to run one function after the other. In the error case the `Either` monad makes sure to skip the error path.
This library respects and aligns with [The Zen of Go](https://the-zen-of-go.netlify.app/):
#### 🧘🏽 Leave concurrency to the caller
| Principle | Alignment | Explanation |
|-----------|-----------|-------------|
| 🧘🏽 Each package fulfills a single purpose | ✔️ | Each top-level package (Option, Either, ReaderIOEither, etc.) defines one data type and its operations |
| 🧘🏽 Handle errors explicitly | ✔️ | Clear distinction between operations that can/cannot fail; failures represented via `Either` type |
| 🧘🏽 Return early rather than nesting deeply | ✔️ | Small, focused functions composed together; `Either` monad handles error paths automatically |
| 🧘🏽 Leave concurrency to the caller | ✔️ | Pure functions are synchronous; I/O operations are asynchronous by default |
| 🧘🏽 Before you launch a goroutine, know when it will stop | 🤷🏽 | Library doesn't start goroutines; Task monad supports cancellation via context |
| 🧘🏽 Avoid package level state | ✔️ | No package-level state anywhere |
| 🧘🏽 Simplicity matters | ✔️ | Small, consistent interface across data types; focus on business logic |
| 🧘🏽 Write tests to lock in behaviour | 🟡 | Programming pattern encourages testing; library has growing test coverage |
| 🧘🏽 If you think it's slow, first prove it with a benchmark | ✔️ | Performance claims should be backed by benchmarks |
| 🧘🏽 Moderation is a virtue | ✔️ | No custom goroutines or expensive synchronization; atomic counters for coordination |
| 🧘🏽 Maintainability counts | ✔️ | Small, concise operations; pure functions with clear type signatures |
✔️ All pure are synchronous by default. The I/O operations are asynchronous per default.
## 💡 Core Concepts
#### 🧘🏽 Before you launch a goroutine, know when it will stop
### Data Types
🤷🏽 This is left to the user of the library since the library itself will not start goroutines on its own. The Task monad offers support for cancellation via the golang context, though.
The library provides several key functional data types:
#### 🧘🏽 Avoid package level state
- **`Option[A]`**: Represents an optional value (Some or None)
- **`Either[E, A]`**: Represents a value that can be one of two types (Left for errors, Right for success)
- **`IO[A]`**: Represents a lazy computation that produces a value
- **`IOEither[E, A]`**: Represents a lazy computation that can fail
- **`Reader[R, A]`**: Represents a computation that depends on an environment
- **`ReaderIOEither[R, E, A]`**: Combines Reader, IO, and Either for effectful computations with dependencies
- **`Task[A]`**: Represents an asynchronous computation
- **`State[S, A]`**: Represents a stateful computation
✔️ No package level state anywhere, this would be a significant anti-pattern
### Monadic Operations
#### 🧘🏽 Simplicity matters
All data types support common monadic operations:
✔️ The library is simple in the sense that it offers a small, consistent interface to a variety of data types. Users can concentrate on implementing business logic rather than dealing with low level data structures.
#### 🧘🏽 Write tests to lock in the behaviour of your package’s API
🟡 The programming pattern suggested by this library encourages writing test cases. The library itself also has a growing number of tests, but not enough, yet. TBD
#### 🧘🏽 If you think it’s slow, first prove it with a benchmark
✔️ Absolutely. If you think the function composition offered by this library is too slow, please provide a benchmark.
#### 🧘🏽 Moderation is a virtue
✔️ The library does not implement its own goroutines and also does not require any expensive synchronization primitives. Coordination of IO operations is implemented via atomic counters without additional primitives.
#### 🧘🏽 Maintainability counts
✔️ Code that consumes this library is easy to maintain because of the small and concise set of operations exposed. Also the suggested programming paradigm to decompose an application into small functions increases maintainability, because these functions are easy to understand and if they are pure, it's often sufficient to look at the type signature to understand the purpose.
The library itself also comprises many small functions, but it's admittedly harder to maintain than code that uses it. However this asymmetry is intended because it offloads complexity from users into a central component.
- **`Map`**: Transform the value inside a context
- **`Chain`** (FlatMap): Transform and flatten nested contexts
- **`Ap`**: Apply a function in a context to a value in a context
- **`Of`**: Wrap a value in a context
- **`Fold`**: Extract a value from a context
## Comparison to Idiomatic Go
In this section we discuss how the functional APIs differ from idiomatic go function signatures and how to convert back and forth.
This section explains how functional APIs differ from idiomatic Go and how to convert between them.
### Pure functions
### Pure Functions
Pure functions are functions that take input parameters and that compute an output without changing any global state and without mutating the input parameters. They will always return the same output for the same input.
Pure functions take input parameters and compute output without changing global state or mutating inputs. They always return the same output for the same input.
#### Without Errors
If your pure function does not return an error, the idiomatic signature is just fine and no changes are required.
If your pure function doesn't return an error, the idiomatic signature works as-is:
```go
func add(a, b int) int {
return a + b
}
```
#### With Errors
If your pure function can return an error, then it will have a `(T, error)` return value in idiomatic go. In functional style the return value is [Either[error, T]](https://pkg.go.dev/github.com/IBM/fp-go/either) because function composition is easier with such a return type. Use the `EitherizeXXX` methods in ["github.com/IBM/fp-go/either"](https://pkg.go.dev/github.com/IBM/fp-go/either) to convert from idiomatic to functional style and `UneitherizeXXX` to convert from functional to idiomatic style.
**Idiomatic Go:**
```go
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
```
### Effectful functions
**Functional Style:**
```go
func divide(a, b int) either.Either[error, int] {
if b == 0 {
return either.Left[int](errors.New("division by zero"))
}
return either.Right[error](a / b)
}
```
An effectful function (or function with a side effect) is one that changes data outside the scope of the function or that does not always produce the same output for the same input (because it depends on some external, mutable state). There is no special way in idiomatic go to identify such a function other than documentation. In functional style we represent them as functions that do not take an input but that produce an output. The base type for these functions is [IO[T]](https://pkg.go.dev/github.com/IBM/fp-go/io) because in many cases such functions represent `I/O` operations.
**Conversion:**
- Use `either.EitherizeXXX` to convert from idiomatic to functional style
- Use `either.UneitherizeXXX` to convert from functional to idiomatic style
### Effectful Functions
An effectful function changes data outside its scope or doesn't always produce the same output for the same input.
#### Without Errors
If your effectful function does not return an error, the functional signature is [IO[T]](https://pkg.go.dev/github.com/IBM/fp-go/io)
**Functional signature:** `IO[T]`
```go
func getCurrentTime() io.IO[time.Time] {
return func() time.Time {
return time.Now()
}
}
```
#### With Errors
If your effectful function can return an error, the functional signature is [IOEither[error, T]](https://pkg.go.dev/github.com/IBM/fp-go/ioeither). Use `EitherizeXXX` from ["github.com/IBM/fp-go/ioeither"](https://pkg.go.dev/github.com/IBM/fp-go/ioeither) to convert an idiomatic go function to functional style.
**Functional signature:** `IOEither[error, T]`
```go
func readFile(path string) ioeither.IOEither[error, []byte] {
return func() either.Either[error, []byte] {
data, err := os.ReadFile(path)
if err != nil {
return either.Left[[]byte](err)
}
return either.Right[error](data)
}
}
```
**Conversion:**
- Use `ioeither.EitherizeXXX` to convert idiomatic Go functions to functional style
### Go Context
Functions that take a [context](https://pkg.go.dev/context) are per definition effectful because they depend on the context parameter that is designed to be mutable (it can e.g. be used to cancel a running operation). Furthermore in idiomatic go the parameter is typically passed as the first parameter to a function.
Functions that take a `context.Context` are effectful because they depend on mutable context.
In functional style we isolate the [context](https://pkg.go.dev/context) and represent the nature of the effectful function as an [IOEither[error, T]](https://pkg.go.dev/github.com/IBM/fp-go/ioeither). The resulting type is [ReaderIOEither[T]](https://pkg.go.dev/github.com/IBM/fp-go/context/readerioeither), a function taking a [context](https://pkg.go.dev/context) that returns a function without parameters returning an [Either[error, T]](https://pkg.go.dev/github.com/IBM/fp-go/either). Use the `EitherizeXXX` methods from ["github.com/IBM/fp-go/context/readerioeither"](https://pkg.go.dev/github.com/IBM/fp-go/context/readerioeither) to convert an idiomatic go function with a [context](https://pkg.go.dev/context) to functional style.
**Idiomatic Go:**
```go
func fetchData(ctx context.Context, url string) ([]byte, error) {
// implementation
}
```
**Functional Style:**
```go
func fetchData(url string) readerioeither.ReaderIOEither[context.Context, error, []byte] {
return func(ctx context.Context) ioeither.IOEither[error, []byte] {
return func() either.Either[error, []byte] {
// implementation
}
}
}
```
**Conversion:**
- Use `readerioeither.EitherizeXXX` to convert idiomatic Go functions with context to functional style
## Implementation Notes
### Generics
All monadic operations are implemented via generics, i.e. they offer a type safe way to compose operations. This allows for convenient IDE support and also gives confidence about the correctness of the composition at compile time.
All monadic operations use Go generics for type safety:
Downside is that this will result in different versions of each operation per type, these versions are generated by the golang compiler at build time (unlike type erasure in languages such as Java of TypeScript). This might lead to large binaries for codebases with many different types. If this is a concern, you can always implement type erasure on top, i.e. use the monadic operations with the `any` type as if generics were not supported. You loose type safety, but this might result in smaller binaries.
-**Pros**: Type-safe composition, IDE support, compile-time correctness
- ⚠️ **Cons**: May result in larger binaries (different versions per type)
- 💡 **Tip**: For binary size concerns, use type erasure with `any` type
### Ordering of Generic Type Parameters
In go we need to specify all type parameters of a function on the global function definition, even if the function returns a higher order function and some of the type parameters are only applicable to the higher order function. So the following is not possible:
Go requires all type parameters on the global function definition. Parameters that cannot be auto-detected come first:
```go
func Map[A, B any](f func(A) B) [R, E any]func(fa ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B]
// Map: B cannot be auto-detected, so it comes first
func Map[R, E, A, B any](f func(A) B) func(ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B]
// Ap: B cannot be auto-detected from the argument
func Ap[B, R, E, A any](fa ReaderIOEither[R, E, A]) func(ReaderIOEither[R, E, func(A) B]) ReaderIOEither[R, E, B]
```
Note that the parameters `R` and `E` are not needed by the first level of `Map` but only by the resulting higher order function. Instead we need to specify the following:
This ordering maximizes type inference where possible.
```go
func Map[R, E, A, B any](f func(A) B) func(fa ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B]
```
### Use of the ~ Operator
which overspecifies `Map` on the global scope. As a result the go compiler will not be able to auto-detect these parameters, it can only auto detect `A` and `B` since they appear in the argument of `Map`. We need to explicitly pass values for these type parameters when `Map` is being used.
Because of this limitation the order of parameters on a function matters. We want to make sure that we define those parameters that cannot be auto-detected, first, and the parameters that can be auto-detected, last. This can lead to inconsistencies in parameter ordering, but we believe that the gain in convenience is worth it. The parameter order of `Ap` is e.g. different from that of `Map`:
```go
func Ap[B, R, E, A any](fa ReaderIOEither[R, E, A]) func(fab ReaderIOEither[R, E, func(A) B]) ReaderIOEither[R, E, B]
```
because `R`, `E` and `A` can be determined from the argument to `Ap` but `B` cannot.
### Use of the [~ Operator](https://go.googlesource.com/proposal/+/master/design/47781-parameterized-go-ast.md)
The FP library attempts to be easy to consume and one aspect of this is the definition of higher level type definitions instead of having to use their low level equivalent. It is e.g. more convenient and readable to use
```go
ReaderIOEither[R, E, A]
```
than
```go
func(R) func() Either.Either[E, A]
```
although both are logically equivalent. At the time of this writing the go type system does not support generic type aliases, only generic type definition, i.e. it is not possible to write:
```go
type ReaderIOEither[R, E, A any] = RD.Reader[R, IOE.IOEither[E, A]]
```
only
Go doesn't support generic type aliases (until Go 1.24), only type definitions. The `~` operator allows generic implementations to work with compatible types:
```go
type ReaderIOEither[R, E, A any] RD.Reader[R, IOE.IOEither[E, A]]
```
This makes a big difference, because in the second case the type `ReaderIOEither[R, E, A any]` is considered a completely new type, not compatible to its right hand side, so it's not just a shortcut but a fully new type.
**Generic Subpackages:**
- Each higher-level type has a `generic` subpackage with fully generic implementations
- These are for library extensions, not end-users
- Main packages specialize generic implementations for convenience
From the implementation perspective however there is no reason to restrict the implementation to the new type, it can be generic for all compatible types. The way to express this in go is the [~](https://go.googlesource.com/proposal/+/master/design/47781-parameterized-go-ast.md) operator. This comes with some quite complicated type declarations in some cases, which undermines the goal of the library to be easy to use.
### Higher Kinded Types (HKT)
For that reason there exist sub-packages called `Generic` for all higher level types. These packages contain the fully generic implementation of the operations, preferring abstraction over usability. These packages are not meant to be used by end-users but are meant to be used by library extensions. The implementation for the convenient higher level types specializes the generic implementation for the particular higher level type, i.e. this layer does not contain any business logic but only *type magic*.
Go doesn't support HKT natively. This library addresses this by:
### Higher Kinded Types
- Introducing HKTs as individual types (e.g., `HKTA` for `HKT[A]`)
- Implementing generic algorithms in the `internal` package
- Keeping complexity hidden from end-users
Go does not support higher kinded types (HKT). Such types occur if a generic type itself is parametrized by another generic type. Example:
## Common Operations
The `Map` operation for `ReaderIOEither` is defined as:
### Map/Chain/Ap/Flap
| Operator | Parameter | Monad | Result | Use Case |
| -------- | ---------------- | --------------- | -------- | -------- |
| Map | `func(A) B` | `HKT[A]` | `HKT[B]` | Transform value in context |
| Chain | `func(A) HKT[B]` | `HKT[A]` | `HKT[B]` | Transform and flatten |
| Ap | `HKT[A]` | `HKT[func(A)B]` | `HKT[B]` | Apply function in context |
| Flap | `A` | `HKT[func(A)B]` | `HKT[B]` | Apply value to function in context |
### Example: Chaining Operations
```go
func Map[R, E, A, B any](f func(A) B) func(fa ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B]
import (
"github.com/IBM/fp-go/either"
"github.com/IBM/fp-go/function"
)
result := function.Pipe3(
either.Right[error](10),
either.Map(func(x int) int { return x * 2 }),
either.Chain(func(x int) either.Either[error, int] {
if x > 15 {
return either.Right[error](x)
}
return either.Left[int](errors.New("too small"))
}),
either.GetOrElse(func() int { return 0 }),
)
```
and in fact the equivalent operations for all other monads follow the same pattern, we could try to introduce a new type for `ReaderIOEither` (without a parameter) as a HKT, e.g. like so (made-up syntax, does not work in go):
## 📚 Resources
```go
func Map[HKT, R, E, A, B any](f func(A) B) func(HKT[R, E, A]) HKT[R, E, B]
```
- [API Documentation](https://pkg.go.dev/github.com/IBM/fp-go)
- [Code Samples](./samples/)
- [V2 Documentation](./v2/README.md) - New features in Go 1.24+
- [fp-ts](https://github.com/gcanti/fp-ts) - Original TypeScript inspiration
this would be the completely generic method signature for all possible monads. In particular in many cases it is possible to compose functions independent of the concrete knowledge of the actual `HKT`. From the perspective of a library this is the ideal situation because then a particular algorithm only has to be implemented and tested once.
## 🤝 Contributing
This FP library addresses this by introducing the HKTs as individual types, e.g. `HKT[A]` would be represented as a new generic type `HKTA`. This loses the correlation to the type `A` but allows to implement generic algorithms, at the price of readability.
Contributions are welcome! Please feel free to submit issues or pull requests.
For that reason these implementations are kept in the `internal` package. These are meant to be used by the library itself or by extensions, not by end users.
## 📄 License
## Map/Ap/Flap
The following table lists the relationship between some selected operators
| Opertator | Parameter | Monad | Result |
| -------- | ---------------- | --------------- | -------- |
| Map | `func(A) B` | `HKT[A]` | `HKT[B]` |
| Chain | `func(A) HKT[B]` | `HKT[A]` | `HKT[B]` |
| Ap | `HKT[A]` | `HKT[func(A)B]` | `HKT[B]` |
| Flap | `A` | `HKT[func(A)B]` | `HKT[B]` |
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

View File

@@ -141,6 +141,10 @@ func reduceRef[A, B any](fa []A, f func(B, *A) B, initial B) B {
return current
}
func MonadReduce[A, B any](fa []A, f func(B, A) B, initial B) B {
return G.MonadReduce(fa, f, initial)
}
func Reduce[A, B any](f func(B, A) B, initial B) func([]A) B {
return G.Reduce[[]A](f, initial)
}

View File

@@ -365,6 +365,70 @@ func generateContextReaderIOEitherEitherize(f, fg *os.File, i int) {
fmt.Fprintln(fg, "}")
}
func generateContextReaderIOEitherUneitherize(f, fg *os.File, i int) {
// non generic version
fmt.Fprintf(f, "\n// Uneitherize%d converts a function with %d parameters returning a [ReaderIOEither[R]] into a function with %d parameters returning a tuple.\n// The first parameter is considered to be the [context.Context].\n", i, i+1, i)
fmt.Fprintf(f, "func Uneitherize%d[F ~func(", i)
for j := 0; j < i; j++ {
if j > 0 {
fmt.Fprintf(f, ", ")
}
fmt.Fprintf(f, "T%d", j)
}
fmt.Fprintf(f, ") ReaderIOEither[R]")
for j := 0; j < i; j++ {
fmt.Fprintf(f, ", T%d", j)
}
fmt.Fprintf(f, ", R any](f F) func(context.Context")
for j := 0; j < i; j++ {
fmt.Fprintf(f, ", T%d", j)
}
fmt.Fprintf(f, ") (R, error) {\n")
fmt.Fprintf(f, " return G.Uneitherize%d[ReaderIOEither[R]", i)
fmt.Fprintf(f, ", func(context.Context")
for j := 0; j < i; j++ {
fmt.Fprintf(f, ", T%d", j)
}
fmt.Fprintf(f, ")(R, error)](f)\n")
fmt.Fprintln(f, "}")
// generic version
fmt.Fprintf(fg, "\n// Uneitherize%d converts a function with %d parameters returning a [GRA] into a function with %d parameters returning a tuple.\n// The first parameter is considered to be the [context.Context].\n", i, i, i)
fmt.Fprintf(fg, "func Uneitherize%d[GRA ~func(context.Context) GIOA, F ~func(context.Context", i)
for j := 0; j < i; j++ {
fmt.Fprintf(fg, ", T%d", j)
}
fmt.Fprintf(fg, ") (R, error), GIOA ~func() E.Either[error, R]")
for j := 0; j < i; j++ {
fmt.Fprintf(fg, ", T%d", j)
}
fmt.Fprintf(fg, ", R any](f func(")
for j := 0; j < i; j++ {
if j > 0 {
fmt.Fprintf(fg, ", ")
}
fmt.Fprintf(fg, "T%d", j)
}
fmt.Fprintf(fg, ") GRA) F {\n")
fmt.Fprintf(fg, " return func(c context.Context")
for j := 0; j < i; j++ {
fmt.Fprintf(fg, ", t%d T%d", j, j)
}
fmt.Fprintf(fg, ") (R, error) {\n")
fmt.Fprintf(fg, " return E.UnwrapError(f(")
for j := 0; j < i; j++ {
if j > 0 {
fmt.Fprintf(fg, ", ")
}
fmt.Fprintf(fg, "t%d", j)
}
fmt.Fprintf(fg, ")(c)())\n")
fmt.Fprintf(fg, " }\n")
fmt.Fprintf(fg, "}\n")
}
func generateContextReaderIOEitherHelpers(filename string, count int) error {
dir, err := os.Getwd()
if err != nil {
@@ -420,10 +484,12 @@ import (
`)
generateContextReaderIOEitherEitherize(f, fg, 0)
generateContextReaderIOEitherUneitherize(f, fg, 0)
for i := 1; i <= count; i++ {
// eitherize
generateContextReaderIOEitherEitherize(f, fg, i)
generateContextReaderIOEitherUneitherize(f, fg, i)
// sequenceT
generateContextReaderIOEitherSequenceT("")(f, fg, i)
generateContextReaderIOEitherSequenceT("Seq")(f, fg, i)

View File

@@ -136,6 +136,70 @@ func generateReaderIOEitherEitherize(f, fg *os.File, i int) {
fmt.Fprintf(fg, "}\n")
}
func generateReaderIOEitherUneitherize(f, fg *os.File, i int) {
// non generic version
fmt.Fprintf(f, "\n// Uneitherize%d converts a function with %d parameters returning a [ReaderIOEither[C, error, R]] into a function with %d parameters returning a tuple.\n// The first parameter is considered to be the context [C].\n", i, i+1, i)
fmt.Fprintf(f, "func Uneitherize%d[F ~func(", i)
for j := 0; j < i; j++ {
if j > 0 {
fmt.Fprintf(f, ", ")
}
fmt.Fprintf(f, "T%d", j)
}
fmt.Fprintf(f, ") ReaderIOEither[C, error, R]")
for j := 0; j < i; j++ {
fmt.Fprintf(f, ", T%d", j)
}
fmt.Fprintf(f, ", C, R any](f F) func(C")
for j := 0; j < i; j++ {
fmt.Fprintf(f, ", T%d", j)
}
fmt.Fprintf(f, ") (R, error) {\n")
fmt.Fprintf(f, " return G.Uneitherize%d[ReaderIOEither[C, error, R]", i)
fmt.Fprintf(f, ", func(C")
for j := 0; j < i; j++ {
fmt.Fprintf(f, ", T%d", j)
}
fmt.Fprintf(f, ")(R, error)](f)\n")
fmt.Fprintln(f, "}")
// generic version
fmt.Fprintf(fg, "\n// Uneitherize%d converts a function with %d parameters returning a [GRA] into a function with %d parameters returning a tuple.\n// The first parameter is considered to be the context [C].\n", i, i, i)
fmt.Fprintf(fg, "func Uneitherize%d[GRA ~func(C) GIOA, F ~func(C", i)
for j := 0; j < i; j++ {
fmt.Fprintf(fg, ", T%d", j)
}
fmt.Fprintf(fg, ") (R, error), GIOA ~func() E.Either[error, R]")
for j := 0; j < i; j++ {
fmt.Fprintf(fg, ", T%d", j)
}
fmt.Fprintf(fg, ", C, R any](f func(")
for j := 0; j < i; j++ {
if j > 0 {
fmt.Fprintf(fg, ", ")
}
fmt.Fprintf(fg, "T%d", j)
}
fmt.Fprintf(fg, ") GRA) F {\n")
fmt.Fprintf(fg, " return func(c C")
for j := 0; j < i; j++ {
fmt.Fprintf(fg, ", t%d T%d", j, j)
}
fmt.Fprintf(fg, ") (R, error) {\n")
fmt.Fprintf(fg, " return E.UnwrapError(f(")
for j := 0; j < i; j++ {
if j > 0 {
fmt.Fprintf(fg, ", ")
}
fmt.Fprintf(fg, "t%d", j)
}
fmt.Fprintf(fg, ")(c)())\n")
fmt.Fprintf(fg, " }\n")
fmt.Fprintf(fg, "}\n")
}
func generateReaderIOEitherHelpers(filename string, count int) error {
dir, err := os.Getwd()
if err != nil {
@@ -197,12 +261,16 @@ import (
generateReaderIOEitherFrom(f, fg, 0)
// eitherize
generateReaderIOEitherEitherize(f, fg, 0)
// uneitherize
generateReaderIOEitherUneitherize(f, fg, 0)
for i := 1; i <= count; i++ {
// from
generateReaderIOEitherFrom(f, fg, i)
// eitherize
generateReaderIOEitherEitherize(f, fg, i)
// uneitherize
generateReaderIOEitherUneitherize(f, fg, i)
}
return nil

View File

@@ -0,0 +1,15 @@
package templates
import (
"text/template"
E "github.com/IBM/fp-go/either"
)
var (
templateFunctions = template.FuncMap{}
)
func Parse(name, tmpl string) E.Either[error, *template.Template] {
return E.TryCatchError(template.New(name).Funcs(templateFunctions).Parse(tmpl))
}

View File

@@ -2,7 +2,7 @@ package readerioeither
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:30:39.012572 +0200 CEST m=+0.008846101
// 2024-05-24 22:24:01.4250895 +0200 CEST m=+0.014515801
import (
"context"
@@ -17,12 +17,24 @@ func Eitherize0[F ~func(context.Context) (R, error), R any](f F) func() ReaderIO
return G.Eitherize0[ReaderIOEither[R]](f)
}
// Uneitherize0 converts a function with 1 parameters returning a [ReaderIOEither[R]] into a function with 0 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize0[F ~func() ReaderIOEither[R], R any](f F) func(context.Context) (R, error) {
return G.Uneitherize0[ReaderIOEither[R], func(context.Context) (R, error)](f)
}
// Eitherize1 converts a function with 1 parameters returning a tuple into a function with 1 parameters returning a [ReaderIOEither[R]]
// The inverse function is [Uneitherize1]
func Eitherize1[F ~func(context.Context, T0) (R, error), T0, R any](f F) func(T0) ReaderIOEither[R] {
return G.Eitherize1[ReaderIOEither[R]](f)
}
// Uneitherize1 converts a function with 2 parameters returning a [ReaderIOEither[R]] into a function with 1 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize1[F ~func(T0) ReaderIOEither[R], T0, R any](f F) func(context.Context, T0) (R, error) {
return G.Uneitherize1[ReaderIOEither[R], func(context.Context, T0) (R, error)](f)
}
// SequenceT1 converts 1 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple1].
func SequenceT1[T1 any](t1 ReaderIOEither[T1]) ReaderIOEither[T.Tuple1[T1]] {
return G.SequenceT1[ReaderIOEither[T.Tuple1[T1]]](t1)
@@ -74,6 +86,12 @@ func Eitherize2[F ~func(context.Context, T0, T1) (R, error), T0, T1, R any](f F)
return G.Eitherize2[ReaderIOEither[R]](f)
}
// Uneitherize2 converts a function with 3 parameters returning a [ReaderIOEither[R]] into a function with 2 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize2[F ~func(T0, T1) ReaderIOEither[R], T0, T1, R any](f F) func(context.Context, T0, T1) (R, error) {
return G.Uneitherize2[ReaderIOEither[R], func(context.Context, T0, T1) (R, error)](f)
}
// SequenceT2 converts 2 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple2].
func SequenceT2[T1, T2 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2]) ReaderIOEither[T.Tuple2[T1, T2]] {
return G.SequenceT2[ReaderIOEither[T.Tuple2[T1, T2]]](t1, t2)
@@ -125,6 +143,12 @@ func Eitherize3[F ~func(context.Context, T0, T1, T2) (R, error), T0, T1, T2, R a
return G.Eitherize3[ReaderIOEither[R]](f)
}
// Uneitherize3 converts a function with 4 parameters returning a [ReaderIOEither[R]] into a function with 3 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize3[F ~func(T0, T1, T2) ReaderIOEither[R], T0, T1, T2, R any](f F) func(context.Context, T0, T1, T2) (R, error) {
return G.Uneitherize3[ReaderIOEither[R], func(context.Context, T0, T1, T2) (R, error)](f)
}
// SequenceT3 converts 3 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple3].
func SequenceT3[T1, T2, T3 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2], t3 ReaderIOEither[T3]) ReaderIOEither[T.Tuple3[T1, T2, T3]] {
return G.SequenceT3[ReaderIOEither[T.Tuple3[T1, T2, T3]]](t1, t2, t3)
@@ -176,6 +200,12 @@ func Eitherize4[F ~func(context.Context, T0, T1, T2, T3) (R, error), T0, T1, T2,
return G.Eitherize4[ReaderIOEither[R]](f)
}
// Uneitherize4 converts a function with 5 parameters returning a [ReaderIOEither[R]] into a function with 4 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize4[F ~func(T0, T1, T2, T3) ReaderIOEither[R], T0, T1, T2, T3, R any](f F) func(context.Context, T0, T1, T2, T3) (R, error) {
return G.Uneitherize4[ReaderIOEither[R], func(context.Context, T0, T1, T2, T3) (R, error)](f)
}
// SequenceT4 converts 4 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple4].
func SequenceT4[T1, T2, T3, T4 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2], t3 ReaderIOEither[T3], t4 ReaderIOEither[T4]) ReaderIOEither[T.Tuple4[T1, T2, T3, T4]] {
return G.SequenceT4[ReaderIOEither[T.Tuple4[T1, T2, T3, T4]]](t1, t2, t3, t4)
@@ -227,6 +257,12 @@ func Eitherize5[F ~func(context.Context, T0, T1, T2, T3, T4) (R, error), T0, T1,
return G.Eitherize5[ReaderIOEither[R]](f)
}
// Uneitherize5 converts a function with 6 parameters returning a [ReaderIOEither[R]] into a function with 5 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize5[F ~func(T0, T1, T2, T3, T4) ReaderIOEither[R], T0, T1, T2, T3, T4, R any](f F) func(context.Context, T0, T1, T2, T3, T4) (R, error) {
return G.Uneitherize5[ReaderIOEither[R], func(context.Context, T0, T1, T2, T3, T4) (R, error)](f)
}
// SequenceT5 converts 5 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple5].
func SequenceT5[T1, T2, T3, T4, T5 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2], t3 ReaderIOEither[T3], t4 ReaderIOEither[T4], t5 ReaderIOEither[T5]) ReaderIOEither[T.Tuple5[T1, T2, T3, T4, T5]] {
return G.SequenceT5[ReaderIOEither[T.Tuple5[T1, T2, T3, T4, T5]]](t1, t2, t3, t4, t5)
@@ -278,6 +314,12 @@ func Eitherize6[F ~func(context.Context, T0, T1, T2, T3, T4, T5) (R, error), T0,
return G.Eitherize6[ReaderIOEither[R]](f)
}
// Uneitherize6 converts a function with 7 parameters returning a [ReaderIOEither[R]] into a function with 6 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize6[F ~func(T0, T1, T2, T3, T4, T5) ReaderIOEither[R], T0, T1, T2, T3, T4, T5, R any](f F) func(context.Context, T0, T1, T2, T3, T4, T5) (R, error) {
return G.Uneitherize6[ReaderIOEither[R], func(context.Context, T0, T1, T2, T3, T4, T5) (R, error)](f)
}
// SequenceT6 converts 6 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple6].
func SequenceT6[T1, T2, T3, T4, T5, T6 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2], t3 ReaderIOEither[T3], t4 ReaderIOEither[T4], t5 ReaderIOEither[T5], t6 ReaderIOEither[T6]) ReaderIOEither[T.Tuple6[T1, T2, T3, T4, T5, T6]] {
return G.SequenceT6[ReaderIOEither[T.Tuple6[T1, T2, T3, T4, T5, T6]]](t1, t2, t3, t4, t5, t6)
@@ -329,6 +371,12 @@ func Eitherize7[F ~func(context.Context, T0, T1, T2, T3, T4, T5, T6) (R, error),
return G.Eitherize7[ReaderIOEither[R]](f)
}
// Uneitherize7 converts a function with 8 parameters returning a [ReaderIOEither[R]] into a function with 7 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) ReaderIOEither[R], T0, T1, T2, T3, T4, T5, T6, R any](f F) func(context.Context, T0, T1, T2, T3, T4, T5, T6) (R, error) {
return G.Uneitherize7[ReaderIOEither[R], func(context.Context, T0, T1, T2, T3, T4, T5, T6) (R, error)](f)
}
// SequenceT7 converts 7 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple7].
func SequenceT7[T1, T2, T3, T4, T5, T6, T7 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2], t3 ReaderIOEither[T3], t4 ReaderIOEither[T4], t5 ReaderIOEither[T5], t6 ReaderIOEither[T6], t7 ReaderIOEither[T7]) ReaderIOEither[T.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
return G.SequenceT7[ReaderIOEither[T.Tuple7[T1, T2, T3, T4, T5, T6, T7]]](t1, t2, t3, t4, t5, t6, t7)
@@ -380,6 +428,12 @@ func Eitherize8[F ~func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7) (R, err
return G.Eitherize8[ReaderIOEither[R]](f)
}
// Uneitherize8 converts a function with 9 parameters returning a [ReaderIOEither[R]] into a function with 8 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) ReaderIOEither[R], T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7) (R, error) {
return G.Uneitherize8[ReaderIOEither[R], func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7) (R, error)](f)
}
// SequenceT8 converts 8 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple8].
func SequenceT8[T1, T2, T3, T4, T5, T6, T7, T8 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2], t3 ReaderIOEither[T3], t4 ReaderIOEither[T4], t5 ReaderIOEither[T5], t6 ReaderIOEither[T6], t7 ReaderIOEither[T7], t8 ReaderIOEither[T8]) ReaderIOEither[T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
return G.SequenceT8[ReaderIOEither[T.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]](t1, t2, t3, t4, t5, t6, t7, t8)
@@ -431,6 +485,12 @@ func Eitherize9[F ~func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7, T8) (R,
return G.Eitherize9[ReaderIOEither[R]](f)
}
// Uneitherize9 converts a function with 10 parameters returning a [ReaderIOEither[R]] into a function with 9 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) ReaderIOEither[R], T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error) {
return G.Uneitherize9[ReaderIOEither[R], func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error)](f)
}
// SequenceT9 converts 9 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple9].
func SequenceT9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2], t3 ReaderIOEither[T3], t4 ReaderIOEither[T4], t5 ReaderIOEither[T5], t6 ReaderIOEither[T6], t7 ReaderIOEither[T7], t8 ReaderIOEither[T8], t9 ReaderIOEither[T9]) ReaderIOEither[T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
return G.SequenceT9[ReaderIOEither[T.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]](t1, t2, t3, t4, t5, t6, t7, t8, t9)
@@ -482,6 +542,12 @@ func Eitherize10[F ~func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9
return G.Eitherize10[ReaderIOEither[R]](f)
}
// Uneitherize10 converts a function with 11 parameters returning a [ReaderIOEither[R]] into a function with 10 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) ReaderIOEither[R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error) {
return G.Uneitherize10[ReaderIOEither[R], func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error)](f)
}
// SequenceT10 converts 10 [ReaderIOEither] into a [ReaderIOEither] of a [T.Tuple10].
func SequenceT10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t1 ReaderIOEither[T1], t2 ReaderIOEither[T2], t3 ReaderIOEither[T3], t4 ReaderIOEither[T4], t5 ReaderIOEither[T5], t6 ReaderIOEither[T6], t7 ReaderIOEither[T7], t8 ReaderIOEither[T8], t9 ReaderIOEither[T9], t10 ReaderIOEither[T10]) ReaderIOEither[T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
return G.SequenceT10[ReaderIOEither[T.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]](t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)

View File

@@ -2,7 +2,7 @@ package generic
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:30:39.012572 +0200 CEST m=+0.008846101
// 2024-05-24 22:24:01.4250895 +0200 CEST m=+0.014515801
import (
"context"
@@ -19,12 +19,28 @@ func Eitherize0[GRA ~func(context.Context) GIOA, F ~func(context.Context) (R, er
return RE.Eitherize0[GRA](f)
}
// Uneitherize0 converts a function with 0 parameters returning a [GRA] into a function with 0 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize0[GRA ~func(context.Context) GIOA, F ~func(context.Context) (R, error), GIOA ~func() E.Either[error, R], R any](f func() GRA) F {
return func(c context.Context) (R, error) {
return E.UnwrapError(f()(c)())
}
}
// Eitherize1 converts a function with 1 parameters returning a tuple into a function with 1 parameters returning a [GRA]
// The inverse function is [Uneitherize1]
func Eitherize1[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0) (R, error), GIOA ~func() E.Either[error, R], T0, R any](f F) func(T0) GRA {
return RE.Eitherize1[GRA](f)
}
// Uneitherize1 converts a function with 1 parameters returning a [GRA] into a function with 1 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize1[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0) (R, error), GIOA ~func() E.Either[error, R], T0, R any](f func(T0) GRA) F {
return func(c context.Context, t0 T0) (R, error) {
return E.UnwrapError(f(t0)(c)())
}
}
// SequenceT1 converts 1 readers into a reader of a [T.Tuple1].
func SequenceT1[
GR_TUPLE1 ~func(context.Context) GIO_TUPLE1,
@@ -169,6 +185,14 @@ func Eitherize2[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1
return RE.Eitherize2[GRA](f)
}
// Uneitherize2 converts a function with 2 parameters returning a [GRA] into a function with 2 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize2[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1) (R, error), GIOA ~func() E.Either[error, R], T0, T1, R any](f func(T0, T1) GRA) F {
return func(c context.Context, t0 T0, t1 T1) (R, error) {
return E.UnwrapError(f(t0, t1)(c)())
}
}
// SequenceT2 converts 2 readers into a reader of a [T.Tuple2].
func SequenceT2[
GR_TUPLE2 ~func(context.Context) GIO_TUPLE2,
@@ -364,6 +388,14 @@ func Eitherize3[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1
return RE.Eitherize3[GRA](f)
}
// Uneitherize3 converts a function with 3 parameters returning a [GRA] into a function with 3 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize3[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1, T2) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, R any](f func(T0, T1, T2) GRA) F {
return func(c context.Context, t0 T0, t1 T1, t2 T2) (R, error) {
return E.UnwrapError(f(t0, t1, t2)(c)())
}
}
// SequenceT3 converts 3 readers into a reader of a [T.Tuple3].
func SequenceT3[
GR_TUPLE3 ~func(context.Context) GIO_TUPLE3,
@@ -610,6 +642,14 @@ func Eitherize4[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1
return RE.Eitherize4[GRA](f)
}
// Uneitherize4 converts a function with 4 parameters returning a [GRA] into a function with 4 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize4[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1, T2, T3) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, R any](f func(T0, T1, T2, T3) GRA) F {
return func(c context.Context, t0 T0, t1 T1, t2 T2, t3 T3) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3)(c)())
}
}
// SequenceT4 converts 4 readers into a reader of a [T.Tuple4].
func SequenceT4[
GR_TUPLE4 ~func(context.Context) GIO_TUPLE4,
@@ -907,6 +947,14 @@ func Eitherize5[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1
return RE.Eitherize5[GRA](f)
}
// Uneitherize5 converts a function with 5 parameters returning a [GRA] into a function with 5 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize5[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1, T2, T3, T4) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, R any](f func(T0, T1, T2, T3, T4) GRA) F {
return func(c context.Context, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4)(c)())
}
}
// SequenceT5 converts 5 readers into a reader of a [T.Tuple5].
func SequenceT5[
GR_TUPLE5 ~func(context.Context) GIO_TUPLE5,
@@ -1255,6 +1303,14 @@ func Eitherize6[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1
return RE.Eitherize6[GRA](f)
}
// Uneitherize6 converts a function with 6 parameters returning a [GRA] into a function with 6 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize6[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1, T2, T3, T4, T5) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, R any](f func(T0, T1, T2, T3, T4, T5) GRA) F {
return func(c context.Context, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5)(c)())
}
}
// SequenceT6 converts 6 readers into a reader of a [T.Tuple6].
func SequenceT6[
GR_TUPLE6 ~func(context.Context) GIO_TUPLE6,
@@ -1654,6 +1710,14 @@ func Eitherize7[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1
return RE.Eitherize7[GRA](f)
}
// Uneitherize7 converts a function with 7 parameters returning a [GRA] into a function with 7 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize7[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1, T2, T3, T4, T5, T6) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, R any](f func(T0, T1, T2, T3, T4, T5, T6) GRA) F {
return func(c context.Context, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5, t6)(c)())
}
}
// SequenceT7 converts 7 readers into a reader of a [T.Tuple7].
func SequenceT7[
GR_TUPLE7 ~func(context.Context) GIO_TUPLE7,
@@ -2104,6 +2168,14 @@ func Eitherize8[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1
return RE.Eitherize8[GRA](f)
}
// Uneitherize8 converts a function with 8 parameters returning a [GRA] into a function with 8 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize8[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, R any](f func(T0, T1, T2, T3, T4, T5, T6, T7) GRA) F {
return func(c context.Context, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7)(c)())
}
}
// SequenceT8 converts 8 readers into a reader of a [T.Tuple8].
func SequenceT8[
GR_TUPLE8 ~func(context.Context) GIO_TUPLE8,
@@ -2605,6 +2677,14 @@ func Eitherize9[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1
return RE.Eitherize9[GRA](f)
}
// Uneitherize9 converts a function with 9 parameters returning a [GRA] into a function with 9 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize9[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8) GRA) F {
return func(c context.Context, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8)(c)())
}
}
// SequenceT9 converts 9 readers into a reader of a [T.Tuple9].
func SequenceT9[
GR_TUPLE9 ~func(context.Context) GIO_TUPLE9,
@@ -3157,6 +3237,14 @@ func Eitherize10[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T
return RE.Eitherize10[GRA](f)
}
// Uneitherize10 converts a function with 10 parameters returning a [GRA] into a function with 10 parameters returning a tuple.
// The first parameter is considered to be the [context.Context].
func Uneitherize10[GRA ~func(context.Context) GIOA, F ~func(context.Context, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) GRA) F {
return func(c context.Context, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9)(c)())
}
}
// SequenceT10 converts 10 readers into a reader of a [T.Tuple10].
func SequenceT10[
GR_TUPLE10 ~func(context.Context) GIO_TUPLE10,

View File

@@ -25,6 +25,7 @@ import (
IOE "github.com/IBM/fp-go/ioeither"
L "github.com/IBM/fp-go/lazy"
O "github.com/IBM/fp-go/option"
RIO "github.com/IBM/fp-go/readerio"
)
func FromEither[A any](e ET.Either[error, A]) ReaderIOEither[A] {
@@ -192,8 +193,7 @@ func Memoize[A any](rdr ReaderIOEither[A]) ReaderIOEither[A] {
}
// Flatten converts a nested [ReaderIOEither] into a [ReaderIOEither]
func Flatten[
A any](rdr ReaderIOEither[ReaderIOEither[A]]) ReaderIOEither[A] {
func Flatten[A any](rdr ReaderIOEither[ReaderIOEither[A]]) ReaderIOEither[A] {
return G.Flatten[ReaderIOEither[ReaderIOEither[A]]](rdr)
}
@@ -204,3 +204,15 @@ func MonadFlap[B, A any](fab ReaderIOEither[func(A) B], a A) ReaderIOEither[B] {
func Flap[B, A any](a A) func(ReaderIOEither[func(A) B]) ReaderIOEither[B] {
return G.Flap[ReaderIOEither[func(A) B], ReaderIOEither[B]](a)
}
func Fold[A, B any](onLeft func(error) ReaderIOEither[B], onRight func(A) ReaderIOEither[B]) func(ReaderIOEither[A]) ReaderIOEither[B] {
return G.Fold[ReaderIOEither[B], ReaderIOEither[A]](onLeft, onRight)
}
func GetOrElse[A any](onLeft func(error) RIO.ReaderIO[context.Context, A]) func(ReaderIOEither[A]) RIO.ReaderIO[context.Context, A] {
return G.GetOrElse[RIO.ReaderIO[context.Context, A], ReaderIOEither[A]](onLeft)
}
func OrLeft[A any](onLeft func(error) RIO.ReaderIO[context.Context, error]) func(ReaderIOEither[A]) ReaderIOEither[A] {
return G.OrLeft[ReaderIOEither[A]](onLeft)
}

View File

@@ -1,2 +1,3 @@
@echo off
go tool cover -html=build/cover.out -o build/cover.html
go tool cover -html=build/cover.out -o build/cover.html
cov-report -ex ".*/cli/.*.go|.*/gen.go|.*/binds.go" build\cover.out

View File

@@ -40,4 +40,4 @@
// [MakeInjector]: [github.com/IBM/fp-go/di/erasure.MakeInjector]
package di
//go:generate go run .. di --count 10 --filename gen.go
//go:generate go run .. di --count 15 --filename gen.go

897
di/gen.go
View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-12-18 21:40:11.0891062 +0100 CET m=+0.007755601
// 2024-02-29 16:18:47.9991921 +0100 CET m=+0.012914901
package di
@@ -41,7 +41,7 @@ func MakeProviderFactory1[T1 any, R any](
)
}
// MakeTokenWithDefault1 creates an [InjectionToken] with a default implementation with 1 dependenciess
// MakeTokenWithDefault1 creates an [InjectionToken] with a default implementation with 1 dependencies
func MakeTokenWithDefault1[T1 any, R any](
name string,
d1 Dependency[T1],
@@ -102,7 +102,7 @@ func MakeProviderFactory2[T1, T2 any, R any](
)
}
// MakeTokenWithDefault2 creates an [InjectionToken] with a default implementation with 2 dependenciess
// MakeTokenWithDefault2 creates an [InjectionToken] with a default implementation with 2 dependencies
func MakeTokenWithDefault2[T1, T2 any, R any](
name string,
d1 Dependency[T1],
@@ -173,7 +173,7 @@ func MakeProviderFactory3[T1, T2, T3 any, R any](
)
}
// MakeTokenWithDefault3 creates an [InjectionToken] with a default implementation with 3 dependenciess
// MakeTokenWithDefault3 creates an [InjectionToken] with a default implementation with 3 dependencies
func MakeTokenWithDefault3[T1, T2, T3 any, R any](
name string,
d1 Dependency[T1],
@@ -254,7 +254,7 @@ func MakeProviderFactory4[T1, T2, T3, T4 any, R any](
)
}
// MakeTokenWithDefault4 creates an [InjectionToken] with a default implementation with 4 dependenciess
// MakeTokenWithDefault4 creates an [InjectionToken] with a default implementation with 4 dependencies
func MakeTokenWithDefault4[T1, T2, T3, T4 any, R any](
name string,
d1 Dependency[T1],
@@ -345,7 +345,7 @@ func MakeProviderFactory5[T1, T2, T3, T4, T5 any, R any](
)
}
// MakeTokenWithDefault5 creates an [InjectionToken] with a default implementation with 5 dependenciess
// MakeTokenWithDefault5 creates an [InjectionToken] with a default implementation with 5 dependencies
func MakeTokenWithDefault5[T1, T2, T3, T4, T5 any, R any](
name string,
d1 Dependency[T1],
@@ -446,7 +446,7 @@ func MakeProviderFactory6[T1, T2, T3, T4, T5, T6 any, R any](
)
}
// MakeTokenWithDefault6 creates an [InjectionToken] with a default implementation with 6 dependenciess
// MakeTokenWithDefault6 creates an [InjectionToken] with a default implementation with 6 dependencies
func MakeTokenWithDefault6[T1, T2, T3, T4, T5, T6 any, R any](
name string,
d1 Dependency[T1],
@@ -557,7 +557,7 @@ func MakeProviderFactory7[T1, T2, T3, T4, T5, T6, T7 any, R any](
)
}
// MakeTokenWithDefault7 creates an [InjectionToken] with a default implementation with 7 dependenciess
// MakeTokenWithDefault7 creates an [InjectionToken] with a default implementation with 7 dependencies
func MakeTokenWithDefault7[T1, T2, T3, T4, T5, T6, T7 any, R any](
name string,
d1 Dependency[T1],
@@ -678,7 +678,7 @@ func MakeProviderFactory8[T1, T2, T3, T4, T5, T6, T7, T8 any, R any](
)
}
// MakeTokenWithDefault8 creates an [InjectionToken] with a default implementation with 8 dependenciess
// MakeTokenWithDefault8 creates an [InjectionToken] with a default implementation with 8 dependencies
func MakeTokenWithDefault8[T1, T2, T3, T4, T5, T6, T7, T8 any, R any](
name string,
d1 Dependency[T1],
@@ -809,7 +809,7 @@ func MakeProviderFactory9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any, R any](
)
}
// MakeTokenWithDefault9 creates an [InjectionToken] with a default implementation with 9 dependenciess
// MakeTokenWithDefault9 creates an [InjectionToken] with a default implementation with 9 dependencies
func MakeTokenWithDefault9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any, R any](
name string,
d1 Dependency[T1],
@@ -950,7 +950,7 @@ func MakeProviderFactory10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any, R any](
)
}
// MakeTokenWithDefault10 creates an [InjectionToken] with a default implementation with 10 dependenciess
// MakeTokenWithDefault10 creates an [InjectionToken] with a default implementation with 10 dependencies
func MakeTokenWithDefault10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any, R any](
name string,
d1 Dependency[T1],
@@ -1011,3 +1011,878 @@ func MakeProvider10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any, R any](
f,
))
}
// eraseProviderFactory11 creates a function that takes a variadic number of untyped arguments and from a function of 11 strongly typed arguments and 11 dependencies
func eraseProviderFactory11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
ft := eraseTuple(T.Tupled11(f))
t1 := lookupAt[T1](0, d1)
t2 := lookupAt[T2](1, d2)
t3 := lookupAt[T3](2, d3)
t4 := lookupAt[T4](3, d4)
t5 := lookupAt[T5](4, d5)
t6 := lookupAt[T6](5, d6)
t7 := lookupAt[T7](6, d7)
t8 := lookupAt[T8](7, d8)
t9 := lookupAt[T9](8, d9)
t10 := lookupAt[T10](9, d10)
t11 := lookupAt[T11](10, d11)
return func(params ...any) IOE.IOEither[error, any] {
return ft(E.SequenceT11(
t1(params),
t2(params),
t3(params),
t4(params),
t5(params),
t6(params),
t7(params),
t8(params),
t9(params),
t10(params),
t11(params),
))
}
}
// MakeProviderFactory11 creates a [DIE.ProviderFactory] from a function with 11 arguments and 11 dependencies
func MakeProviderFactory11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) IOE.IOEither[error, R],
) DIE.ProviderFactory {
return DIE.MakeProviderFactory(
A.From[DIE.Dependency](
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
),
eraseProviderFactory11(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
f,
),
)
}
// MakeTokenWithDefault11 creates an [InjectionToken] with a default implementation with 11 dependencies
func MakeTokenWithDefault11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any, R any](
name string,
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) IOE.IOEither[error, R],
) InjectionToken[R] {
return MakeTokenWithDefault[R](name, MakeProviderFactory11(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
f,
))
}
// MakeProvider11 creates a [DIE.Provider] for an [InjectionToken] from a function with 11 dependencies
func MakeProvider11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any, R any](
token InjectionToken[R],
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) IOE.IOEither[error, R],
) DIE.Provider {
return DIE.MakeProvider(
token,
MakeProviderFactory11(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
f,
))
}
// eraseProviderFactory12 creates a function that takes a variadic number of untyped arguments and from a function of 12 strongly typed arguments and 12 dependencies
func eraseProviderFactory12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
ft := eraseTuple(T.Tupled12(f))
t1 := lookupAt[T1](0, d1)
t2 := lookupAt[T2](1, d2)
t3 := lookupAt[T3](2, d3)
t4 := lookupAt[T4](3, d4)
t5 := lookupAt[T5](4, d5)
t6 := lookupAt[T6](5, d6)
t7 := lookupAt[T7](6, d7)
t8 := lookupAt[T8](7, d8)
t9 := lookupAt[T9](8, d9)
t10 := lookupAt[T10](9, d10)
t11 := lookupAt[T11](10, d11)
t12 := lookupAt[T12](11, d12)
return func(params ...any) IOE.IOEither[error, any] {
return ft(E.SequenceT12(
t1(params),
t2(params),
t3(params),
t4(params),
t5(params),
t6(params),
t7(params),
t8(params),
t9(params),
t10(params),
t11(params),
t12(params),
))
}
}
// MakeProviderFactory12 creates a [DIE.ProviderFactory] from a function with 12 arguments and 12 dependencies
func MakeProviderFactory12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) IOE.IOEither[error, R],
) DIE.ProviderFactory {
return DIE.MakeProviderFactory(
A.From[DIE.Dependency](
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
),
eraseProviderFactory12(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
f,
),
)
}
// MakeTokenWithDefault12 creates an [InjectionToken] with a default implementation with 12 dependencies
func MakeTokenWithDefault12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any, R any](
name string,
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) IOE.IOEither[error, R],
) InjectionToken[R] {
return MakeTokenWithDefault[R](name, MakeProviderFactory12(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
f,
))
}
// MakeProvider12 creates a [DIE.Provider] for an [InjectionToken] from a function with 12 dependencies
func MakeProvider12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any, R any](
token InjectionToken[R],
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) IOE.IOEither[error, R],
) DIE.Provider {
return DIE.MakeProvider(
token,
MakeProviderFactory12(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
f,
))
}
// eraseProviderFactory13 creates a function that takes a variadic number of untyped arguments and from a function of 13 strongly typed arguments and 13 dependencies
func eraseProviderFactory13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
ft := eraseTuple(T.Tupled13(f))
t1 := lookupAt[T1](0, d1)
t2 := lookupAt[T2](1, d2)
t3 := lookupAt[T3](2, d3)
t4 := lookupAt[T4](3, d4)
t5 := lookupAt[T5](4, d5)
t6 := lookupAt[T6](5, d6)
t7 := lookupAt[T7](6, d7)
t8 := lookupAt[T8](7, d8)
t9 := lookupAt[T9](8, d9)
t10 := lookupAt[T10](9, d10)
t11 := lookupAt[T11](10, d11)
t12 := lookupAt[T12](11, d12)
t13 := lookupAt[T13](12, d13)
return func(params ...any) IOE.IOEither[error, any] {
return ft(E.SequenceT13(
t1(params),
t2(params),
t3(params),
t4(params),
t5(params),
t6(params),
t7(params),
t8(params),
t9(params),
t10(params),
t11(params),
t12(params),
t13(params),
))
}
}
// MakeProviderFactory13 creates a [DIE.ProviderFactory] from a function with 13 arguments and 13 dependencies
func MakeProviderFactory13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) IOE.IOEither[error, R],
) DIE.ProviderFactory {
return DIE.MakeProviderFactory(
A.From[DIE.Dependency](
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
),
eraseProviderFactory13(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
f,
),
)
}
// MakeTokenWithDefault13 creates an [InjectionToken] with a default implementation with 13 dependencies
func MakeTokenWithDefault13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any, R any](
name string,
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) IOE.IOEither[error, R],
) InjectionToken[R] {
return MakeTokenWithDefault[R](name, MakeProviderFactory13(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
f,
))
}
// MakeProvider13 creates a [DIE.Provider] for an [InjectionToken] from a function with 13 dependencies
func MakeProvider13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any, R any](
token InjectionToken[R],
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) IOE.IOEither[error, R],
) DIE.Provider {
return DIE.MakeProvider(
token,
MakeProviderFactory13(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
f,
))
}
// eraseProviderFactory14 creates a function that takes a variadic number of untyped arguments and from a function of 14 strongly typed arguments and 14 dependencies
func eraseProviderFactory14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
d14 Dependency[T14],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
ft := eraseTuple(T.Tupled14(f))
t1 := lookupAt[T1](0, d1)
t2 := lookupAt[T2](1, d2)
t3 := lookupAt[T3](2, d3)
t4 := lookupAt[T4](3, d4)
t5 := lookupAt[T5](4, d5)
t6 := lookupAt[T6](5, d6)
t7 := lookupAt[T7](6, d7)
t8 := lookupAt[T8](7, d8)
t9 := lookupAt[T9](8, d9)
t10 := lookupAt[T10](9, d10)
t11 := lookupAt[T11](10, d11)
t12 := lookupAt[T12](11, d12)
t13 := lookupAt[T13](12, d13)
t14 := lookupAt[T14](13, d14)
return func(params ...any) IOE.IOEither[error, any] {
return ft(E.SequenceT14(
t1(params),
t2(params),
t3(params),
t4(params),
t5(params),
t6(params),
t7(params),
t8(params),
t9(params),
t10(params),
t11(params),
t12(params),
t13(params),
t14(params),
))
}
}
// MakeProviderFactory14 creates a [DIE.ProviderFactory] from a function with 14 arguments and 14 dependencies
func MakeProviderFactory14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
d14 Dependency[T14],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) IOE.IOEither[error, R],
) DIE.ProviderFactory {
return DIE.MakeProviderFactory(
A.From[DIE.Dependency](
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
),
eraseProviderFactory14(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
f,
),
)
}
// MakeTokenWithDefault14 creates an [InjectionToken] with a default implementation with 14 dependencies
func MakeTokenWithDefault14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any, R any](
name string,
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
d14 Dependency[T14],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) IOE.IOEither[error, R],
) InjectionToken[R] {
return MakeTokenWithDefault[R](name, MakeProviderFactory14(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
f,
))
}
// MakeProvider14 creates a [DIE.Provider] for an [InjectionToken] from a function with 14 dependencies
func MakeProvider14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any, R any](
token InjectionToken[R],
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
d14 Dependency[T14],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) IOE.IOEither[error, R],
) DIE.Provider {
return DIE.MakeProvider(
token,
MakeProviderFactory14(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
f,
))
}
// eraseProviderFactory15 creates a function that takes a variadic number of untyped arguments and from a function of 15 strongly typed arguments and 15 dependencies
func eraseProviderFactory15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
d14 Dependency[T14],
d15 Dependency[T15],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
ft := eraseTuple(T.Tupled15(f))
t1 := lookupAt[T1](0, d1)
t2 := lookupAt[T2](1, d2)
t3 := lookupAt[T3](2, d3)
t4 := lookupAt[T4](3, d4)
t5 := lookupAt[T5](4, d5)
t6 := lookupAt[T6](5, d6)
t7 := lookupAt[T7](6, d7)
t8 := lookupAt[T8](7, d8)
t9 := lookupAt[T9](8, d9)
t10 := lookupAt[T10](9, d10)
t11 := lookupAt[T11](10, d11)
t12 := lookupAt[T12](11, d12)
t13 := lookupAt[T13](12, d13)
t14 := lookupAt[T14](13, d14)
t15 := lookupAt[T15](14, d15)
return func(params ...any) IOE.IOEither[error, any] {
return ft(E.SequenceT15(
t1(params),
t2(params),
t3(params),
t4(params),
t5(params),
t6(params),
t7(params),
t8(params),
t9(params),
t10(params),
t11(params),
t12(params),
t13(params),
t14(params),
t15(params),
))
}
}
// MakeProviderFactory15 creates a [DIE.ProviderFactory] from a function with 15 arguments and 15 dependencies
func MakeProviderFactory15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any, R any](
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
d14 Dependency[T14],
d15 Dependency[T15],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) IOE.IOEither[error, R],
) DIE.ProviderFactory {
return DIE.MakeProviderFactory(
A.From[DIE.Dependency](
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
d15,
),
eraseProviderFactory15(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
d15,
f,
),
)
}
// MakeTokenWithDefault15 creates an [InjectionToken] with a default implementation with 15 dependencies
func MakeTokenWithDefault15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any, R any](
name string,
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
d14 Dependency[T14],
d15 Dependency[T15],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) IOE.IOEither[error, R],
) InjectionToken[R] {
return MakeTokenWithDefault[R](name, MakeProviderFactory15(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
d15,
f,
))
}
// MakeProvider15 creates a [DIE.Provider] for an [InjectionToken] from a function with 15 dependencies
func MakeProvider15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any, R any](
token InjectionToken[R],
d1 Dependency[T1],
d2 Dependency[T2],
d3 Dependency[T3],
d4 Dependency[T4],
d5 Dependency[T5],
d6 Dependency[T6],
d7 Dependency[T7],
d8 Dependency[T8],
d9 Dependency[T9],
d10 Dependency[T10],
d11 Dependency[T11],
d12 Dependency[T12],
d13 Dependency[T13],
d14 Dependency[T14],
d15 Dependency[T15],
f func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) IOE.IOEither[error, R],
) DIE.Provider {
return DIE.MakeProvider(
token,
MakeProviderFactory15(
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
d15,
f,
))
}

View File

@@ -1,8 +1,10 @@
package either
import (
"fmt"
"testing"
TST "github.com/IBM/fp-go/internal/testing"
"github.com/stretchr/testify/assert"
)
@@ -16,3 +18,33 @@ func TestCompactArray(t *testing.T) {
res := CompactArray(ar)
assert.Equal(t, 2, len(res))
}
func TestSequenceArray(t *testing.T) {
s := TST.SequenceArrayTest(
FromStrictEquals[error, bool](),
Pointed[error, string](),
Pointed[error, bool](),
Functor[error, []string, bool](),
SequenceArray[error, string],
)
for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
}
}
func TestSequenceArrayError(t *testing.T) {
s := TST.SequenceArrayErrorTest(
FromStrictEquals[error, bool](),
Left[string, error],
Left[bool, error],
Pointed[error, string](),
Pointed[error, bool](),
Functor[error, []string, bool](),
SequenceArray[error, string],
)
// run across four bits
s(4)(t)
}

View File

@@ -31,7 +31,7 @@ type (
// String prints some debug info for the object
//
// go:noinline
//go:noinline
func eitherString(s *either) string {
if s.isLeft {
return fmt.Sprintf("Left[%T](%v)", s.value, s.value)
@@ -41,7 +41,7 @@ func eitherString(s *either) string {
// Format prints some debug info for the object
//
// go:noinline
//go:noinline
func eitherFormat(e *either, f fmt.State, c rune) {
switch c {
case 's':

View File

@@ -16,4 +16,4 @@
// Package option defines the [Either] datastructure and its monadic operations
package either
//go:generate go run .. either --count 10 --filename gen.go
//go:generate go run .. either --count 15 --filename gen.go

View File

@@ -33,7 +33,7 @@ func Of[E, A any](value A) Either[E, A] {
return F.Pipe1(value, Right[E, A])
}
func FromIO[E, IO ~func() A, A any](f IO) Either[E, A] {
func FromIO[E any, IO ~func() A, A any](f IO) Either[E, A] {
return F.Pipe1(f(), Right[E, A])
}

View File

@@ -22,6 +22,7 @@ import (
F "github.com/IBM/fp-go/function"
"github.com/IBM/fp-go/internal/utils"
IO "github.com/IBM/fp-go/io"
O "github.com/IBM/fp-go/option"
S "github.com/IBM/fp-go/string"
"github.com/stretchr/testify/assert"
@@ -71,7 +72,6 @@ func TestReduce(t *testing.T) {
assert.Equal(t, "foo", F.Pipe1(Left[string, string]("bar"), Reduce[string](s.Concat, "foo")))
}
func TestAp(t *testing.T) {
f := S.Size
@@ -120,3 +120,10 @@ func TestStringer(t *testing.T) {
var s fmt.Stringer = e
assert.Equal(t, exp, s.String())
}
func TestFromIO(t *testing.T) {
f := IO.Of("abc")
e := FromIO[error](f)
assert.Equal(t, Right[error]("abc"), e)
}

31
either/functor.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package either
import (
"github.com/IBM/fp-go/internal/functor"
)
type eitherFunctor[E, A, B any] struct{}
func (o *eitherFunctor[E, A, B]) Map(f func(A) B) func(Either[E, A]) Either[E, B] {
return Map[E, A, B](f)
}
// Functor implements the functoric operations for [Either]
func Functor[E, A, B any]() functor.Functor[A, B, Either[E, A], Either[E, B]] {
return &eitherFunctor[E, A, B]{}
}

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:30:40.410373 +0200 CEST m=+0.010337601
// 2024-02-29 16:18:50.8721435 +0100 CET m=+0.070394501
package either
@@ -679,3 +679,518 @@ func TraverseTuple10[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3
)
}
}
// Eitherize11 converts a function with 11 parameters returning a tuple into a function with 11 parameters returning an Either
// The inverse function is [Uneitherize11]
func Eitherize11[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) Either[error, R] {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10) Either[error, R] {
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10))
}
}
// Uneitherize11 converts a function with 11 parameters returning an Either into a function with 11 parameters returning a tuple
// The inverse function is [Eitherize11]
func Uneitherize11[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) (R, error) {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10) (R, error) {
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10))
}
}
// SequenceT11 converts 11 parameters of [Either[E, T]] into a [Either[E, Tuple11]].
func SequenceT11[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11]) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] {
return A.SequenceT11(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T7],
Ap[func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T8],
Ap[func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T9],
Ap[func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T10],
Ap[T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T11],
t1,
t2,
t3,
t4,
t5,
t6,
t7,
t8,
t9,
t10,
t11,
)
}
// SequenceTuple11 converts a [Tuple11] of [Either[E, T]] into an [Either[E, Tuple11]].
func SequenceTuple11[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](t T.Tuple11[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11]]) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] {
return A.SequenceTuple11(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T7],
Ap[func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T8],
Ap[func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T9],
Ap[func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T10],
Ap[T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T11],
t,
)
}
// TraverseTuple11 converts a [Tuple11] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple11]].
func TraverseTuple11[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11) func(T.Tuple11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11]) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] {
return func(t T.Tuple11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11]) Either[E, T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] {
return A.TraverseTuple11(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T7],
Ap[func(T9) func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T8],
Ap[func(T10) func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T9],
Ap[func(T11) T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T10],
Ap[T.Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], E, T11],
f1,
f2,
f3,
f4,
f5,
f6,
f7,
f8,
f9,
f10,
f11,
t,
)
}
}
// Eitherize12 converts a function with 12 parameters returning a tuple into a function with 12 parameters returning an Either
// The inverse function is [Uneitherize12]
func Eitherize12[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) Either[error, R] {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11) Either[error, R] {
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11))
}
}
// Uneitherize12 converts a function with 12 parameters returning an Either into a function with 12 parameters returning a tuple
// The inverse function is [Eitherize12]
func Uneitherize12[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) (R, error) {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11) (R, error) {
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11))
}
}
// SequenceT12 converts 12 parameters of [Either[E, T]] into a [Either[E, Tuple12]].
func SequenceT12[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11], t12 Either[E, T12]) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] {
return A.SequenceT12(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T8],
Ap[func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T9],
Ap[func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T10],
Ap[func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T11],
Ap[T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T12],
t1,
t2,
t3,
t4,
t5,
t6,
t7,
t8,
t9,
t10,
t11,
t12,
)
}
// SequenceTuple12 converts a [Tuple12] of [Either[E, T]] into an [Either[E, Tuple12]].
func SequenceTuple12[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](t T.Tuple12[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11], Either[E, T12]]) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] {
return A.SequenceTuple12(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T8],
Ap[func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T9],
Ap[func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T10],
Ap[func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T11],
Ap[T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T12],
t,
)
}
// TraverseTuple12 converts a [Tuple12] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple12]].
func TraverseTuple12[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], F12 ~func(A12) Either[E, T12], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11, A12, T12 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12) func(T.Tuple12[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12]) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] {
return func(t T.Tuple12[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12]) Either[E, T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] {
return A.TraverseTuple12(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T8],
Ap[func(T10) func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T9],
Ap[func(T11) func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T10],
Ap[func(T12) T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T11],
Ap[T.Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], E, T12],
f1,
f2,
f3,
f4,
f5,
f6,
f7,
f8,
f9,
f10,
f11,
f12,
t,
)
}
}
// Eitherize13 converts a function with 13 parameters returning a tuple into a function with 13 parameters returning an Either
// The inverse function is [Uneitherize13]
func Eitherize13[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) Either[error, R] {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12) Either[error, R] {
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12))
}
}
// Uneitherize13 converts a function with 13 parameters returning an Either into a function with 13 parameters returning a tuple
// The inverse function is [Eitherize13]
func Uneitherize13[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) (R, error) {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12) (R, error) {
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12))
}
}
// SequenceT13 converts 13 parameters of [Either[E, T]] into a [Either[E, Tuple13]].
func SequenceT13[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11], t12 Either[E, T12], t13 Either[E, T13]) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] {
return A.SequenceT13(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T9],
Ap[func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T10],
Ap[func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T11],
Ap[func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T12],
Ap[T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T13],
t1,
t2,
t3,
t4,
t5,
t6,
t7,
t8,
t9,
t10,
t11,
t12,
t13,
)
}
// SequenceTuple13 converts a [Tuple13] of [Either[E, T]] into an [Either[E, Tuple13]].
func SequenceTuple13[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](t T.Tuple13[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11], Either[E, T12], Either[E, T13]]) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] {
return A.SequenceTuple13(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T9],
Ap[func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T10],
Ap[func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T11],
Ap[func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T12],
Ap[T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T13],
t,
)
}
// TraverseTuple13 converts a [Tuple13] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple13]].
func TraverseTuple13[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], F12 ~func(A12) Either[E, T12], F13 ~func(A13) Either[E, T13], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11, A12, T12, A13, T13 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13) func(T.Tuple13[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13]) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] {
return func(t T.Tuple13[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13]) Either[E, T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] {
return A.TraverseTuple13(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T9],
Ap[func(T11) func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T10],
Ap[func(T12) func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T11],
Ap[func(T13) T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T12],
Ap[T.Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], E, T13],
f1,
f2,
f3,
f4,
f5,
f6,
f7,
f8,
f9,
f10,
f11,
f12,
f13,
t,
)
}
}
// Eitherize14 converts a function with 14 parameters returning a tuple into a function with 14 parameters returning an Either
// The inverse function is [Uneitherize14]
func Eitherize14[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) Either[error, R] {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13) Either[error, R] {
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13))
}
}
// Uneitherize14 converts a function with 14 parameters returning an Either into a function with 14 parameters returning a tuple
// The inverse function is [Eitherize14]
func Uneitherize14[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) (R, error) {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13) (R, error) {
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13))
}
}
// SequenceT14 converts 14 parameters of [Either[E, T]] into a [Either[E, Tuple14]].
func SequenceT14[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11], t12 Either[E, T12], t13 Either[E, T13], t14 Either[E, T14]) Either[E, T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] {
return A.SequenceT14(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T9],
Ap[func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T10],
Ap[func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T11],
Ap[func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T12],
Ap[func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T13],
Ap[T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T14],
t1,
t2,
t3,
t4,
t5,
t6,
t7,
t8,
t9,
t10,
t11,
t12,
t13,
t14,
)
}
// SequenceTuple14 converts a [Tuple14] of [Either[E, T]] into an [Either[E, Tuple14]].
func SequenceTuple14[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](t T.Tuple14[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11], Either[E, T12], Either[E, T13], Either[E, T14]]) Either[E, T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] {
return A.SequenceTuple14(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T9],
Ap[func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T10],
Ap[func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T11],
Ap[func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T12],
Ap[func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T13],
Ap[T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T14],
t,
)
}
// TraverseTuple14 converts a [Tuple14] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple14]].
func TraverseTuple14[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], F12 ~func(A12) Either[E, T12], F13 ~func(A13) Either[E, T13], F14 ~func(A14) Either[E, T14], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11, A12, T12, A13, T13, A14, T14 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14) func(T.Tuple14[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14]) Either[E, T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] {
return func(t T.Tuple14[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14]) Either[E, T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] {
return A.TraverseTuple14(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T9],
Ap[func(T11) func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T10],
Ap[func(T12) func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T11],
Ap[func(T13) func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T12],
Ap[func(T14) T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T13],
Ap[T.Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], E, T14],
f1,
f2,
f3,
f4,
f5,
f6,
f7,
f8,
f9,
f10,
f11,
f12,
f13,
f14,
t,
)
}
}
// Eitherize15 converts a function with 15 parameters returning a tuple into a function with 15 parameters returning an Either
// The inverse function is [Uneitherize15]
func Eitherize15[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) Either[error, R] {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13, t14 T14) Either[error, R] {
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14))
}
}
// Uneitherize15 converts a function with 15 parameters returning an Either into a function with 15 parameters returning a tuple
// The inverse function is [Eitherize15]
func Uneitherize15[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) (R, error) {
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13, t14 T14) (R, error) {
return UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14))
}
}
// SequenceT15 converts 15 parameters of [Either[E, T]] into a [Either[E, Tuple15]].
func SequenceT15[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](t1 Either[E, T1], t2 Either[E, T2], t3 Either[E, T3], t4 Either[E, T4], t5 Either[E, T5], t6 Either[E, T6], t7 Either[E, T7], t8 Either[E, T8], t9 Either[E, T9], t10 Either[E, T10], t11 Either[E, T11], t12 Either[E, T12], t13 Either[E, T13], t14 Either[E, T14], t15 Either[E, T15]) Either[E, T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] {
return A.SequenceT15(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T9],
Ap[func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T10],
Ap[func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T11],
Ap[func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T12],
Ap[func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T13],
Ap[func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T14],
Ap[T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T15],
t1,
t2,
t3,
t4,
t5,
t6,
t7,
t8,
t9,
t10,
t11,
t12,
t13,
t14,
t15,
)
}
// SequenceTuple15 converts a [Tuple15] of [Either[E, T]] into an [Either[E, Tuple15]].
func SequenceTuple15[E, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](t T.Tuple15[Either[E, T1], Either[E, T2], Either[E, T3], Either[E, T4], Either[E, T5], Either[E, T6], Either[E, T7], Either[E, T8], Either[E, T9], Either[E, T10], Either[E, T11], Either[E, T12], Either[E, T13], Either[E, T14], Either[E, T15]]) Either[E, T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] {
return A.SequenceTuple15(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T9],
Ap[func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T10],
Ap[func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T11],
Ap[func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T12],
Ap[func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T13],
Ap[func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T14],
Ap[T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T15],
t,
)
}
// TraverseTuple15 converts a [Tuple15] of [A] via transformation functions transforming [A] to [Either[E, A]] into a [Either[E, Tuple15]].
func TraverseTuple15[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~func(A3) Either[E, T3], F4 ~func(A4) Either[E, T4], F5 ~func(A5) Either[E, T5], F6 ~func(A6) Either[E, T6], F7 ~func(A7) Either[E, T7], F8 ~func(A8) Either[E, T8], F9 ~func(A9) Either[E, T9], F10 ~func(A10) Either[E, T10], F11 ~func(A11) Either[E, T11], F12 ~func(A12) Either[E, T12], F13 ~func(A13) Either[E, T13], F14 ~func(A14) Either[E, T14], F15 ~func(A15) Either[E, T15], E, A1, T1, A2, T2, A3, T3, A4, T4, A5, T5, A6, T6, A7, T7, A8, T8, A9, T9, A10, T10, A11, T11, A12, T12, A13, T13, A14, T14, A15, T15 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15) func(T.Tuple15[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15]) Either[E, T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] {
return func(t T.Tuple15[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15]) Either[E, T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] {
return A.TraverseTuple15(
Map[E, T1, func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]],
Ap[func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T2],
Ap[func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T3],
Ap[func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T4],
Ap[func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T5],
Ap[func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T6],
Ap[func(T8) func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T7],
Ap[func(T9) func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T8],
Ap[func(T10) func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T9],
Ap[func(T11) func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T10],
Ap[func(T12) func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T11],
Ap[func(T13) func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T12],
Ap[func(T14) func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T13],
Ap[func(T15) T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T14],
Ap[T.Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], E, T15],
f1,
f2,
f3,
f4,
f5,
f6,
f7,
f8,
f9,
f10,
f11,
f12,
f13,
f14,
f15,
t,
)
}
}

31
either/pointed.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package either
import (
"github.com/IBM/fp-go/internal/pointed"
)
type eitherPointed[E, A any] struct{}
func (o *eitherPointed[E, A]) Of(a A) Either[E, A] {
return Of[E, A](a)
}
// Pointed implements the pointedic operations for [Either]
func Pointed[E, A any]() pointed.Pointed[A, Either[E, A]] {
return &eitherPointed[E, A]{}
}

View File

@@ -32,6 +32,11 @@ func ToReader[R io.Reader](r R) io.Reader {
return r
}
// ToWriter converts a [io.Writer]
func ToWriter[W io.Writer](w W) io.Writer {
return w
}
// ToCloser converts a [io.Closer]
func ToCloser[C io.Closer](c C) io.Closer {
return c

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2024-01-31 21:45:01.6437619 +0100 CET m=+0.032758901
// 2024-02-29 16:19:01.120389 +0100 CET m=+0.011216001
package function

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2024-01-31 21:44:55.7538323 +0100 CET m=+0.013067701
// 2024-02-29 16:18:53.6664566 +0100 CET m=+0.011085101
package function

8
go.mod
View File

@@ -3,15 +3,15 @@ module github.com/IBM/fp-go
go 1.20
require (
github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.27.1
github.com/stretchr/testify v1.11.1
github.com/urfave/cli/v2 v2.27.7
)
require (
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

32
go.sum
View File

@@ -1,17 +1,33 @@
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI=
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8=
github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8=
github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g=
github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=
github.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:30:50.5492271 +0200 CEST m=+0.023274501
// 2024-02-29 16:19:02.7798504 +0100 CET m=+0.021933401
package identity

View File

@@ -15,4 +15,4 @@
package apply
//go:generate go run ../.. apply --count 10 --filename gen.go
//go:generate go run ../.. apply --count 15 --filename gen.go

File diff suppressed because it is too large Load Diff

View File

@@ -17,6 +17,37 @@ package array
func Slice[GA ~[]A, A any](low, high int) func(as GA) GA {
return func(as GA) GA {
length := len(as)
// Handle negative indices - count backward from the end
if low < 0 {
low = length + low
if low < 0 {
low = 0
}
}
if high < 0 {
high = length + high
if high < 0 {
high = 0
}
}
// Start index > array length: return empty array
if low > length {
return Empty[GA, A]()
}
// End index > array length: slice to the end
if high > length {
high = length
}
// Start >= end: return empty array
if low >= high {
return Empty[GA, A]()
}
return as[low:high]
}
}

View File

@@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package file
package bracket
import (
F "github.com/IBM/fp-go/function"

198
internal/statet/state.go Normal file
View File

@@ -0,0 +1,198 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package state
import (
F "github.com/IBM/fp-go/function"
P "github.com/IBM/fp-go/pair"
)
func Of[
HKTSA ~func(S) HKTA,
HKTA,
S, A any,
](
fof func(P.Pair[A, S]) HKTA,
a A) HKTSA {
return F.Flow2(
F.Bind1st(P.MakePair[A, S], a),
fof,
)
}
func MonadMap[
HKTSA ~func(S) HKTA,
HKTSB ~func(S) HKTB,
HKTA,
HKTB,
S, A, B any,
](
fmap func(HKTA, func(P.Pair[A, S]) P.Pair[B, S]) HKTB,
fa HKTSA,
f func(A) B,
) HKTSB {
return F.Flow2(
fa,
F.Bind2nd(fmap, P.Map[S](f)),
)
}
func Map[
HKTSA ~func(S) HKTA,
HKTSB ~func(S) HKTB,
HKTA,
HKTB,
S, A, B any,
](
fmap func(func(P.Pair[A, S]) P.Pair[B, S]) func(HKTA) HKTB,
f func(A) B,
) func(HKTSA) HKTSB {
mp := fmap(P.Map[S](f))
return func(fa HKTSA) HKTSB {
return F.Flow2(
fa,
mp,
)
}
}
func MonadChain[
HKTSA ~func(S) HKTA,
HKTSB ~func(S) HKTB,
HKTA,
HKTB,
S, A any,
](
fchain func(HKTA, func(P.Pair[A, S]) HKTB) HKTB,
fa HKTSA,
f func(A) HKTSB,
) HKTSB {
return F.Flow2(
fa,
F.Bind2nd(fchain, func(a P.Pair[A, S]) HKTB {
return f(P.Head(a))(P.Tail(a))
}),
)
}
func Chain[
HKTSA ~func(S) HKTA,
HKTSB ~func(S) HKTB,
HKTA,
HKTB,
S, A any,
](
fchain func(func(P.Pair[A, S]) HKTB) func(HKTA) HKTB,
f func(A) HKTSB,
) func(HKTSA) HKTSB {
mp := fchain(func(a P.Pair[A, S]) HKTB {
return f(P.Head(a))(P.Tail(a))
})
return func(fa HKTSA) HKTSB {
return F.Flow2(
fa,
mp,
)
}
}
func MonadAp[
HKTSA ~func(S) HKTA,
HKTSB ~func(S) HKTB,
HKTSAB ~func(S) HKTAB,
HKTA,
HKTB,
HKTAB,
S, A, B any,
](
fmap func(HKTA, func(P.Pair[A, S]) P.Pair[B, S]) HKTB,
fchain func(HKTAB, func(P.Pair[func(A) B, S]) HKTB) HKTB,
fab HKTSAB,
fa HKTSA,
) HKTSB {
return func(s S) HKTB {
return fchain(fab(s), func(ab P.Pair[func(A) B, S]) HKTB {
return fmap(fa(P.Tail(ab)), P.Map[S](P.Head(ab)))
})
}
}
func Ap[
HKTSA ~func(S) HKTA,
HKTSB ~func(S) HKTB,
HKTSAB ~func(S) HKTAB,
HKTA,
HKTB,
HKTAB,
S, A, B any,
](
fmap func(func(P.Pair[A, S]) P.Pair[B, S]) func(HKTA) HKTB,
fchain func(func(P.Pair[func(A) B, S]) HKTB) func(HKTAB) HKTB,
fa HKTSA,
) func(HKTSAB) HKTSB {
return func(fab HKTSAB) HKTSB {
return F.Flow2(
fab,
fchain(func(ab P.Pair[func(A) B, S]) HKTB {
return fmap(P.Map[S](P.Head(ab)))(fa(P.Tail(ab)))
}),
)
}
}
func FromF[
HKTSA ~func(S) HKTA,
HKTA,
HKTFA,
S, A any,
](
fmap func(HKTFA, func(A) P.Pair[A, S]) HKTA,
ma HKTFA) HKTSA {
f1 := F.Bind1st(fmap, ma)
return func(s S) HKTA {
return f1(F.Bind2nd(P.MakePair[A, S], s))
}
}
func FromState[
HKTSA ~func(S) HKTA,
ST ~func(S) P.Pair[A, S],
HKTA,
S, A any,
](
fof func(P.Pair[A, S]) HKTA,
sa ST,
) HKTSA {
return F.Flow2(sa, fof)
}

View File

@@ -0,0 +1,183 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package testing
import (
"fmt"
"testing"
EQ "github.com/IBM/fp-go/eq"
F "github.com/IBM/fp-go/function"
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/pointed"
"github.com/stretchr/testify/assert"
)
// SequenceArrayTest tests if the sequence operation works in case the operation cannot error
func SequenceArrayTest[
HKTA,
HKTB,
HKTAA any, // HKT[[]A]
](
eq EQ.Eq[HKTB],
pa pointed.Pointed[string, HKTA],
pb pointed.Pointed[bool, HKTB],
faa functor.Functor[[]string, bool, HKTAA, HKTB],
seq func([]HKTA) HKTAA,
) func(count int) func(t *testing.T) {
return func(count int) func(t *testing.T) {
exp := make([]string, count)
good := make([]HKTA, count)
for i := 0; i < count; i++ {
val := fmt.Sprintf("TestData %d", i)
exp[i] = val
good[i] = pa.Of(val)
}
return func(t *testing.T) {
res := F.Pipe2(
good,
seq,
faa.Map(func(act []string) bool {
return assert.Equal(t, exp, act)
}),
)
assert.True(t, eq.Equals(res, pb.Of(true)))
}
}
}
// SequenceArrayErrorTest tests if the sequence operation works in case the operation can error
func SequenceArrayErrorTest[
HKTA,
HKTB,
HKTAA any, // HKT[[]A]
](
eq EQ.Eq[HKTB],
left func(error) HKTA,
leftB func(error) HKTB,
pa pointed.Pointed[string, HKTA],
pb pointed.Pointed[bool, HKTB],
faa functor.Functor[[]string, bool, HKTAA, HKTB],
seq func([]HKTA) HKTAA,
) func(count int) func(t *testing.T) {
return func(count int) func(t *testing.T) {
expGood := make([]string, count)
good := make([]HKTA, count)
expBad := make([]error, count)
bad := make([]HKTA, count)
for i := 0; i < count; i++ {
goodVal := fmt.Sprintf("TestData %d", i)
badVal := fmt.Errorf("ErrorData %d", i)
expGood[i] = goodVal
good[i] = pa.Of(goodVal)
expBad[i] = badVal
bad[i] = left(badVal)
}
total := 1 << count
return func(t *testing.T) {
// test the good case
res := F.Pipe2(
good,
seq,
faa.Map(func(act []string) bool {
return assert.Equal(t, expGood, act)
}),
)
assert.True(t, eq.Equals(res, pb.Of(true)))
// iterate and test the bad cases
for i := 1; i < total; i++ {
// run the test
t.Run(fmt.Sprintf("Bitmask test %d", i), func(t1 *testing.T) {
// the actual
act := make([]HKTA, count)
// the expected error
var exp error
// prepare the values bases on the bit mask
mask := 1
for j := 0; j < count; j++ {
if (i & mask) == 0 {
act[j] = good[j]
} else {
act[j] = bad[j]
if exp == nil {
exp = expBad[j]
}
}
mask <<= 1
}
// test the good case
res := F.Pipe2(
act,
seq,
faa.Map(func(act []string) bool {
return assert.Equal(t, expGood, act)
}),
)
// validate the error
assert.True(t, eq.Equals(res, leftB(exp)))
})
}
}
}
}
// SequenceRecordTest tests if the sequence operation works in case the operation cannot error
func SequenceRecordTest[
HKTA,
HKTB,
HKTAA any, // HKT[map[string]string]
](
eq EQ.Eq[HKTB],
pa pointed.Pointed[string, HKTA],
pb pointed.Pointed[bool, HKTB],
faa functor.Functor[map[string]string, bool, HKTAA, HKTB],
seq func(map[string]HKTA) HKTAA,
) func(count int) func(t *testing.T) {
return func(count int) func(t *testing.T) {
exp := make(map[string]string)
good := make(map[string]HKTA)
for i := 0; i < count; i++ {
key := fmt.Sprintf("KeyData %d", i)
val := fmt.Sprintf("ValueData %d", i)
exp[key] = val
good[key] = pa.Of(val)
}
return func(t *testing.T) {
res := F.Pipe2(
good,
seq,
faa.Map(func(act map[string]string) bool {
return assert.Equal(t, exp, act)
}),
)
assert.True(t, eq.Equals(res, pb.Of(true)))
}
}
}

View File

@@ -24,3 +24,8 @@ import (
func Eq[A any](e EQ.Eq[A]) EQ.Eq[IO[A]] {
return G.Eq[IO[A]](e)
}
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[A comparable]() EQ.Eq[IO[A]] {
return G.FromStrictEquals[IO[A]]()
}

26
io/functor.go Normal file
View File

@@ -0,0 +1,26 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io
import (
"github.com/IBM/fp-go/internal/functor"
G "github.com/IBM/fp-go/io/generic"
)
// Functor returns the monadic operations for [IO]
func Functor[A, B any]() functor.Functor[A, B, IO[A], IO[B]] {
return G.Functor[A, B, IO[A], IO[B]]()
}

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:30:56.7105551 +0200 CEST m=+0.011255201
// 2024-02-29 16:19:10.2607969 +0100 CET m=+0.024787801
package io

View File

@@ -27,16 +27,11 @@ const (
// MonadApSeq implements the applicative on a single thread by first executing mab and the ma
func MonadApSeq[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
return MakeIO[GB](func() B {
return F.Pipe1(
ma(),
mab(),
)
})
return MonadChain(mab, F.Bind1st(MonadMap[GA, GB], ma))
}
// MonadApPar implements the applicative on two threads, the main thread executes mab and the actuall
// apply operation and the second thred computes ma. Communication between the threads happens via a channel
// apply operation and the second thread computes ma. Communication between the threads happens via a channel
func MonadApPar[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
return MakeIO[GB](func() B {
c := make(chan A)

View File

@@ -33,3 +33,8 @@ func Eq[GA ~func() A, A any](e EQ.Eq[A]) EQ.Eq[GA] {
return eq(l, r)()
})
}
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[GA ~func() A, A comparable]() EQ.Eq[GA] {
return Eq[GA](EQ.FromStrictEquals[A]())
}

31
io/generic/functor.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"github.com/IBM/fp-go/internal/functor"
)
type ioFunctor[A, B any, GA ~func() A, GB ~func() B] struct{}
func (o *ioFunctor[A, B, GA, GB]) Map(f func(A) B) func(GA) GB {
return Map[GA, GB, A, B](f)
}
// Functor implements the functoric operations for [IO]
func Functor[A, B any, GA ~func() A, GB ~func() B]() functor.Functor[A, B, GA, GB] {
return &ioFunctor[A, B, GA, GB]{}
}

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:30:56.7105551 +0200 CEST m=+0.011255201
// 2024-02-29 16:19:10.2613281 +0100 CET m=+0.025319001
package generic
import (

31
io/generic/pointed.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"github.com/IBM/fp-go/internal/pointed"
)
type ioPointed[A any, GA ~func() A] struct{}
func (o *ioPointed[A, GA]) Of(a A) GA {
return Of[GA, A](a)
}
// Pointed implements the pointedic operations for [IO]
func Pointed[A any, GA ~func() A]() pointed.Pointed[A, GA] {
return &ioPointed[A, GA]{}
}

View File

@@ -32,6 +32,28 @@ func MonadTraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B
)
}
func MonadTraverseArraySeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](tas AAS, f func(A) GB) GBS {
return RA.MonadTraverse(
Of[GBS, BBS],
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
ApSeq[GBS, func() func(B) BBS, GB],
tas,
f,
)
}
func MonadTraverseArrayPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](tas AAS, f func(A) GB) GBS {
return RA.MonadTraverse(
Of[GBS, BBS],
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
ApPar[GBS, func() func(B) BBS, GB],
tas,
f,
)
}
func TraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
return RA.Traverse[AAS](
Of[GBS, BBS],
@@ -42,6 +64,26 @@ func TraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](
)
}
func TraverseArraySeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
return RA.Traverse[AAS](
Of[GBS, BBS],
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
ApSeq[GBS, func() func(B) BBS, GB],
f,
)
}
func TraverseArrayPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
return RA.Traverse[AAS](
Of[GBS, BBS],
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
ApPar[GBS, func() func(B) BBS, GB],
f,
)
}
func TraverseArrayWithIndex[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
return RA.TraverseWithIndex[AAS](
Of[GBS, BBS],
@@ -52,10 +94,38 @@ func TraverseArrayWithIndex[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A
)
}
func TraverseArrayWithIndexSeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
return RA.TraverseWithIndex[AAS](
Of[GBS, BBS],
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
ApSeq[GBS, func() func(B) BBS, GB],
f,
)
}
func TraverseArrayWithIndexPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
return RA.TraverseWithIndex[AAS](
Of[GBS, BBS],
Map[GBS, func() func(B) BBS, BBS, func(B) BBS],
ApPar[GBS, func() func(B) BBS, GB],
f,
)
}
func SequenceArray[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
return MonadTraverseArray[GA, GAS](tas, F.Identity[GA])
}
func SequenceArraySeq[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
return MonadTraverseArraySeq[GA, GAS](tas, F.Identity[GA])
}
func SequenceArrayPar[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
return MonadTraverseArrayPar[GA, GAS](tas, F.Identity[GA])
}
// MonadTraverseRecord transforms a record using an IO transform an IO of a record
func MonadTraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
return RR.MonadTraverse[MA](
@@ -89,3 +159,71 @@ func TraverseRecordWithIndex[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[
func SequenceRecord[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
return MonadTraverseRecord[GAS](tas, F.Identity[GA])
}
// MonadTraverseRecordSeq transforms a record using an IO transform an IO of a record
func MonadTraverseRecordSeq[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
return RR.MonadTraverse[MA](
Of[GBS, MB],
Map[GBS, func() func(B) MB, MB, func(B) MB],
ApSeq[GBS, func() func(B) MB, GB],
ma, f,
)
}
// TraverseRecordSeq transforms a record using an IO transform an IO of a record
func TraverseRecordSeq[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
return RR.Traverse[MA](
Of[GBS, MB],
Map[GBS, func() func(B) MB, MB, func(B) MB],
ApSeq[GBS, func() func(B) MB, GB],
f,
)
}
// TraverseRecordWithIndexSeq transforms a record using an IO transform an IO of a record
func TraverseRecordWithIndexSeq[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(K, A) GB) func(MA) GBS {
return RR.TraverseWithIndex[MA](
Of[GBS, MB],
Map[GBS, func() func(B) MB, MB, func(B) MB],
ApSeq[GBS, func() func(B) MB, GB],
f,
)
}
func SequenceRecordSeq[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
return MonadTraverseRecordSeq[GAS](tas, F.Identity[GA])
}
// MonadTraverseRecordPar transforms a record using an IO transform an IO of a record
func MonadTraverseRecordPar[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
return RR.MonadTraverse[MA](
Of[GBS, MB],
Map[GBS, func() func(B) MB, MB, func(B) MB],
ApPar[GBS, func() func(B) MB, GB],
ma, f,
)
}
// TraverseRecordPar transforms a record using an IO transform an IO of a record
func TraverseRecordPar[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
return RR.Traverse[MA](
Of[GBS, MB],
Map[GBS, func() func(B) MB, MB, func(B) MB],
ApPar[GBS, func() func(B) MB, GB],
f,
)
}
// TraverseRecordWithIndexPar transforms a record using an IO transform an IO of a record
func TraverseRecordWithIndexPar[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(K, A) GB) func(MA) GBS {
return RR.TraverseWithIndex[MA](
Of[GBS, MB],
Map[GBS, func() func(B) MB, MB, func(B) MB],
ApPar[GBS, func() func(B) MB, GB],
f,
)
}
func SequenceRecordPar[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
return MonadTraverseRecordPar[GAS](tas, F.Identity[GA])
}

26
io/pointed.go Normal file
View File

@@ -0,0 +1,26 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io
import (
"github.com/IBM/fp-go/internal/pointed"
G "github.com/IBM/fp-go/io/generic"
)
// Pointed returns the monadic operations for [IO]
func Pointed[A any]() pointed.Pointed[A, IO[A]] {
return G.Pointed[A, IO[A]]()
}

65
io/sequence_test.go Normal file
View File

@@ -0,0 +1,65 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io
import (
"fmt"
A "github.com/IBM/fp-go/array"
F "github.com/IBM/fp-go/function"
TST "github.com/IBM/fp-go/internal/testing"
"github.com/stretchr/testify/assert"
"testing"
)
func TestMapSeq(t *testing.T) {
var results []string
handler := func(value string) IO[string] {
return func() string {
results = append(results, value)
return value
}
}
src := A.From("a", "b", "c")
res := F.Pipe2(
src,
TraverseArraySeq(handler),
Map(func(data []string) bool {
return assert.Equal(t, data, results)
}),
)
assert.True(t, res())
}
func TestSequenceArray(t *testing.T) {
s := TST.SequenceArrayTest(
FromStrictEquals[bool](),
Pointed[string](),
Pointed[bool](),
Functor[[]string, bool](),
SequenceArray[string],
)
for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
}
}

View File

@@ -60,3 +60,45 @@ func TraverseRecordWithIndex[K comparable, A, B any](f func(K, A) IO[B]) func(ma
func SequenceRecord[K comparable, A any](tas map[K]IO[A]) IO[map[K]A] {
return G.SequenceRecord[IO[A], IO[map[K]A]](tas)
}
func MonadTraverseArraySeq[A, B any](tas []A, f func(A) IO[B]) IO[[]B] {
return G.MonadTraverseArraySeq[IO[B], IO[[]B]](tas, f)
}
// TraverseArraySeq applies a function returning an [IO] to all elements in an array and the
// transforms this into an [IO] of that array
func TraverseArraySeq[A, B any](f func(A) IO[B]) func([]A) IO[[]B] {
return G.TraverseArraySeq[IO[B], IO[[]B], []A](f)
}
// TraverseArrayWithIndexSeq applies a function returning an [IO] to all elements in an array and the
// transforms this into an [IO] of that array
func TraverseArrayWithIndexSeq[A, B any](f func(int, A) IO[B]) func([]A) IO[[]B] {
return G.TraverseArrayWithIndexSeq[IO[B], IO[[]B], []A](f)
}
// SequenceArraySeq converts an array of [IO] to an [IO] of an array
func SequenceArraySeq[A any](tas []IO[A]) IO[[]A] {
return G.SequenceArraySeq[IO[A], IO[[]A]](tas)
}
func MonadTraverseRecordSeq[K comparable, A, B any](tas map[K]A, f func(A) IO[B]) IO[map[K]B] {
return G.MonadTraverseRecordSeq[IO[map[K]B]](tas, f)
}
// TraverseRecord applies a function returning an [IO] to all elements in a record and the
// transforms this into an [IO] of that record
func TraverseRecordSeq[K comparable, A, B any](f func(A) IO[B]) func(map[K]A) IO[map[K]B] {
return G.TraverseRecordSeq[IO[map[K]B], map[K]A, IO[B]](f)
}
// TraverseRecordWithIndexSeq applies a function returning an [IO] to all elements in a record and the
// transforms this into an [IO] of that record
func TraverseRecordWithIndeSeq[K comparable, A, B any](f func(K, A) IO[B]) func(map[K]A) IO[map[K]B] {
return G.TraverseRecordWithIndexSeq[IO[B], IO[map[K]B], map[K]A](f)
}
// SequenceRecordSeq converts a record of [IO] to an [IO] of a record
func SequenceRecordSeq[K comparable, A any](tas map[K]IO[A]) IO[map[K]A] {
return G.SequenceRecordSeq[IO[A], IO[map[K]A]](tas)
}

View File

@@ -18,20 +18,23 @@ package file
import (
"io"
FL "github.com/IBM/fp-go/file"
F "github.com/IBM/fp-go/function"
IOE "github.com/IBM/fp-go/ioeither"
)
func onReadAll[R io.Reader](r R) IOE.IOEither[error, []byte] {
return IOE.TryCatchError(func() ([]byte, error) {
return io.ReadAll(r)
})
}
var (
// readAll is the adapted version of [io.ReadAll]
readAll = IOE.Eitherize1(io.ReadAll)
)
// ReadAll uses a generator function to create a stream, reads it and closes it
func ReadAll[R io.ReadCloser](acquire IOE.IOEither[error, R]) IOE.IOEither[error, []byte] {
return IOE.WithResource[[]byte](
acquire,
Close[R])(
onReadAll[R],
return F.Pipe1(
F.Flow2(
FL.ToReader[R],
readAll,
),
IOE.WithResource[[]byte](acquire, Close[R]),
)
}

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:30:58.6457744 +0200 CEST m=+0.080336501
// 2024-02-29 16:19:13.144922 +0100 CET m=+0.065757301
package ioeither

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:30:58.6556525 +0200 CEST m=+0.090214601
// 2024-02-29 16:19:13.1643755 +0100 CET m=+0.085210801
package generic
import (

68
ioeither/generic/monad.go Normal file
View File

@@ -0,0 +1,68 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
ET "github.com/IBM/fp-go/either"
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
)
type ioEitherPointed[E, A any, GA ~func() ET.Either[E, A]] struct{}
type ioEitherMonad[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B]] struct{}
type ioEitherFunctor[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B]] struct{}
func (o *ioEitherPointed[E, A, GA]) Of(a A) GA {
return Of[GA, E, A](a)
}
func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Of(a A) GA {
return Of[GA, E, A](a)
}
func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Map(f func(A) B) func(GA) GB {
return Map[GA, GB, E, A, B](f)
}
func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Chain(f func(A) GB) func(GA) GB {
return Chain[GA, GB, E, A, B](f)
}
func (o *ioEitherMonad[E, A, B, GA, GB, GAB]) Ap(fa GA) func(GAB) GB {
return Ap[GB, GAB, GA, E, A, B](fa)
}
func (o *ioEitherFunctor[E, A, B, GA, GB]) Map(f func(A) B) func(GA) GB {
return Map[GA, GB, E, A, B](f)
}
// Pointed implements the pointed operations for [IOEither]
func Pointed[E, A any, GA ~func() ET.Either[E, A]]() pointed.Pointed[A, GA] {
return &ioEitherPointed[E, A, GA]{}
}
// Functor implements the monadic operations for [IOEither]
func Functor[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B]]() functor.Functor[A, B, GA, GB] {
return &ioEitherFunctor[E, A, B, GA, GB]{}
}
// Monad implements the monadic operations for [IOEither]
func Monad[E, A, B any, GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B]]() monad.Monad[A, B, GA, GB, GAB] {
return &ioEitherMonad[E, A, B, GA, GB, GAB]{}
}

38
ioeither/monad.go Normal file
View File

@@ -0,0 +1,38 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ioeither
import (
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
G "github.com/IBM/fp-go/ioeither/generic"
)
// Pointed returns the pointed operations for [IOEither]
func Pointed[E, A any]() pointed.Pointed[A, IOEither[E, A]] {
return G.Pointed[E, A, IOEither[E, A]]()
}
// Functor returns the functor operations for [IOEither]
func Functor[E, A, B any]() functor.Functor[A, B, IOEither[E, A], IOEither[E, B]] {
return G.Functor[E, A, B, IOEither[E, A], IOEither[E, B]]()
}
// Monad returns the monadic operations for [IOEither]
func Monad[E, A, B any]() monad.Monad[A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]] {
return G.Monad[E, A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]]()
}

82
ioeither/sequence_test.go Normal file
View File

@@ -0,0 +1,82 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ioeither
import (
"fmt"
A "github.com/IBM/fp-go/array"
E "github.com/IBM/fp-go/either"
F "github.com/IBM/fp-go/function"
"github.com/stretchr/testify/assert"
TST "github.com/IBM/fp-go/internal/testing"
"testing"
)
func TestMapSeq(t *testing.T) {
var results []string
handler := func(value string) IOEither[error, string] {
return func() E.Either[error, string] {
results = append(results, value)
return E.Of[error](value)
}
}
src := A.From("a", "b", "c")
res := F.Pipe2(
src,
TraverseArraySeq(handler),
Map[error](func(data []string) bool {
return assert.Equal(t, data, results)
}),
)
assert.Equal(t, E.Of[error](true), res())
}
func TestSequenceArray(t *testing.T) {
s := TST.SequenceArrayTest(
FromStrictEquals[error, bool](),
Pointed[error, string](),
Pointed[error, bool](),
Functor[error, []string, bool](),
SequenceArray[error, string],
)
for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
}
}
func TestSequenceArrayError(t *testing.T) {
s := TST.SequenceArrayErrorTest(
FromStrictEquals[error, bool](),
Left[string, error],
Left[bool, error],
Pointed[error, string](),
Pointed[error, bool](),
Functor[error, []string, bool](),
SequenceArray[error, string],
)
// run across four bits
s(4)(t)
}

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:31:01.9227118 +0200 CEST m=+0.009977901
// 2024-02-29 16:19:16.7939127 +0100 CET m=+0.053853301
package iooption

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:31:01.9227118 +0200 CEST m=+0.009977901
// 2024-02-29 16:19:16.8032769 +0100 CET m=+0.063217501
package generic
import (

View File

@@ -19,8 +19,7 @@ import (
G "github.com/IBM/fp-go/iterator/stateless/generic"
)
// DropWhile creates an [Iterator] that drops elements from the [Iterator] as long as the predicate is true; afterwards, returns every element.
// Note, the [Iterator] does not produce any output until the predicate first becomes false
// Cycle creates an [Iterator] containing an [Iterator] repeated an infinite number of times.
func Cycle[U any](ma Iterator[U]) Iterator[U] {
return G.Cycle[Iterator[U]](ma)
}

View File

@@ -16,25 +16,13 @@
package option
import (
"fmt"
"testing"
F "github.com/IBM/fp-go/function"
TST "github.com/IBM/fp-go/internal/testing"
"github.com/stretchr/testify/assert"
)
func TestSequenceArray(t *testing.T) {
one := Of(1)
two := Of(2)
res := F.Pipe1(
[]Option[int]{one, two},
SequenceArray[int],
)
assert.Equal(t, res, Of([]int{1, 2}))
}
func TestCompactArray(t *testing.T) {
ar := []Option[string]{
Of("ok"),
@@ -45,3 +33,18 @@ func TestCompactArray(t *testing.T) {
res := CompactArray(ar)
assert.Equal(t, 2, len(res))
}
func TestSequenceArray(t *testing.T) {
s := TST.SequenceArrayTest(
FromStrictEquals[bool](),
Pointed[string](),
Pointed[bool](),
Functor[[]string, bool](),
SequenceArray[string],
)
for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
}
}

View File

@@ -35,7 +35,7 @@ type Option[A any] struct {
// optString prints some debug info for the object
//
// go:noinline
//go:noinline
func optString(isSome bool, value any) string {
if isSome {
return fmt.Sprintf("Some[%T](%v)", value, value)
@@ -45,7 +45,7 @@ func optString(isSome bool, value any) string {
// optFormat prints some debug info for the object
//
// go:noinline
//go:noinline
func optFormat(isSome bool, value any, f fmt.State, c rune) {
switch c {
case 's':
@@ -78,7 +78,7 @@ func (s Option[A]) MarshalJSON() ([]byte, error) {
// optUnmarshalJSON unmarshals the [Option] from a JSON string
//
// go:noinline
//go:noinline
func optUnmarshalJSON(isSome *bool, value any, data []byte) error {
// decode the value
if bytes.Equal(data, jsonNull) {

31
option/functor.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package option
import (
"github.com/IBM/fp-go/internal/functor"
)
type optionFunctor[A, B any] struct{}
func (o *optionFunctor[A, B]) Map(f func(A) B) func(Option[A]) Option[B] {
return Map[A, B](f)
}
// Functor implements the functoric operations for [Option]
func Functor[A, B any]() functor.Functor[A, B, Option[A], Option[B]] {
return &optionFunctor[A, B]{}
}

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:31:07.8687134 +0200 CEST m=+0.012222901
// 2024-02-29 16:19:19.6336283 +0100 CET m=+0.018011101
package option

31
option/pointed.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package option
import (
"github.com/IBM/fp-go/internal/pointed"
)
type optionPointed[A any] struct{}
func (o *optionPointed[A]) Of(a A) Option[A] {
return Of[A](a)
}
// Pointed implements the Pointed operations for [Option]
func Pointed[A any]() pointed.Pointed[A, Option[A]] {
return &optionPointed[A]{}
}

View File

@@ -16,21 +16,13 @@
package option
import (
"fmt"
"testing"
TST "github.com/IBM/fp-go/internal/testing"
"github.com/stretchr/testify/assert"
)
func TestSequenceRecord(t *testing.T) {
assert.Equal(t, Of(map[string]string{
"a": "A",
"b": "B",
}), SequenceRecord(map[string]Option[string]{
"a": Of("A"),
"b": Of("B"),
}))
}
func TestCompactRecord(t *testing.T) {
// make the map
m := make(map[string]Option[int])
@@ -45,3 +37,18 @@ func TestCompactRecord(t *testing.T) {
assert.Equal(t, exp, m1)
}
func TestSequenceRecord(t *testing.T) {
s := TST.SequenceRecordTest(
FromStrictEquals[bool](),
Pointed[string](),
Pointed[bool](),
Functor[map[string]string, bool](),
SequenceRecord[string, string],
)
for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceRecord %d", i), s(i))
}
}

View File

@@ -64,7 +64,7 @@ func Reverse[T any](o Ord[T]) Ord[T] {
}, o.Equals)
}
// Contramap creates an odering under a transformation function
// Contramap creates an ordering under a transformation function
func Contramap[A, B any](f func(B) A) func(Ord[A]) Ord[B] {
return func(o Ord[A]) Ord[B] {
return MakeOrd(func(x, y B) int {

View File

@@ -34,14 +34,14 @@ type (
// String prints some debug info for the object
//
// go:noinline
//go:noinline
func pairString(s *pair) string {
return fmt.Sprintf("Pair[%T, %t](%v, %v)", s.h, s.t, s.h, s.t)
return fmt.Sprintf("Pair[%T, %T](%v, %v)", s.h, s.t, s.h, s.t)
}
// Format prints some debug info for the object
//
// go:noinline
//go:noinline
func pairFormat(e *pair, f fmt.State, c rune) {
switch c {
case 's':

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:31:13.0131834 +0200 CEST m=+0.010996501
// 2024-02-29 16:19:26.0521202 +0100 CET m=+0.018000401
package reader

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:31:13.0131834 +0200 CEST m=+0.010996501
// 2024-02-29 16:19:26.0521202 +0100 CET m=+0.018000401
package generic
// From0 converts a function with 1 parameters returning a [R] into a function with 0 parameters returning a [GRA]

View File

@@ -17,11 +17,13 @@ package readerioeither
import (
"context"
"fmt"
"testing"
A "github.com/IBM/fp-go/array"
ET "github.com/IBM/fp-go/either"
F "github.com/IBM/fp-go/function"
TST "github.com/IBM/fp-go/internal/testing"
"github.com/stretchr/testify/assert"
)
@@ -37,3 +39,33 @@ func TestTraverseArray(t *testing.T) {
assert.Equal(t, ET.Right[string]([]string{"aa", "bb"}), F.Pipe1([]string{"a", "b"}, f)(ctx)())
assert.Equal(t, ET.Left[[]string]("e"), F.Pipe1([]string{"a", ""}, f)(ctx)())
}
func TestSequenceArray(t *testing.T) {
s := TST.SequenceArrayTest(
FromStrictEquals[context.Context, error, bool]()(context.Background()),
Pointed[context.Context, error, string](),
Pointed[context.Context, error, bool](),
Functor[context.Context, error, []string, bool](),
SequenceArray[context.Context, error, string],
)
for i := 0; i < 10; i++ {
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
}
}
func TestSequenceArrayError(t *testing.T) {
s := TST.SequenceArrayErrorTest(
FromStrictEquals[context.Context, error, bool]()(context.Background()),
Left[context.Context, string, error],
Left[context.Context, bool, error],
Pointed[context.Context, error, string](),
Pointed[context.Context, error, bool](),
Functor[context.Context, error, []string, bool](),
SequenceArray[context.Context, error, string],
)
// run across four bits
s(4)(t)
}

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:31:16.2414489 +0200 CEST m=+0.013052301
// 2024-05-24 17:26:07.2835624 +0200 CEST m=+0.011499301
package readerioeither
@@ -20,6 +20,12 @@ func Eitherize0[F ~func(C) (R, error), C, R any](f F) func() ReaderIOEither[C, e
return G.Eitherize0[ReaderIOEither[C, error, R]](f)
}
// Uneitherize0 converts a function with 1 parameters returning a [ReaderIOEither[C, error, R]] into a function with 0 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize0[F ~func() ReaderIOEither[C, error, R], C, R any](f F) func(C) (R, error) {
return G.Uneitherize0[ReaderIOEither[C, error, R], func(C) (R, error)](f)
}
// From1 converts a function with 2 parameters returning a tuple into a function with 1 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From1[F ~func(C, T0) func() (R, error), T0, C, R any](f F) func(T0) ReaderIOEither[C, error, R] {
@@ -32,6 +38,12 @@ func Eitherize1[F ~func(C, T0) (R, error), T0, C, R any](f F) func(T0) ReaderIOE
return G.Eitherize1[ReaderIOEither[C, error, R]](f)
}
// Uneitherize1 converts a function with 2 parameters returning a [ReaderIOEither[C, error, R]] into a function with 1 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize1[F ~func(T0) ReaderIOEither[C, error, R], T0, C, R any](f F) func(C, T0) (R, error) {
return G.Uneitherize1[ReaderIOEither[C, error, R], func(C, T0) (R, error)](f)
}
// From2 converts a function with 3 parameters returning a tuple into a function with 2 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From2[F ~func(C, T0, T1) func() (R, error), T0, T1, C, R any](f F) func(T0, T1) ReaderIOEither[C, error, R] {
@@ -44,6 +56,12 @@ func Eitherize2[F ~func(C, T0, T1) (R, error), T0, T1, C, R any](f F) func(T0, T
return G.Eitherize2[ReaderIOEither[C, error, R]](f)
}
// Uneitherize2 converts a function with 3 parameters returning a [ReaderIOEither[C, error, R]] into a function with 2 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize2[F ~func(T0, T1) ReaderIOEither[C, error, R], T0, T1, C, R any](f F) func(C, T0, T1) (R, error) {
return G.Uneitherize2[ReaderIOEither[C, error, R], func(C, T0, T1) (R, error)](f)
}
// From3 converts a function with 4 parameters returning a tuple into a function with 3 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From3[F ~func(C, T0, T1, T2) func() (R, error), T0, T1, T2, C, R any](f F) func(T0, T1, T2) ReaderIOEither[C, error, R] {
@@ -56,6 +74,12 @@ func Eitherize3[F ~func(C, T0, T1, T2) (R, error), T0, T1, T2, C, R any](f F) fu
return G.Eitherize3[ReaderIOEither[C, error, R]](f)
}
// Uneitherize3 converts a function with 4 parameters returning a [ReaderIOEither[C, error, R]] into a function with 3 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize3[F ~func(T0, T1, T2) ReaderIOEither[C, error, R], T0, T1, T2, C, R any](f F) func(C, T0, T1, T2) (R, error) {
return G.Uneitherize3[ReaderIOEither[C, error, R], func(C, T0, T1, T2) (R, error)](f)
}
// From4 converts a function with 5 parameters returning a tuple into a function with 4 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From4[F ~func(C, T0, T1, T2, T3) func() (R, error), T0, T1, T2, T3, C, R any](f F) func(T0, T1, T2, T3) ReaderIOEither[C, error, R] {
@@ -68,6 +92,12 @@ func Eitherize4[F ~func(C, T0, T1, T2, T3) (R, error), T0, T1, T2, T3, C, R any]
return G.Eitherize4[ReaderIOEither[C, error, R]](f)
}
// Uneitherize4 converts a function with 5 parameters returning a [ReaderIOEither[C, error, R]] into a function with 4 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize4[F ~func(T0, T1, T2, T3) ReaderIOEither[C, error, R], T0, T1, T2, T3, C, R any](f F) func(C, T0, T1, T2, T3) (R, error) {
return G.Uneitherize4[ReaderIOEither[C, error, R], func(C, T0, T1, T2, T3) (R, error)](f)
}
// From5 converts a function with 6 parameters returning a tuple into a function with 5 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From5[F ~func(C, T0, T1, T2, T3, T4) func() (R, error), T0, T1, T2, T3, T4, C, R any](f F) func(T0, T1, T2, T3, T4) ReaderIOEither[C, error, R] {
@@ -80,6 +110,12 @@ func Eitherize5[F ~func(C, T0, T1, T2, T3, T4) (R, error), T0, T1, T2, T3, T4, C
return G.Eitherize5[ReaderIOEither[C, error, R]](f)
}
// Uneitherize5 converts a function with 6 parameters returning a [ReaderIOEither[C, error, R]] into a function with 5 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize5[F ~func(T0, T1, T2, T3, T4) ReaderIOEither[C, error, R], T0, T1, T2, T3, T4, C, R any](f F) func(C, T0, T1, T2, T3, T4) (R, error) {
return G.Uneitherize5[ReaderIOEither[C, error, R], func(C, T0, T1, T2, T3, T4) (R, error)](f)
}
// From6 converts a function with 7 parameters returning a tuple into a function with 6 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From6[F ~func(C, T0, T1, T2, T3, T4, T5) func() (R, error), T0, T1, T2, T3, T4, T5, C, R any](f F) func(T0, T1, T2, T3, T4, T5) ReaderIOEither[C, error, R] {
@@ -92,6 +128,12 @@ func Eitherize6[F ~func(C, T0, T1, T2, T3, T4, T5) (R, error), T0, T1, T2, T3, T
return G.Eitherize6[ReaderIOEither[C, error, R]](f)
}
// Uneitherize6 converts a function with 7 parameters returning a [ReaderIOEither[C, error, R]] into a function with 6 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize6[F ~func(T0, T1, T2, T3, T4, T5) ReaderIOEither[C, error, R], T0, T1, T2, T3, T4, T5, C, R any](f F) func(C, T0, T1, T2, T3, T4, T5) (R, error) {
return G.Uneitherize6[ReaderIOEither[C, error, R], func(C, T0, T1, T2, T3, T4, T5) (R, error)](f)
}
// From7 converts a function with 8 parameters returning a tuple into a function with 7 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From7[F ~func(C, T0, T1, T2, T3, T4, T5, T6) func() (R, error), T0, T1, T2, T3, T4, T5, T6, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) ReaderIOEither[C, error, R] {
@@ -104,6 +146,12 @@ func Eitherize7[F ~func(C, T0, T1, T2, T3, T4, T5, T6) (R, error), T0, T1, T2, T
return G.Eitherize7[ReaderIOEither[C, error, R]](f)
}
// Uneitherize7 converts a function with 8 parameters returning a [ReaderIOEither[C, error, R]] into a function with 7 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) ReaderIOEither[C, error, R], T0, T1, T2, T3, T4, T5, T6, C, R any](f F) func(C, T0, T1, T2, T3, T4, T5, T6) (R, error) {
return G.Uneitherize7[ReaderIOEither[C, error, R], func(C, T0, T1, T2, T3, T4, T5, T6) (R, error)](f)
}
// From8 converts a function with 9 parameters returning a tuple into a function with 8 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From8[F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7) func() (R, error), T0, T1, T2, T3, T4, T5, T6, T7, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) ReaderIOEither[C, error, R] {
@@ -116,6 +164,12 @@ func Eitherize8[F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7) (R, error), T0, T1, T
return G.Eitherize8[ReaderIOEither[C, error, R]](f)
}
// Uneitherize8 converts a function with 9 parameters returning a [ReaderIOEither[C, error, R]] into a function with 8 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) ReaderIOEither[C, error, R], T0, T1, T2, T3, T4, T5, T6, T7, C, R any](f F) func(C, T0, T1, T2, T3, T4, T5, T6, T7) (R, error) {
return G.Uneitherize8[ReaderIOEither[C, error, R], func(C, T0, T1, T2, T3, T4, T5, T6, T7) (R, error)](f)
}
// From9 converts a function with 10 parameters returning a tuple into a function with 9 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From9[F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8) func() (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) ReaderIOEither[C, error, R] {
@@ -128,6 +182,12 @@ func Eitherize9[F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error), T0, T
return G.Eitherize9[ReaderIOEither[C, error, R]](f)
}
// Uneitherize9 converts a function with 10 parameters returning a [ReaderIOEither[C, error, R]] into a function with 9 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) ReaderIOEither[C, error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, C, R any](f F) func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error) {
return G.Uneitherize9[ReaderIOEither[C, error, R], func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error)](f)
}
// From10 converts a function with 11 parameters returning a tuple into a function with 10 parameters returning a [ReaderIOEither[R]]
// The first parameter is considered to be the context [C].
func From10[F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) func() (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) ReaderIOEither[C, error, R] {
@@ -139,3 +199,9 @@ func From10[F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) func() (R, error)
func Eitherize10[F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) ReaderIOEither[C, error, R] {
return G.Eitherize10[ReaderIOEither[C, error, R]](f)
}
// Uneitherize10 converts a function with 11 parameters returning a [ReaderIOEither[C, error, R]] into a function with 10 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) ReaderIOEither[C, error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, C, R any](f F) func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error) {
return G.Uneitherize10[ReaderIOEither[C, error, R], func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error)](f)
}

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2023-10-23 08:31:16.241979 +0200 CEST m=+0.013582401
// 2024-05-24 17:26:07.2835624 +0200 CEST m=+0.011499301
package generic
import (
@@ -26,6 +26,14 @@ func Eitherize0[GRA ~func(C) GIOA, F ~func(C) (R, error), GIOA ~func() E.Either[
})
}
// Uneitherize0 converts a function with 0 parameters returning a [GRA] into a function with 0 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize0[GRA ~func(C) GIOA, F ~func(C) (R, error), GIOA ~func() E.Either[error, R], C, R any](f func() GRA) F {
return func(c C) (R, error) {
return E.UnwrapError(f()(c)())
}
}
// From1 converts a function with 2 parameters returning a tuple into a function with 1 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From1[GRA ~func(C) GIOA, F ~func(C, T0) func() (R, error), GIOA ~func() E.Either[error, R], T0, C, R any](f F) func(T0) GRA {
@@ -44,6 +52,14 @@ func Eitherize1[GRA ~func(C) GIOA, F ~func(C, T0) (R, error), GIOA ~func() E.Eit
})
}
// Uneitherize1 converts a function with 1 parameters returning a [GRA] into a function with 1 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize1[GRA ~func(C) GIOA, F ~func(C, T0) (R, error), GIOA ~func() E.Either[error, R], T0, C, R any](f func(T0) GRA) F {
return func(c C, t0 T0) (R, error) {
return E.UnwrapError(f(t0)(c)())
}
}
// From2 converts a function with 3 parameters returning a tuple into a function with 2 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From2[GRA ~func(C) GIOA, F ~func(C, T0, T1) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, C, R any](f F) func(T0, T1) GRA {
@@ -62,6 +78,14 @@ func Eitherize2[GRA ~func(C) GIOA, F ~func(C, T0, T1) (R, error), GIOA ~func() E
})
}
// Uneitherize2 converts a function with 2 parameters returning a [GRA] into a function with 2 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize2[GRA ~func(C) GIOA, F ~func(C, T0, T1) (R, error), GIOA ~func() E.Either[error, R], T0, T1, C, R any](f func(T0, T1) GRA) F {
return func(c C, t0 T0, t1 T1) (R, error) {
return E.UnwrapError(f(t0, t1)(c)())
}
}
// From3 converts a function with 4 parameters returning a tuple into a function with 3 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From3[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, C, R any](f F) func(T0, T1, T2) GRA {
@@ -80,6 +104,14 @@ func Eitherize3[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2) (R, error), GIOA ~func
})
}
// Uneitherize3 converts a function with 3 parameters returning a [GRA] into a function with 3 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize3[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, C, R any](f func(T0, T1, T2) GRA) F {
return func(c C, t0 T0, t1 T1, t2 T2) (R, error) {
return E.UnwrapError(f(t0, t1, t2)(c)())
}
}
// From4 converts a function with 5 parameters returning a tuple into a function with 4 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From4[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, C, R any](f F) func(T0, T1, T2, T3) GRA {
@@ -98,6 +130,14 @@ func Eitherize4[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3) (R, error), GIOA ~
})
}
// Uneitherize4 converts a function with 4 parameters returning a [GRA] into a function with 4 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize4[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, C, R any](f func(T0, T1, T2, T3) GRA) F {
return func(c C, t0 T0, t1 T1, t2 T2, t3 T3) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3)(c)())
}
}
// From5 converts a function with 6 parameters returning a tuple into a function with 5 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From5[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, C, R any](f F) func(T0, T1, T2, T3, T4) GRA {
@@ -116,6 +156,14 @@ func Eitherize5[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4) (R, error), GI
})
}
// Uneitherize5 converts a function with 5 parameters returning a [GRA] into a function with 5 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize5[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, C, R any](f func(T0, T1, T2, T3, T4) GRA) F {
return func(c C, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4)(c)())
}
}
// From6 converts a function with 7 parameters returning a tuple into a function with 6 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From6[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, C, R any](f F) func(T0, T1, T2, T3, T4, T5) GRA {
@@ -134,6 +182,14 @@ func Eitherize6[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5) (R, error)
})
}
// Uneitherize6 converts a function with 6 parameters returning a [GRA] into a function with 6 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize6[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, C, R any](f func(T0, T1, T2, T3, T4, T5) GRA) F {
return func(c C, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5)(c)())
}
}
// From7 converts a function with 8 parameters returning a tuple into a function with 7 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From7[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) GRA {
@@ -152,6 +208,14 @@ func Eitherize7[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6) (R, er
})
}
// Uneitherize7 converts a function with 7 parameters returning a [GRA] into a function with 7 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize7[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, C, R any](f func(T0, T1, T2, T3, T4, T5, T6) GRA) F {
return func(c C, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5, t6)(c)())
}
}
// From8 converts a function with 9 parameters returning a tuple into a function with 8 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From8[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) GRA {
@@ -170,6 +234,14 @@ func Eitherize8[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7) (R
})
}
// Uneitherize8 converts a function with 8 parameters returning a [GRA] into a function with 8 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize8[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, C, R any](f func(T0, T1, T2, T3, T4, T5, T6, T7) GRA) F {
return func(c C, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7)(c)())
}
}
// From9 converts a function with 10 parameters returning a tuple into a function with 9 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From9[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) GRA {
@@ -188,6 +260,14 @@ func Eitherize9[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8
})
}
// Uneitherize9 converts a function with 9 parameters returning a [GRA] into a function with 9 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize9[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, C, R any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8) GRA) F {
return func(c C, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8)(c)())
}
}
// From10 converts a function with 11 parameters returning a tuple into a function with 10 parameters returning a [GRA]
// The first parameter is considerd to be the context [C].
func From10[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) func() (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, C, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) GRA {
@@ -205,3 +285,11 @@ func Eitherize10[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T
}
})
}
// Uneitherize10 converts a function with 10 parameters returning a [GRA] into a function with 10 parameters returning a tuple.
// The first parameter is considered to be the context [C].
func Uneitherize10[GRA ~func(C) GIOA, F ~func(C, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), GIOA ~func() E.Either[error, R], T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, C, R any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) GRA) F {
return func(c C, t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) (R, error) {
return E.UnwrapError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9)(c)())
}
}

View File

@@ -0,0 +1,68 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
ET "github.com/IBM/fp-go/either"
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
)
type readerIOEitherPointed[R, E, A any, GRA ~func(R) GIOA, GIOA ~func() ET.Either[E, A]] struct{}
type readerIOEitherMonad[R, E, A, B any, GRA ~func(R) GIOA, GRB ~func(R) GIOB, GRAB ~func(R) GIOAB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], GIOAB ~func() ET.Either[E, func(A) B]] struct{}
type readerIOEitherFunctor[R, E, A, B any, GRA ~func(R) GIOA, GRB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B]] struct{}
func (o *readerIOEitherPointed[R, E, A, GRA, GIOA]) Of(a A) GRA {
return Of[GRA, GIOA, R, E, A](a)
}
func (o *readerIOEitherMonad[R, E, A, B, GRA, GRB, GRAB, GIOA, GIOB, GIOAB]) Of(a A) GRA {
return Of[GRA, GIOA, R, E, A](a)
}
func (o *readerIOEitherMonad[R, E, A, B, GRA, GRB, GRAB, GIOA, GIOB, GIOAB]) Map(f func(A) B) func(GRA) GRB {
return Map[GRA, GRB, GIOA, GIOB, R, E, A, B](f)
}
func (o *readerIOEitherMonad[R, E, A, B, GRA, GRB, GRAB, GIOA, GIOB, GIOAB]) Chain(f func(A) GRB) func(GRA) GRB {
return Chain[GRA, GRB, GIOA, GIOB, R, E, A, B](f)
}
func (o *readerIOEitherMonad[R, E, A, B, GRA, GRB, GRAB, GIOA, GIOB, GIOAB]) Ap(fa GRA) func(GRAB) GRB {
return Ap[GRA, GRB, GRAB, GIOA, GIOB, GIOAB, R, E, A, B](fa)
}
func (o *readerIOEitherFunctor[R, E, A, B, GRA, GRB, GIOA, GIOB]) Map(f func(A) B) func(GRA) GRB {
return Map[GRA, GRB, GIOA, GIOB, R, E, A, B](f)
}
// Pointed implements the pointed operations for [ReaderIOEither]
func Pointed[R, E, A any, GRA ~func(R) GIOA, GIOA ~func() ET.Either[E, A]]() pointed.Pointed[A, GRA] {
return &readerIOEitherPointed[R, E, A, GRA, GIOA]{}
}
// Functor implements the monadic operations for [ReaderIOEither]
func Functor[R, E, A, B any, GRA ~func(R) GIOA, GRB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B]]() functor.Functor[A, B, GRA, GRB] {
return &readerIOEitherFunctor[R, E, A, B, GRA, GRB, GIOA, GIOB]{}
}
// Monad implements the monadic operations for [ReaderIOEither]
func Monad[R, E, A, B any, GRA ~func(R) GIOA, GRB ~func(R) GIOB, GRAB ~func(R) GIOAB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], GIOAB ~func() ET.Either[E, func(A) B]]() monad.Monad[A, B, GRA, GRB, GRAB] {
return &readerIOEitherMonad[R, E, A, B, GRA, GRB, GRAB, GIOA, GIOB, GIOAB]{}
}

View File

@@ -449,3 +449,15 @@ func MonadMapLeft[GREA1 ~func(R) GEA1, GREA2 ~func(R) GEA2, GEA1 ~func() ET.Eith
func MapLeft[GREA1 ~func(R) GEA1, GREA2 ~func(R) GEA2, GEA1 ~func() ET.Either[E1, A], GEA2 ~func() ET.Either[E2, A], R, E1, E2, A any](f func(E1) E2) func(GREA1) GREA2 {
return F.Bind2nd(MonadMapLeft[GREA1, GREA2], f)
}
// Local changes the value of the local context during the execution of the action `ma` (similar to `Contravariant`'s
// `contramap`).
func Local[
GEA1 ~func(R1) GIOA,
GEA2 ~func(R2) GIOA,
GIOA ~func() ET.Either[E, A],
R1, R2, E, A any,
](f func(R2) R1) func(GEA1) GEA2 {
return RD.Local[GEA1, GEA2](f)
}

38
readerioeither/monad.go Normal file
View File

@@ -0,0 +1,38 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package readerioeither
import (
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
G "github.com/IBM/fp-go/readerioeither/generic"
)
// Pointed returns the pointed operations for [ReaderIOEither]
func Pointed[R, E, A any]() pointed.Pointed[A, ReaderIOEither[R, E, A]] {
return G.Pointed[R, E, A, ReaderIOEither[R, E, A]]()
}
// Functor returns the functor operations for [ReaderIOEither]
func Functor[R, E, A, B any]() functor.Functor[A, B, ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]] {
return G.Functor[R, E, A, B, ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]]()
}
// Monad returns the monadic operations for [ReaderIOEither]
func Monad[R, E, A, B any]() monad.Monad[A, B, ReaderIOEither[R, E, A], ReaderIOEither[R, E, B], ReaderIOEither[R, E, func(A) B]] {
return G.Monad[R, E, A, B, ReaderIOEither[R, E, A], ReaderIOEither[R, E, B], ReaderIOEither[R, E, func(A) B]]()
}

View File

@@ -289,3 +289,9 @@ func MonadMapLeft[R, E1, E2, A any](fa ReaderIOEither[R, E1, A], f func(E1) E2)
func MapLeft[R, A, E1, E2 any](f func(E1) E2) func(ReaderIOEither[R, E1, A]) ReaderIOEither[R, E2, A] {
return G.MapLeft[ReaderIOEither[R, E1, A], ReaderIOEither[R, E2, A]](f)
}
// Local changes the value of the local context during the execution of the action `ma` (similar to `Contravariant`'s
// `contramap`).
func Local[R1, R2, E, A any](f func(R2) R1) func(ReaderIOEither[R1, E, A]) ReaderIOEither[R2, E, A] {
return G.Local[ReaderIOEither[R1, E, A], ReaderIOEither[R2, E, A]](f)
}

View File

@@ -23,3 +23,8 @@ import (
func Eq[K comparable, V any](e E.Eq[V]) E.Eq[map[K]V] {
return G.Eq[map[K]V, K, V](e)
}
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[K, V comparable]() E.Eq[map[K]V] {
return G.FromStrictEquals[map[K]V]()
}

48
record/eq_test.go Normal file
View File

@@ -0,0 +1,48 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package record
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFromStrictEquals(t *testing.T) {
m1 := map[string]string{
"a": "A",
"b": "B",
}
m2 := map[string]string{
"a": "A",
"b": "C",
}
m3 := map[string]string{
"a": "A",
"b": "B",
}
m4 := map[string]string{
"a": "A",
"b": "B",
"c": "C",
}
e := FromStrictEquals[string, string]()
assert.True(t, e.Equals(m1, m1))
assert.True(t, e.Equals(m1, m3))
assert.False(t, e.Equals(m1, m2))
assert.False(t, e.Equals(m1, m4))
}

View File

@@ -37,3 +37,8 @@ func Eq[M ~map[K]V, K comparable, V any](e E.Eq[V]) E.Eq[M] {
return equals(left, right, eq)
})
}
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[M ~map[K]V, K, V comparable]() E.Eq[M] {
return Eq[M](E.FromStrictEquals[V]())
}

View File

@@ -54,3 +54,69 @@ func TestUnionMonoid(t *testing.T) {
assert.Equal(t, res, m.Concat(x, y))
}
func TestUnionFirstMonoid(t *testing.T) {
m := UnionFirstMonoid[string, string]()
e := Empty[string, string]()
x := map[string]string{
"a": "a1",
"b": "b1",
"c": "c1",
}
y := map[string]string{
"b": "b2",
"c": "c2",
"d": "d2",
}
res := map[string]string{
"a": "a1",
"b": "b1",
"c": "c1",
"d": "d2",
}
assert.Equal(t, x, m.Concat(x, m.Empty()))
assert.Equal(t, x, m.Concat(m.Empty(), x))
assert.Equal(t, x, m.Concat(x, e))
assert.Equal(t, x, m.Concat(e, x))
assert.Equal(t, res, m.Concat(x, y))
}
func TestUnionLastMonoid(t *testing.T) {
m := UnionLastMonoid[string, string]()
e := Empty[string, string]()
x := map[string]string{
"a": "a1",
"b": "b1",
"c": "c1",
}
y := map[string]string{
"b": "b2",
"c": "c2",
"d": "d2",
}
res := map[string]string{
"a": "a1",
"b": "b2",
"c": "c2",
"d": "d2",
}
assert.Equal(t, x, m.Concat(x, m.Empty()))
assert.Equal(t, x, m.Concat(m.Empty(), x))
assert.Equal(t, x, m.Concat(x, e))
assert.Equal(t, x, m.Concat(e, x))
assert.Equal(t, res, m.Concat(x, y))
}

View File

@@ -176,3 +176,25 @@ func TestFromArrayMap(t *testing.T) {
"C": "C",
}, res2)
}
func TestEmpty(t *testing.T) {
nonEmpty := map[string]string{
"a": "A",
"b": "B",
}
empty := Empty[string, string]()
assert.True(t, IsEmpty(empty))
assert.False(t, IsEmpty(nonEmpty))
assert.False(t, IsNonEmpty(empty))
assert.True(t, IsNonEmpty(nonEmpty))
}
func TestHas(t *testing.T) {
nonEmpty := map[string]string{
"a": "A",
"b": "B",
}
assert.True(t, Has("a", nonEmpty))
assert.False(t, Has("c", nonEmpty))
}

View File

@@ -1,11 +1,20 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base",
"config:recommended",
":dependencyDashboard"
],
"rangeStrategy": "bump",
"packageRules": [
{
"matchDatasources": [
"golang-version"
],
"matchPackageNames": [
"go"
],
"enabled": false
},
{
"matchManagers": [
"gomod"

3
scan.bat Normal file
View File

@@ -0,0 +1,3 @@
@echo off
busybox find . -type f -name "*\.go" | busybox xargs gopls check

31
state/eq.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package state
import (
EQ "github.com/IBM/fp-go/eq"
G "github.com/IBM/fp-go/state/generic"
)
// Constructs an equal predicate for a [State]
func Eq[S, A any](w EQ.Eq[S], a EQ.Eq[A]) func(S) EQ.Eq[State[S, A]] {
return G.Eq[State[S, A]](w, a)
}
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[S, A comparable]() func(S) EQ.Eq[State[S, A]] {
return G.FromStrictEquals[State[S, A]]()
}

36
state/generic/eq.go Normal file
View File

@@ -0,0 +1,36 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
EQ "github.com/IBM/fp-go/eq"
P "github.com/IBM/fp-go/pair"
)
// Constructs an equal predicate for a [State]
func Eq[GA ~func(S) P.Pair[A, S], S, A any](w EQ.Eq[S], a EQ.Eq[A]) func(S) EQ.Eq[GA] {
eqp := P.Eq(a, w)
return func(s S) EQ.Eq[GA] {
return EQ.FromEquals(func(l, r GA) bool {
return eqp.Equals(l(s), r(s))
})
}
}
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[GA ~func(S) P.Pair[A, S], S, A comparable]() func(S) EQ.Eq[GA] {
return Eq[GA](EQ.FromStrictEquals[S](), EQ.FromStrictEquals[A]())
}

88
state/generic/monad.go Normal file
View File

@@ -0,0 +1,88 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"github.com/IBM/fp-go/internal/applicative"
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
P "github.com/IBM/fp-go/pair"
)
type statePointed[GA ~func(S) P.Pair[A, S], S, A any] struct{}
type stateFunctor[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], S, A, B any] struct{}
type stateApplicative[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any] struct{}
type stateMonad[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any] struct{}
func (o *statePointed[GA, S, A]) Of(a A) GA {
return Of[GA](a)
}
func (o *stateApplicative[GB, GAB, GA, S, A, B]) Of(a A) GA {
return Of[GA](a)
}
func (o *stateMonad[GB, GAB, GA, S, A, B]) Of(a A) GA {
return Of[GA](a)
}
func (o *stateFunctor[GB, GA, S, A, B]) Map(f func(A) B) func(GA) GB {
return Map[GB, GA](f)
}
func (o *stateApplicative[GB, GAB, GA, S, A, B]) Map(f func(A) B) func(GA) GB {
return Map[GB, GA](f)
}
func (o *stateMonad[GB, GAB, GA, S, A, B]) Map(f func(A) B) func(GA) GB {
return Map[GB, GA](f)
}
func (o *stateMonad[GB, GAB, GA, S, A, B]) Chain(f func(A) GB) func(GA) GB {
return Chain[GB, GA](f)
}
func (o *stateApplicative[GB, GAB, GA, S, A, B]) Ap(fa GA) func(GAB) GB {
return Ap[GB, GAB, GA](fa)
}
func (o *stateMonad[GB, GAB, GA, S, A, B]) Ap(fa GA) func(GAB) GB {
return Ap[GB, GAB, GA](fa)
}
// Pointed implements the pointed operations for [Writer]
func Pointed[GA ~func(S) P.Pair[A, S], S, A any]() pointed.Pointed[A, GA] {
return &statePointed[GA, S, A]{}
}
// Functor implements the functor operations for [Writer]
func Functor[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], S, A, B any]() functor.Functor[A, B, GA, GB] {
return &stateFunctor[GB, GA, S, A, B]{}
}
// Applicative implements the applicative operations for [Writer]
func Applicative[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any]() applicative.Applicative[A, B, GA, GB, GAB] {
return &stateApplicative[GB, GAB, GA, S, A, B]{}
}
// Monad implements the monadic operations for [Writer]
func Monad[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any]() monad.Monad[A, B, GA, GB, GAB] {
return &stateMonad[GB, GAB, GA, S, A, B]{}
}

131
state/generic/state.go Normal file
View File

@@ -0,0 +1,131 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
F "github.com/IBM/fp-go/function"
C "github.com/IBM/fp-go/internal/chain"
FC "github.com/IBM/fp-go/internal/functor"
P "github.com/IBM/fp-go/pair"
)
var (
undefined any = struct{}{}
)
func Get[GA ~func(S) P.Pair[S, S], S any]() GA {
return P.Of[S]
}
func Gets[GA ~func(S) P.Pair[A, S], FCT ~func(S) A, A, S any](f FCT) GA {
return func(s S) P.Pair[A, S] {
return P.MakePair(f(s), s)
}
}
func Put[GA ~func(S) P.Pair[any, S], S any]() GA {
return F.Bind1st(P.MakePair[any, S], undefined)
}
func Modify[GA ~func(S) P.Pair[any, S], FCT ~func(S) S, S any](f FCT) GA {
return F.Flow2(
f,
F.Bind1st(P.MakePair[any, S], undefined),
)
}
func Of[GA ~func(S) P.Pair[A, S], S, A any](a A) GA {
return F.Bind1st(P.MakePair[A, S], a)
}
func MonadMap[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) B, S, A, B any](fa GA, f FCT) GB {
return func(s S) P.Pair[B, S] {
p2 := fa(s)
return P.MakePair(f(P.Head(p2)), P.Tail(p2))
}
}
func Map[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) B, S, A, B any](f FCT) func(GA) GB {
return F.Bind2nd(MonadMap[GB, GA, FCT, S, A, B], f)
}
func MonadChain[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) GB, S, A, B any](fa GA, f FCT) GB {
return func(s S) P.Pair[B, S] {
a := fa(s)
return f(P.Head(a))(P.Tail(a))
}
}
func Chain[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) GB, S, A, B any](f FCT) func(GA) GB {
return F.Bind2nd(MonadChain[GB, GA, FCT, S, A, B], f)
}
func MonadAp[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any](fab GAB, fa GA) GB {
return func(s S) P.Pair[B, S] {
f := fab(s)
a := fa(P.Tail(f))
return P.MakePair(P.Head(f)(P.Head(a)), P.Tail(a))
}
}
func Ap[GB ~func(S) P.Pair[B, S], GAB ~func(S) P.Pair[func(A) B, S], GA ~func(S) P.Pair[A, S], S, A, B any](ga GA) func(GAB) GB {
return F.Bind2nd(MonadAp[GB, GAB, GA, S, A, B], ga)
}
func MonadChainFirst[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) GB, S, A, B any](ma GA, f FCT) GA {
return C.MonadChainFirst(
MonadChain[GA, GA, func(A) GA],
MonadMap[GA, GB, func(B) A],
ma,
f,
)
}
func ChainFirst[GB ~func(S) P.Pair[B, S], GA ~func(S) P.Pair[A, S], FCT ~func(A) GB, S, A, B any](f FCT) func(GA) GA {
return C.ChainFirst(
Chain[GA, GA, func(A) GA],
Map[GA, GB, func(B) A],
f,
)
}
func Flatten[GAA ~func(S) P.Pair[GA, S], GA ~func(S) P.Pair[A, S], S, A any](mma GAA) GA {
return MonadChain[GA, GAA, func(GA) GA](mma, F.Identity[GA])
}
func Execute[GA ~func(S) P.Pair[A, S], S, A any](s S) func(GA) S {
return func(fa GA) S {
return P.Tail(fa(s))
}
}
func Evaluate[GA ~func(S) P.Pair[A, S], S, A any](s S) func(GA) A {
return func(fa GA) A {
return P.Head(fa(s))
}
}
func MonadFlap[FAB ~func(A) B, GFAB ~func(S) P.Pair[FAB, S], GB ~func(S) P.Pair[B, S], S, A, B any](fab GFAB, a A) GB {
return FC.MonadFlap(
MonadMap[GB, GFAB, func(FAB) B],
fab,
a)
}
func Flap[FAB ~func(A) B, GFAB ~func(S) P.Pair[FAB, S], GB ~func(S) P.Pair[B, S], S, A, B any](a A) func(GFAB) GB {
return FC.Flap(Map[GB, GFAB, func(FAB) B], a)
}

44
state/monad.go Normal file
View File

@@ -0,0 +1,44 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package state
import (
"github.com/IBM/fp-go/internal/applicative"
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
G "github.com/IBM/fp-go/state/generic"
)
// Pointed implements the pointed operations for [State]
func Pointed[S, A any]() pointed.Pointed[A, State[S, A]] {
return G.Pointed[State[S, A], S, A]()
}
// Functor implements the pointed operations for [State]
func Functor[S, A, B any]() functor.Functor[A, B, State[S, A], State[S, B]] {
return G.Functor[State[S, B], State[S, A], S, A, B]()
}
// Applicative implements the applicative operations for [State]
func Applicative[S, A, B any]() applicative.Applicative[A, B, State[S, A], State[S, B], State[S, func(A) B]] {
return G.Applicative[State[S, B], State[S, func(A) B], State[S, A]]()
}
// Monad implements the monadic operations for [State]
func Monad[S, A, B any]() monad.Monad[A, B, State[S, A], State[S, B], State[S, func(A) B]] {
return G.Monad[State[S, B], State[S, func(A) B], State[S, A]]()
}

97
state/state.go Normal file
View File

@@ -0,0 +1,97 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package state
import (
P "github.com/IBM/fp-go/pair"
R "github.com/IBM/fp-go/reader"
G "github.com/IBM/fp-go/state/generic"
)
// State represents an operation on top of a current [State] that produces a value and a new [State]
type State[S, A any] R.Reader[S, P.Pair[A, S]]
func Get[S any]() State[S, S] {
return G.Get[State[S, S]]()
}
func Gets[FCT ~func(S) A, A, S any](f FCT) State[S, A] {
return G.Gets[State[S, A]](f)
}
func Put[S any]() State[S, any] {
return G.Put[State[S, any]]()
}
func Modify[FCT ~func(S) S, S any](f FCT) State[S, any] {
return G.Modify[State[S, any]](f)
}
func Of[S, A any](a A) State[S, A] {
return G.Of[State[S, A]](a)
}
func MonadMap[S any, FCT ~func(A) B, A, B any](fa State[S, A], f FCT) State[S, B] {
return G.MonadMap[State[S, B], State[S, A]](fa, f)
}
func Map[S any, FCT ~func(A) B, A, B any](f FCT) func(State[S, A]) State[S, B] {
return G.Map[State[S, B], State[S, A]](f)
}
func MonadChain[S any, FCT ~func(A) State[S, B], A, B any](fa State[S, A], f FCT) State[S, B] {
return G.MonadChain[State[S, B], State[S, A]](fa, f)
}
func Chain[S any, FCT ~func(A) State[S, B], A, B any](f FCT) func(State[S, A]) State[S, B] {
return G.Chain[State[S, B], State[S, A]](f)
}
func MonadAp[S, A, B any](fab State[S, func(A) B], fa State[S, A]) State[S, B] {
return G.MonadAp[State[S, B], State[S, func(A) B], State[S, A]](fab, fa)
}
func Ap[S, A, B any](ga State[S, A]) func(State[S, func(A) B]) State[S, B] {
return G.Ap[State[S, B], State[S, func(A) B], State[S, A]](ga)
}
func MonadChainFirst[S any, FCT ~func(A) State[S, B], A, B any](ma State[S, A], f FCT) State[S, A] {
return G.MonadChainFirst[State[S, B], State[S, A]](ma, f)
}
func ChainFirst[S any, FCT ~func(A) State[S, B], A, B any](f FCT) func(State[S, A]) State[S, A] {
return G.ChainFirst[State[S, B], State[S, A]](f)
}
func Flatten[S, A any](mma State[S, State[S, A]]) State[S, A] {
return G.Flatten[State[S, State[S, A]], State[S, A]](mma)
}
func Execute[A, S any](s S) func(State[S, A]) S {
return G.Execute[State[S, A]](s)
}
func Evaluate[A, S any](s S) func(State[S, A]) A {
return G.Evaluate[State[S, A]](s)
}
func MonadFlap[FAB ~func(A) B, S, A, B any](fab State[S, FAB], a A) State[S, B] {
return G.MonadFlap[FAB, State[S, FAB], State[S, B], S, A, B](fab, a)
}
func Flap[S, A, B any](a A) func(State[S, func(A) B]) State[S, B] {
return G.Flap[func(A) B, State[S, func(A) B], State[S, B]](a)
}

78
state/testing/laws.go Normal file
View File

@@ -0,0 +1,78 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package testing
import (
"testing"
EQ "github.com/IBM/fp-go/eq"
L "github.com/IBM/fp-go/internal/monad/testing"
ST "github.com/IBM/fp-go/state"
)
// AssertLaws asserts the apply monad laws for the `Either` monad
func AssertLaws[S, A, B, C any](t *testing.T,
eqw EQ.Eq[S],
eqa EQ.Eq[A],
eqb EQ.Eq[B],
eqc EQ.Eq[C],
ab func(A) B,
bc func(B) C,
s S,
) func(a A) bool {
fofc := ST.Pointed[S, C]()
fofaa := ST.Pointed[S, func(A) A]()
fofbc := ST.Pointed[S, func(B) C]()
fofabb := ST.Pointed[S, func(func(A) B) B]()
fmap := ST.Functor[S, func(B) C, func(func(A) B) func(A) C]()
fapabb := ST.Applicative[S, func(A) B, B]()
fapabac := ST.Applicative[S, func(A) B, func(A) C]()
maa := ST.Monad[S, A, A]()
mab := ST.Monad[S, A, B]()
mac := ST.Monad[S, A, C]()
mbc := ST.Monad[S, B, C]()
return L.MonadAssertLaws(t,
ST.Eq(eqw, eqa)(s),
ST.Eq(eqw, eqb)(s),
ST.Eq(eqw, eqc)(s),
fofc,
fofaa,
fofbc,
fofabb,
fmap,
fapabb,
fapabac,
maa,
mab,
mac,
mbc,
ab,
bc,
)
}

View File

@@ -0,0 +1,49 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package testing
import (
"fmt"
"testing"
A "github.com/IBM/fp-go/array"
EQ "github.com/IBM/fp-go/eq"
"github.com/stretchr/testify/assert"
)
func TestMonadLaws(t *testing.T) {
// some comparison
eqs := A.Eq[string](EQ.FromStrictEquals[string]())
eqa := EQ.FromStrictEquals[bool]()
eqb := EQ.FromStrictEquals[int]()
eqc := EQ.FromStrictEquals[string]()
ab := func(a bool) int {
if a {
return 1
}
return 0
}
bc := func(b int) string {
return fmt.Sprintf("value %d", b)
}
laws := AssertLaws(t, eqs, eqa, eqb, eqc, ab, bc, A.Empty[string]())
assert.True(t, laws(true))
assert.True(t, laws(false))
}

35
statereaderioeither/eq.go Normal file
View File

@@ -0,0 +1,35 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package statereaderioeither
import (
EQ "github.com/IBM/fp-go/eq"
P "github.com/IBM/fp-go/pair"
RIOE "github.com/IBM/fp-go/readerioeither"
G "github.com/IBM/fp-go/statereaderioeither/generic"
)
// Eq implements the equals predicate for values contained in the [StateReaderIOEither] monad
func Eq[
S, R, E, A any](eqr EQ.Eq[RIOE.ReaderIOEither[R, E, P.Pair[A, S]]]) func(S) EQ.Eq[StateReaderIOEither[S, R, E, A]] {
return G.Eq[StateReaderIOEither[S, R, E, A]](eqr)
}
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[
S, R any, E, A comparable]() func(R) func(S) EQ.Eq[StateReaderIOEither[S, R, E, A]] {
return G.FromStrictEquals[StateReaderIOEither[S, R, E, A]]()
}

View File

@@ -0,0 +1,49 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
ET "github.com/IBM/fp-go/either"
EQ "github.com/IBM/fp-go/eq"
F "github.com/IBM/fp-go/function"
P "github.com/IBM/fp-go/pair"
G "github.com/IBM/fp-go/readerioeither/generic"
)
// Eq implements the equals predicate for values contained in the [StateReaderIOEither] monad
func Eq[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any](eqr EQ.Eq[RIOEA]) func(S) EQ.Eq[SRIOEA] {
return func(s S) EQ.Eq[SRIOEA] {
return EQ.FromEquals(func(l, r SRIOEA) bool {
return eqr.Equals(l(s), r(s))
})
}
}
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
func FromStrictEquals[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R any, E, A comparable]() func(R) func(S) EQ.Eq[SRIOEA] {
return F.Flow2(
G.FromStrictEquals[RIOEA](),
Eq[SRIOEA, RIOEA, IOEA, S, R, E, A],
)
}

View File

@@ -0,0 +1,159 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
ET "github.com/IBM/fp-go/either"
"github.com/IBM/fp-go/internal/applicative"
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
P "github.com/IBM/fp-go/pair"
)
type stateReaderIOEitherPointed[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
] struct{}
type stateReaderIOEitherFunctor[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
] struct{}
type stateReaderIOEitherApplicative[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
SRIOEAB ~func(S) RIOEAB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
RIOEAB ~func(R) IOEAB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
S, R, E, A, B any,
] struct{}
type stateReaderIOEitherMonad[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
SRIOEAB ~func(S) RIOEAB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
RIOEAB ~func(R) IOEAB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
S, R, E, A, B any,
] struct{}
func (o *stateReaderIOEitherPointed[SRIOEA, RIOEA, IOEA, S, R, E, A]) Of(a A) SRIOEA {
return Of[SRIOEA](a)
}
func (o *stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Of(a A) SRIOEA {
return Of[SRIOEA](a)
}
func (o *stateReaderIOEitherApplicative[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Of(a A) SRIOEA {
return Of[SRIOEA](a)
}
func (o *stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Map(f func(A) B) func(SRIOEA) SRIOEB {
return Map[SRIOEA, SRIOEB](f)
}
func (o *stateReaderIOEitherApplicative[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Map(f func(A) B) func(SRIOEA) SRIOEB {
return Map[SRIOEA, SRIOEB](f)
}
func (o *stateReaderIOEitherFunctor[SRIOEA, SRIOEB, RIOEA, RIOEB, IOEA, IOEB, S, R, E, A, B]) Map(f func(A) B) func(SRIOEA) SRIOEB {
return Map[SRIOEA, SRIOEB](f)
}
func (o *stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Chain(f func(A) SRIOEB) func(SRIOEA) SRIOEB {
return Chain[SRIOEA, SRIOEB](f)
}
func (o *stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Ap(fa SRIOEA) func(SRIOEAB) SRIOEB {
return Ap[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B](fa)
}
func (o *stateReaderIOEitherApplicative[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]) Ap(fa SRIOEA) func(SRIOEAB) SRIOEB {
return Ap[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B](fa)
}
// Pointed implements the pointed operations for [StateReaderIOEither]
func Pointed[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
]() pointed.Pointed[A, SRIOEA] {
return &stateReaderIOEitherPointed[SRIOEA, RIOEA, IOEA, S, R, E, A]{}
}
// Functor implements the functor operations for [StateReaderIOEither]
func Functor[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
]() functor.Functor[A, B, SRIOEA, SRIOEB] {
return &stateReaderIOEitherFunctor[SRIOEA, SRIOEB, RIOEA, RIOEB, IOEA, IOEB, S, R, E, A, B]{}
}
// Applicative implements the applicative operations for [StateReaderIOEither]
func Applicative[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
SRIOEAB ~func(S) RIOEAB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
RIOEAB ~func(R) IOEAB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
S, R, E, A, B any,
]() applicative.Applicative[A, B, SRIOEA, SRIOEB, SRIOEAB] {
return &stateReaderIOEitherApplicative[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]{}
}
// Monad implements the monadic operations for [StateReaderIOEither]
func Monad[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
SRIOEAB ~func(S) RIOEAB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
RIOEAB ~func(R) IOEAB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
S, R, E, A, B any,
]() monad.Monad[A, B, SRIOEA, SRIOEB, SRIOEAB] {
return &stateReaderIOEitherMonad[SRIOEA, SRIOEB, SRIOEAB, RIOEA, RIOEB, RIOEAB, IOEA, IOEB, IOEAB, S, R, E, A, B]{}
}

View File

@@ -0,0 +1,425 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
ET "github.com/IBM/fp-go/either"
F "github.com/IBM/fp-go/function"
ST "github.com/IBM/fp-go/internal/statet"
P "github.com/IBM/fp-go/pair"
G "github.com/IBM/fp-go/readerioeither/generic"
)
func Left[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
](e E) SRIOEA {
return F.Constant1[S](G.Left[RIOEA](e))
}
func Right[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
](a A) SRIOEA {
return ST.Of[SRIOEA](
G.Of[RIOEA],
a,
)
}
func Of[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
](a A) SRIOEA {
return Right[SRIOEA](a)
}
func MonadMap[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](fa SRIOEA, f func(A) B) SRIOEB {
return ST.MonadMap[SRIOEA, SRIOEB](
G.MonadMap[RIOEA, RIOEB],
fa,
f,
)
}
func Map[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](f func(A) B) func(SRIOEA) SRIOEB {
return ST.Map[SRIOEA, SRIOEB](
G.Map[RIOEA, RIOEB],
f,
)
}
func MonadChain[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](fa SRIOEA, f func(A) SRIOEB) SRIOEB {
return ST.MonadChain[SRIOEA, SRIOEB](
G.MonadChain[RIOEA, RIOEB],
fa,
f,
)
}
func Chain[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](f func(A) SRIOEB) func(SRIOEA) SRIOEB {
return ST.Chain[SRIOEA, SRIOEB](
G.Chain[RIOEA, RIOEB],
f,
)
}
func MonadAp[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
SRIOEAB ~func(S) RIOEAB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
RIOEAB ~func(R) IOEAB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
S, R, E, A, B any,
](fab SRIOEAB, fa SRIOEA) SRIOEB {
return ST.MonadAp[SRIOEA, SRIOEB, SRIOEAB](
G.MonadMap[RIOEA, RIOEB],
G.MonadChain[RIOEAB, RIOEB],
fab,
fa,
)
}
func Ap[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
SRIOEAB ~func(S) RIOEAB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
RIOEAB ~func(R) IOEAB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEAB ~func() ET.Either[E, P.Pair[func(A) B, S]],
S, R, E, A, B any,
](fa SRIOEA) func(SRIOEAB) SRIOEB {
return ST.Ap[SRIOEA, SRIOEB, SRIOEAB](
G.Map[RIOEA, RIOEB],
G.Chain[RIOEAB, RIOEB],
fa,
)
}
// Conversions
func FromReaderIOEither[
SRIOEA ~func(S) RIOEA,
RIOEA_IN ~func(R) IOEA_IN,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEA_IN ~func() ET.Either[E, A],
S, R, E, A any,
](fa RIOEA_IN) SRIOEA {
return ST.FromF[SRIOEA](
G.MonadMap[RIOEA_IN, RIOEA],
fa,
)
}
func FromReaderEither[
SRIOEA ~func(S) RIOEA,
RIOEA_IN ~func(R) IOEA_IN,
RIOEA ~func(R) IOEA,
REA_IN ~func(R) ET.Either[E, A],
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEA_IN ~func() ET.Either[E, A],
S, R, E, A any,
](fa REA_IN) SRIOEA {
return FromReaderIOEither[SRIOEA](G.FromReaderEither[REA_IN, RIOEA_IN](fa))
}
func FromIOEither[
SRIOEA ~func(S) RIOEA,
RIOEA_IN ~func(R) IOEA_IN,
IOEA_IN ~func() ET.Either[E, A],
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
](fa IOEA_IN) SRIOEA {
return FromReaderIOEither[SRIOEA](G.FromIOEither[RIOEA_IN](fa))
}
func FromIO[
SRIOEA ~func(S) RIOEA,
RIOEA_IN ~func(R) IOEA_IN,
IO_IN ~func() A,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEA_IN ~func() ET.Either[E, A],
S, R, E, A any,
](fa IO_IN) SRIOEA {
return FromReaderIOEither[SRIOEA](G.FromIO[RIOEA_IN](fa))
}
func FromReader[
SRIOEA ~func(S) RIOEA,
RIOEA_IN ~func(R) IOEA_IN,
R_IN ~func(R) A,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEA_IN ~func() ET.Either[E, A],
S, R, E, A any,
](fa R_IN) SRIOEA {
return FromReaderIOEither[SRIOEA](G.FromReader[R_IN, RIOEA_IN](fa))
}
func FromEither[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
](ma ET.Either[E, A]) SRIOEA {
return ET.MonadFold(ma, Left[SRIOEA], Right[SRIOEA])
}
func FromState[
SRIOEA ~func(S) RIOEA,
STATE ~func(S) P.Pair[A, S],
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
](fa STATE) SRIOEA {
return ST.FromState[SRIOEA](G.Of[RIOEA], fa)
}
// Combinators
func Local[
SR1IOEA ~func(S) R1IOEA,
SR2IOEA ~func(S) R2IOEA,
R1IOEA ~func(R1) IOEA,
R2IOEA ~func(R2) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R1, R2, E, A any,
](f func(R2) R1) func(SR1IOEA) SR2IOEA {
return func(ma SR1IOEA) SR2IOEA {
return F.Flow2(ma, G.Local[R1IOEA, R2IOEA](f))
}
}
func Asks[
SRIOEA ~func(S) RIOEA,
RIOEA ~func(R) IOEA,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
S, R, E, A any,
](f func(R) SRIOEA) SRIOEA {
return func(s S) RIOEA {
return func(r R) IOEA {
return f(r)(s)(r)
}
}
}
func FromIOEitherK[
SRIOEB ~func(S) RIOEB,
RIOEB_IN ~func(R) IOEB_IN,
IOEB_IN ~func() ET.Either[E, B],
RIOEB ~func(R) IOEB,
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](f func(A) IOEB_IN) func(A) SRIOEB {
return F.Flow2(
f,
FromIOEither[SRIOEB, RIOEB_IN],
)
}
func FromEitherK[
SRIOEB ~func(S) RIOEB,
RIOEB ~func(R) IOEB,
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](f func(A) ET.Either[E, B]) func(A) SRIOEB {
return F.Flow2(
f,
FromEither[SRIOEB],
)
}
func FromIOK[
SRIOEB ~func(S) RIOEB,
RIOEB_IN ~func(R) IOEB_IN,
IOB_IN ~func() B,
RIOEB ~func(R) IOEB,
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEB_IN ~func() ET.Either[E, B],
S, R, E, A, B any,
](f func(A) IOB_IN) func(A) SRIOEB {
return F.Flow2(
f,
FromIO[SRIOEB, RIOEB_IN, IOB_IN],
)
}
func FromReaderIOEitherK[
SRIOEB ~func(S) RIOEB,
RIOEB_IN ~func(R) IOEB_IN,
IOEB_IN ~func() ET.Either[E, B],
RIOEB ~func(R) IOEB,
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](f func(A) RIOEB_IN) func(A) SRIOEB {
return F.Flow2(
f,
FromReaderIOEither[SRIOEB, RIOEB_IN],
)
}
func MonadChainReaderIOEitherK[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEB_IN ~func(R) IOEB_IN,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEB_IN ~func() ET.Either[E, B],
S, R, E, A, B any,
](ma SRIOEA, f func(A) RIOEB_IN) SRIOEB {
return MonadChain(ma, FromReaderIOEitherK[SRIOEB, RIOEB_IN](f))
}
func ChainReaderIOEitherK[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEB_IN ~func(R) IOEB_IN,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
IOEB_IN ~func() ET.Either[E, B],
S, R, E, A, B any,
](f func(A) RIOEB_IN) func(SRIOEA) SRIOEB {
return Chain[SRIOEA](FromReaderIOEitherK[SRIOEB, RIOEB_IN](f))
}
func MonadChainIOEitherK[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEB_IN ~func(R) IOEB_IN,
IOEB_IN ~func() ET.Either[E, B],
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](ma SRIOEA, f func(A) IOEB_IN) SRIOEB {
return MonadChain(ma, FromIOEitherK[SRIOEB, RIOEB_IN](f))
}
func ChainIOEitherK[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEB_IN ~func(R) IOEB_IN,
IOEB_IN ~func() ET.Either[E, B],
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](f func(A) IOEB_IN) func(SRIOEA) SRIOEB {
return Chain[SRIOEA](FromIOEitherK[SRIOEB, RIOEB_IN](f))
}
func MonadChainEitherK[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](ma SRIOEA, f func(A) ET.Either[E, B]) SRIOEB {
return MonadChain(ma, FromEitherK[SRIOEB](f))
}
func ChainEitherK[
SRIOEA ~func(S) RIOEA,
SRIOEB ~func(S) RIOEB,
RIOEA ~func(R) IOEA,
RIOEB ~func(R) IOEB,
IOEA ~func() ET.Either[E, P.Pair[A, S]],
IOEB ~func() ET.Either[E, P.Pair[B, S]],
S, R, E, A, B any,
](f func(A) ET.Either[E, B]) func(SRIOEA) SRIOEB {
return Chain[SRIOEA](FromEitherK[SRIOEB](f))
}

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package statereaderioeither
import (
"github.com/IBM/fp-go/internal/applicative"
"github.com/IBM/fp-go/internal/functor"
"github.com/IBM/fp-go/internal/monad"
"github.com/IBM/fp-go/internal/pointed"
G "github.com/IBM/fp-go/statereaderioeither/generic"
)
// Pointed returns the pointed operations for [StateReaderIOEither]
func Pointed[S, R, E, A any]() pointed.Pointed[A, StateReaderIOEither[S, R, E, A]] {
return G.Pointed[StateReaderIOEither[S, R, E, A]]()
}
// Functor returns the functor operations for [StateReaderIOEither]
func Functor[S, R, E, A, B any]() functor.Functor[A, B, StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]] {
return G.Functor[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]]()
}
// Applicative returns the applicative operations for [StateReaderIOEither]
func Applicative[S, R, E, A, B any]() applicative.Applicative[A, B, StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]] {
return G.Applicative[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]]()
}
// Monad returns the monadic operations for [StateReaderIOEither]
func Monad[S, R, E, A, B any]() monad.Monad[A, B, StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]] {
return G.Monad[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]]()
}

View File

@@ -0,0 +1,145 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package statereaderioeither
import (
ET "github.com/IBM/fp-go/either"
IO "github.com/IBM/fp-go/io"
IOE "github.com/IBM/fp-go/ioeither"
RD "github.com/IBM/fp-go/reader"
RE "github.com/IBM/fp-go/readereither"
RIOE "github.com/IBM/fp-go/readerioeither"
ST "github.com/IBM/fp-go/state"
G "github.com/IBM/fp-go/statereaderioeither/generic"
)
func Left[S, R, A, E any](e E) StateReaderIOEither[S, R, E, A] {
return G.Left[StateReaderIOEither[S, R, E, A]](e)
}
func Right[S, R, E, A any](a A) StateReaderIOEither[S, R, E, A] {
return G.Right[StateReaderIOEither[S, R, E, A]](a)
}
func Of[S, R, E, A any](a A) StateReaderIOEither[S, R, E, A] {
return G.Of[StateReaderIOEither[S, R, E, A]](a)
}
func MonadMap[S, R, E, A, B any](fa StateReaderIOEither[S, R, E, A], f func(A) B) StateReaderIOEither[S, R, E, B] {
return G.MonadMap[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](fa, f)
}
func Map[S, R, E, A, B any](f func(A) B) func(StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
return G.Map[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](f)
}
func MonadChain[S, R, E, A, B any](fa StateReaderIOEither[S, R, E, A], f func(A) StateReaderIOEither[S, R, E, B]) StateReaderIOEither[S, R, E, B] {
return G.MonadChain[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](fa, f)
}
func Chain[S, R, E, A, B any](f func(A) StateReaderIOEither[S, R, E, B]) func(StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
return G.Chain[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](f)
}
func MonadAp[S, R, E, A, B any](fab StateReaderIOEither[S, R, E, func(A) B], fa StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
return G.MonadAp[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]](fab, fa)
}
func Ap[S, R, E, A, B any](fa StateReaderIOEither[S, R, E, A]) func(StateReaderIOEither[S, R, E, func(A) B]) StateReaderIOEither[S, R, E, B] {
return G.Ap[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], StateReaderIOEither[S, R, E, func(A) B]](fa)
}
func FromReaderIOEither[S, R, E, A any](fa RIOE.ReaderIOEither[R, E, A]) StateReaderIOEither[S, R, E, A] {
return G.FromReaderIOEither[StateReaderIOEither[S, R, E, A]](fa)
}
func FromReaderEither[S, R, E, A any](fa RE.ReaderEither[R, E, A]) StateReaderIOEither[S, R, E, A] {
return G.FromReaderEither[StateReaderIOEither[S, R, E, A], RIOE.ReaderIOEither[R, E, A]](fa)
}
func FromIOEither[S, R, E, A any](fa IOE.IOEither[E, A]) StateReaderIOEither[S, R, E, A] {
return G.FromIOEither[StateReaderIOEither[S, R, E, A], RIOE.ReaderIOEither[R, E, A]](fa)
}
func FromState[S, R, E, A any](sa ST.State[S, A]) StateReaderIOEither[S, R, E, A] {
return G.FromState[StateReaderIOEither[S, R, E, A]](sa)
}
func FromIO[S, R, E, A any](fa IO.IO[A]) StateReaderIOEither[S, R, E, A] {
return G.FromIO[StateReaderIOEither[S, R, E, A], RIOE.ReaderIOEither[R, E, A]](fa)
}
func FromReader[S, R, E, A any](fa RD.Reader[R, A]) StateReaderIOEither[S, R, E, A] {
return G.FromReader[StateReaderIOEither[S, R, E, A], RIOE.ReaderIOEither[R, E, A]](fa)
}
func FromEither[S, R, E, A any](ma ET.Either[E, A]) StateReaderIOEither[S, R, E, A] {
return G.FromEither[StateReaderIOEither[S, R, E, A]](ma)
}
// Combinators
func Local[S, R1, R2, E, A, B any](f func(R2) R1) func(StateReaderIOEither[S, R1, E, A]) StateReaderIOEither[S, R2, E, A] {
return G.Local[StateReaderIOEither[S, R1, E, A], StateReaderIOEither[S, R2, E, A]](f)
}
func Asks[
S, R, E, A any,
](f func(R) StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, A] {
return G.Asks[StateReaderIOEither[S, R, E, A]](f)
}
func FromEitherK[S, R, E, A, B any](f func(A) ET.Either[E, B]) func(A) StateReaderIOEither[S, R, E, B] {
return G.FromEitherK[StateReaderIOEither[S, R, E, B]](f)
}
func FromIOK[S, R, E, A, B any](f func(A) IO.IO[B]) func(A) StateReaderIOEither[S, R, E, B] {
return G.FromIOK[StateReaderIOEither[S, R, E, B], RIOE.ReaderIOEither[R, E, B]](f)
}
func FromIOEitherK[
S, R, E, A, B any,
](f func(A) IOE.IOEither[E, B]) func(A) StateReaderIOEither[S, R, E, B] {
return G.FromIOEitherK[StateReaderIOEither[S, R, E, B], RIOE.ReaderIOEither[R, E, B]](f)
}
func FromReaderIOEitherK[S, R, E, A, B any](f func(A) RIOE.ReaderIOEither[R, E, B]) func(A) StateReaderIOEither[S, R, E, B] {
return G.FromReaderIOEitherK[StateReaderIOEither[S, R, E, B], RIOE.ReaderIOEither[R, E, B]](f)
}
func MonadChainReaderIOEitherK[S, R, E, A, B any](ma StateReaderIOEither[S, R, E, A], f func(A) RIOE.ReaderIOEither[R, E, B]) StateReaderIOEither[S, R, E, B] {
return G.MonadChainReaderIOEitherK[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](ma, f)
}
func ChainReaderIOEitherK[S, R, E, A, B any](f func(A) RIOE.ReaderIOEither[R, E, B]) func(StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
return G.ChainReaderIOEitherK[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](f)
}
func MonadChainIOEitherK[S, R, E, A, B any](ma StateReaderIOEither[S, R, E, A], f func(A) IOE.IOEither[E, B]) StateReaderIOEither[S, R, E, B] {
return G.MonadChainIOEitherK[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], RIOE.ReaderIOEither[R, E, B]](ma, f)
}
func ChainIOEitherK[S, R, E, A, B any](f func(A) IOE.IOEither[E, B]) func(StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
return G.ChainIOEitherK[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B], RIOE.ReaderIOEither[R, E, B]](f)
}
func MonadChainEitherK[S, R, E, A, B any](ma StateReaderIOEither[S, R, E, A], f func(A) ET.Either[E, B]) StateReaderIOEither[S, R, E, B] {
return G.MonadChainEitherK[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](ma, f)
}
func ChainEitherK[S, R, E, A, B any](f func(A) ET.Either[E, B]) func(StateReaderIOEither[S, R, E, A]) StateReaderIOEither[S, R, E, B] {
return G.ChainEitherK[StateReaderIOEither[S, R, E, A], StateReaderIOEither[S, R, E, B]](f)
}

View File

@@ -0,0 +1,87 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package testing
import (
"testing"
ET "github.com/IBM/fp-go/either"
EQ "github.com/IBM/fp-go/eq"
L "github.com/IBM/fp-go/internal/monad/testing"
P "github.com/IBM/fp-go/pair"
RIOE "github.com/IBM/fp-go/readerioeither"
ST "github.com/IBM/fp-go/statereaderioeither"
)
// AssertLaws asserts the apply monad laws for the `Either` monad
func AssertLaws[S, E, R, A, B, C any](t *testing.T,
eqs EQ.Eq[S],
eqe EQ.Eq[E],
eqa EQ.Eq[A],
eqb EQ.Eq[B],
eqc EQ.Eq[C],
ab func(A) B,
bc func(B) C,
s S,
r R,
) func(a A) bool {
eqra := RIOE.Eq[R](ET.Eq(eqe, P.Eq(eqa, eqs)))(r)
eqrb := RIOE.Eq[R](ET.Eq(eqe, P.Eq(eqb, eqs)))(r)
eqrc := RIOE.Eq[R](ET.Eq(eqe, P.Eq(eqc, eqs)))(r)
fofc := ST.Pointed[S, R, E, C]()
fofaa := ST.Pointed[S, R, E, func(A) A]()
fofbc := ST.Pointed[S, R, E, func(B) C]()
fofabb := ST.Pointed[S, R, E, func(func(A) B) B]()
fmap := ST.Functor[S, R, E, func(B) C, func(func(A) B) func(A) C]()
fapabb := ST.Applicative[S, R, E, func(A) B, B]()
fapabac := ST.Applicative[S, R, E, func(A) B, func(A) C]()
maa := ST.Monad[S, R, E, A, A]()
mab := ST.Monad[S, R, E, A, B]()
mac := ST.Monad[S, R, E, A, C]()
mbc := ST.Monad[S, R, E, B, C]()
return L.MonadAssertLaws(t,
ST.Eq(eqra)(s),
ST.Eq(eqrb)(s),
ST.Eq(eqrc)(s),
fofc,
fofaa,
fofbc,
fofabb,
fmap,
fapabb,
fapabac,
maa,
mab,
mac,
mbc,
ab,
bc,
)
}

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package testing
import (
"context"
"fmt"
"testing"
A "github.com/IBM/fp-go/array"
EQ "github.com/IBM/fp-go/eq"
"github.com/stretchr/testify/assert"
)
func TestMonadLaws(t *testing.T) {
// some comparison
eqs := A.Eq[string](EQ.FromStrictEquals[string]())
eqe := EQ.FromStrictEquals[error]()
eqa := EQ.FromStrictEquals[bool]()
eqb := EQ.FromStrictEquals[int]()
eqc := EQ.FromStrictEquals[string]()
ab := func(a bool) int {
if a {
return 1
}
return 0
}
bc := func(b int) string {
return fmt.Sprintf("value %d", b)
}
laws := AssertLaws(t, eqs, eqe, eqa, eqb, eqc, ab, bc, A.Empty[string](), context.Background())
assert.True(t, laws(true))
assert.True(t, laws(false))
}

View File

@@ -0,0 +1,24 @@
// Copyright (c) 2024 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package statereaderioeither
import (
P "github.com/IBM/fp-go/pair"
RD "github.com/IBM/fp-go/reader"
RIOE "github.com/IBM/fp-go/readerioeither"
)
type StateReaderIOEither[S, R, E, A any] RD.Reader[S, RIOE.ReaderIOEither[R, E, P.Pair[A, S]]]

View File

@@ -15,4 +15,4 @@
package tuple
//go:generate go run .. tuple --count 10 --filename gen.go
//go:generate go run .. tuple --count 15 --filename gen.go

View File

@@ -1,6 +1,6 @@
// Code generated by go generate; DO NOT EDIT.
// This file was generated by robots at
// 2024-02-08 08:36:32.8883679 +0100 CET m=+0.008054801
// 2024-02-29 16:19:31.6574369 +0100 CET m=+0.012049601
package tuple
@@ -104,6 +104,91 @@ type Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any] struct {
F10 T10
}
// Tuple11 is a struct that carries 11 independently typed values
type Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any] struct {
F1 T1
F2 T2
F3 T3
F4 T4
F5 T5
F6 T6
F7 T7
F8 T8
F9 T9
F10 T10
F11 T11
}
// Tuple12 is a struct that carries 12 independently typed values
type Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any] struct {
F1 T1
F2 T2
F3 T3
F4 T4
F5 T5
F6 T6
F7 T7
F8 T8
F9 T9
F10 T10
F11 T11
F12 T12
}
// Tuple13 is a struct that carries 13 independently typed values
type Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any] struct {
F1 T1
F2 T2
F3 T3
F4 T4
F5 T5
F6 T6
F7 T7
F8 T8
F9 T9
F10 T10
F11 T11
F12 T12
F13 T13
}
// Tuple14 is a struct that carries 14 independently typed values
type Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any] struct {
F1 T1
F2 T2
F3 T3
F4 T4
F5 T5
F6 T6
F7 T7
F8 T8
F9 T9
F10 T10
F11 T11
F12 T12
F13 T13
F14 T14
}
// Tuple15 is a struct that carries 15 independently typed values
type Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any] struct {
F1 T1
F2 T2
F3 T3
F4 T4
F5 T5
F6 T6
F7 T7
F8 T8
F9 T9
F10 T10
F11 T11
F12 T12
F13 T13
F14 T14
F15 T15
}
// MakeTuple1 is a function that converts its 1 parameters into a [Tuple1]
func MakeTuple1[T1 any](t1 T1) Tuple1[T1] {
return Tuple1[T1]{t1}
@@ -1326,3 +1411,843 @@ func FromArray10[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4,
)
}
}
// Push10 creates a [Tuple11] from a [Tuple10] by appending a constant value
func Push10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](value T11) func(Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] {
return func(t Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]) Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] {
return MakeTuple11(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, value)
}
}
// MakeTuple11 is a function that converts its 11 parameters into a [Tuple11]
func MakeTuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11) Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] {
return Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]{t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11}
}
// Tupled11 converts a function with 11 parameters into a function taking a Tuple11
// The inverse function is [Untupled11]
func Tupled11[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R any](f F) func(Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) R {
return func(t Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) R {
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11)
}
}
// Untupled11 converts a function with a [Tuple11] parameter into a function with 11 parameters
// The inverse function is [Tupled11]
func Untupled11[F ~func(Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11) R {
return f(MakeTuple11(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11))
}
}
// Monoid11 creates a [Monoid] for a [Tuple11] based on 11 monoids for the contained types
func Monoid11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7], m8 M.Monoid[T8], m9 M.Monoid[T9], m10 M.Monoid[T10], m11 M.Monoid[T11]) M.Monoid[Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] {
return M.MakeMonoid(func(l, r Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] {
return MakeTuple11(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9), m10.Concat(l.F10, r.F10), m11.Concat(l.F11, r.F11))
}, MakeTuple11(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty(), m10.Empty(), m11.Empty()))
}
// Ord11 creates n [Ord] for a [Tuple11] based on 11 [Ord]s for the contained types
func Ord11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7], o8 O.Ord[T8], o9 O.Ord[T9], o10 O.Ord[T10], o11 O.Ord[T11]) O.Ord[Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]] {
return O.MakeOrd(func(l, r Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) int {
if c := o1.Compare(l.F1, r.F1); c != 0 {
return c
}
if c := o2.Compare(l.F2, r.F2); c != 0 {
return c
}
if c := o3.Compare(l.F3, r.F3); c != 0 {
return c
}
if c := o4.Compare(l.F4, r.F4); c != 0 {
return c
}
if c := o5.Compare(l.F5, r.F5); c != 0 {
return c
}
if c := o6.Compare(l.F6, r.F6); c != 0 {
return c
}
if c := o7.Compare(l.F7, r.F7); c != 0 {
return c
}
if c := o8.Compare(l.F8, r.F8); c != 0 {
return c
}
if c := o9.Compare(l.F9, r.F9); c != 0 {
return c
}
if c := o10.Compare(l.F10, r.F10); c != 0 {
return c
}
if c := o11.Compare(l.F11, r.F11); c != 0 {
return c
}
return 0
}, func(l, r Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) bool {
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9) && o10.Equals(l.F10, r.F10) && o11.Equals(l.F11, r.F11)
})
}
// Map11 maps each value of a [Tuple11] via a mapping function
func Map11[F1 ~func(T1) R1, F2 ~func(T2) R2, F3 ~func(T3) R3, F4 ~func(T4) R4, F5 ~func(T5) R5, F6 ~func(T6) R6, F7 ~func(T7) R7, F8 ~func(T8) R8, F9 ~func(T9) R9, F10 ~func(T10) R10, F11 ~func(T11) R11, T1, R1, T2, R2, T3, R3, T4, R4, T5, R5, T6, R6, T7, R7, T8, R8, T9, R9, T10, R10, T11, R11 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11) func(Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) Tuple11[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11] {
return func(t Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) Tuple11[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11] {
return MakeTuple11(
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
)
}
}
// Replicate11 creates a [Tuple11] with all fields set to the input value `t`
func Replicate11[T any](t T) Tuple11[T, T, T, T, T, T, T, T, T, T, T] {
return MakeTuple11(t, t, t, t, t, t, t, t, t, t, t)
}
// String prints some debug info for the [Tuple11]
func (t Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) String() string {
return tupleString(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11)
}
// MarshalJSON marshals the [Tuple11] into a JSON array
func (t Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) MarshalJSON() ([]byte, error) {
return tupleMarshalJSON(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11)
}
// UnmarshalJSON unmarshals a JSON array into a [Tuple11]
func (t *Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) UnmarshalJSON(data []byte) error {
return tupleUnmarshalJSON(data, &t.F1, &t.F2, &t.F3, &t.F4, &t.F5, &t.F6, &t.F7, &t.F8, &t.F9, &t.F10, &t.F11)
}
// ToArray converts the [Tuple11] into an array of type [R] using 11 transformation functions from [T] to [R]
// The inverse function is [FromArray11]
func ToArray11[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, F8 ~func(T8) R, F9 ~func(T9) R, F10 ~func(T10) R, F11 ~func(T11) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11) func(t Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) []R {
return func(t Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) []R {
return []R{
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
}
}
}
// FromArray converts an array of [R] into a [Tuple11] using 11 functions from [R] to [T]
// The inverse function is [ToArray11]
func FromArray11[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, F8 ~func(R) T8, F9 ~func(R) T9, F10 ~func(R) T10, F11 ~func(R) T11, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11) func(r []R) Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] {
return func(r []R) Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] {
return MakeTuple11(
f1(r[0]),
f2(r[1]),
f3(r[2]),
f4(r[3]),
f5(r[4]),
f6(r[5]),
f7(r[6]),
f8(r[7]),
f9(r[8]),
f10(r[9]),
f11(r[10]),
)
}
}
// Push11 creates a [Tuple12] from a [Tuple11] by appending a constant value
func Push11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](value T12) func(Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] {
return func(t Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11]) Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] {
return MakeTuple12(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, value)
}
}
// MakeTuple12 is a function that converts its 12 parameters into a [Tuple12]
func MakeTuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12) Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] {
return Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]{t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12}
}
// Tupled12 converts a function with 12 parameters into a function taking a Tuple12
// The inverse function is [Untupled12]
func Tupled12[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R any](f F) func(Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) R {
return func(t Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) R {
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12)
}
}
// Untupled12 converts a function with a [Tuple12] parameter into a function with 12 parameters
// The inverse function is [Tupled12]
func Untupled12[F ~func(Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12) R {
return f(MakeTuple12(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12))
}
}
// Monoid12 creates a [Monoid] for a [Tuple12] based on 12 monoids for the contained types
func Monoid12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7], m8 M.Monoid[T8], m9 M.Monoid[T9], m10 M.Monoid[T10], m11 M.Monoid[T11], m12 M.Monoid[T12]) M.Monoid[Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] {
return M.MakeMonoid(func(l, r Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] {
return MakeTuple12(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9), m10.Concat(l.F10, r.F10), m11.Concat(l.F11, r.F11), m12.Concat(l.F12, r.F12))
}, MakeTuple12(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty(), m10.Empty(), m11.Empty(), m12.Empty()))
}
// Ord12 creates n [Ord] for a [Tuple12] based on 12 [Ord]s for the contained types
func Ord12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7], o8 O.Ord[T8], o9 O.Ord[T9], o10 O.Ord[T10], o11 O.Ord[T11], o12 O.Ord[T12]) O.Ord[Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]] {
return O.MakeOrd(func(l, r Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) int {
if c := o1.Compare(l.F1, r.F1); c != 0 {
return c
}
if c := o2.Compare(l.F2, r.F2); c != 0 {
return c
}
if c := o3.Compare(l.F3, r.F3); c != 0 {
return c
}
if c := o4.Compare(l.F4, r.F4); c != 0 {
return c
}
if c := o5.Compare(l.F5, r.F5); c != 0 {
return c
}
if c := o6.Compare(l.F6, r.F6); c != 0 {
return c
}
if c := o7.Compare(l.F7, r.F7); c != 0 {
return c
}
if c := o8.Compare(l.F8, r.F8); c != 0 {
return c
}
if c := o9.Compare(l.F9, r.F9); c != 0 {
return c
}
if c := o10.Compare(l.F10, r.F10); c != 0 {
return c
}
if c := o11.Compare(l.F11, r.F11); c != 0 {
return c
}
if c := o12.Compare(l.F12, r.F12); c != 0 {
return c
}
return 0
}, func(l, r Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) bool {
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9) && o10.Equals(l.F10, r.F10) && o11.Equals(l.F11, r.F11) && o12.Equals(l.F12, r.F12)
})
}
// Map12 maps each value of a [Tuple12] via a mapping function
func Map12[F1 ~func(T1) R1, F2 ~func(T2) R2, F3 ~func(T3) R3, F4 ~func(T4) R4, F5 ~func(T5) R5, F6 ~func(T6) R6, F7 ~func(T7) R7, F8 ~func(T8) R8, F9 ~func(T9) R9, F10 ~func(T10) R10, F11 ~func(T11) R11, F12 ~func(T12) R12, T1, R1, T2, R2, T3, R3, T4, R4, T5, R5, T6, R6, T7, R7, T8, R8, T9, R9, T10, R10, T11, R11, T12, R12 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12) func(Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) Tuple12[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12] {
return func(t Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) Tuple12[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12] {
return MakeTuple12(
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
f12(t.F12),
)
}
}
// Replicate12 creates a [Tuple12] with all fields set to the input value `t`
func Replicate12[T any](t T) Tuple12[T, T, T, T, T, T, T, T, T, T, T, T] {
return MakeTuple12(t, t, t, t, t, t, t, t, t, t, t, t)
}
// String prints some debug info for the [Tuple12]
func (t Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) String() string {
return tupleString(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12)
}
// MarshalJSON marshals the [Tuple12] into a JSON array
func (t Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) MarshalJSON() ([]byte, error) {
return tupleMarshalJSON(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12)
}
// UnmarshalJSON unmarshals a JSON array into a [Tuple12]
func (t *Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) UnmarshalJSON(data []byte) error {
return tupleUnmarshalJSON(data, &t.F1, &t.F2, &t.F3, &t.F4, &t.F5, &t.F6, &t.F7, &t.F8, &t.F9, &t.F10, &t.F11, &t.F12)
}
// ToArray converts the [Tuple12] into an array of type [R] using 12 transformation functions from [T] to [R]
// The inverse function is [FromArray12]
func ToArray12[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, F8 ~func(T8) R, F9 ~func(T9) R, F10 ~func(T10) R, F11 ~func(T11) R, F12 ~func(T12) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12) func(t Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) []R {
return func(t Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) []R {
return []R{
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
f12(t.F12),
}
}
}
// FromArray converts an array of [R] into a [Tuple12] using 12 functions from [R] to [T]
// The inverse function is [ToArray12]
func FromArray12[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, F8 ~func(R) T8, F9 ~func(R) T9, F10 ~func(R) T10, F11 ~func(R) T11, F12 ~func(R) T12, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12) func(r []R) Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] {
return func(r []R) Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] {
return MakeTuple12(
f1(r[0]),
f2(r[1]),
f3(r[2]),
f4(r[3]),
f5(r[4]),
f6(r[5]),
f7(r[6]),
f8(r[7]),
f9(r[8]),
f10(r[9]),
f11(r[10]),
f12(r[11]),
)
}
}
// Push12 creates a [Tuple13] from a [Tuple12] by appending a constant value
func Push12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](value T13) func(Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] {
return func(t Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12]) Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] {
return MakeTuple13(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, value)
}
}
// MakeTuple13 is a function that converts its 13 parameters into a [Tuple13]
func MakeTuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13) Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] {
return Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]{t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13}
}
// Tupled13 converts a function with 13 parameters into a function taking a Tuple13
// The inverse function is [Untupled13]
func Tupled13[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R any](f F) func(Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) R {
return func(t Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) R {
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13)
}
}
// Untupled13 converts a function with a [Tuple13] parameter into a function with 13 parameters
// The inverse function is [Tupled13]
func Untupled13[F ~func(Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13) R {
return f(MakeTuple13(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13))
}
}
// Monoid13 creates a [Monoid] for a [Tuple13] based on 13 monoids for the contained types
func Monoid13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7], m8 M.Monoid[T8], m9 M.Monoid[T9], m10 M.Monoid[T10], m11 M.Monoid[T11], m12 M.Monoid[T12], m13 M.Monoid[T13]) M.Monoid[Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] {
return M.MakeMonoid(func(l, r Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] {
return MakeTuple13(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9), m10.Concat(l.F10, r.F10), m11.Concat(l.F11, r.F11), m12.Concat(l.F12, r.F12), m13.Concat(l.F13, r.F13))
}, MakeTuple13(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty(), m10.Empty(), m11.Empty(), m12.Empty(), m13.Empty()))
}
// Ord13 creates n [Ord] for a [Tuple13] based on 13 [Ord]s for the contained types
func Ord13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7], o8 O.Ord[T8], o9 O.Ord[T9], o10 O.Ord[T10], o11 O.Ord[T11], o12 O.Ord[T12], o13 O.Ord[T13]) O.Ord[Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]] {
return O.MakeOrd(func(l, r Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) int {
if c := o1.Compare(l.F1, r.F1); c != 0 {
return c
}
if c := o2.Compare(l.F2, r.F2); c != 0 {
return c
}
if c := o3.Compare(l.F3, r.F3); c != 0 {
return c
}
if c := o4.Compare(l.F4, r.F4); c != 0 {
return c
}
if c := o5.Compare(l.F5, r.F5); c != 0 {
return c
}
if c := o6.Compare(l.F6, r.F6); c != 0 {
return c
}
if c := o7.Compare(l.F7, r.F7); c != 0 {
return c
}
if c := o8.Compare(l.F8, r.F8); c != 0 {
return c
}
if c := o9.Compare(l.F9, r.F9); c != 0 {
return c
}
if c := o10.Compare(l.F10, r.F10); c != 0 {
return c
}
if c := o11.Compare(l.F11, r.F11); c != 0 {
return c
}
if c := o12.Compare(l.F12, r.F12); c != 0 {
return c
}
if c := o13.Compare(l.F13, r.F13); c != 0 {
return c
}
return 0
}, func(l, r Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) bool {
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9) && o10.Equals(l.F10, r.F10) && o11.Equals(l.F11, r.F11) && o12.Equals(l.F12, r.F12) && o13.Equals(l.F13, r.F13)
})
}
// Map13 maps each value of a [Tuple13] via a mapping function
func Map13[F1 ~func(T1) R1, F2 ~func(T2) R2, F3 ~func(T3) R3, F4 ~func(T4) R4, F5 ~func(T5) R5, F6 ~func(T6) R6, F7 ~func(T7) R7, F8 ~func(T8) R8, F9 ~func(T9) R9, F10 ~func(T10) R10, F11 ~func(T11) R11, F12 ~func(T12) R12, F13 ~func(T13) R13, T1, R1, T2, R2, T3, R3, T4, R4, T5, R5, T6, R6, T7, R7, T8, R8, T9, R9, T10, R10, T11, R11, T12, R12, T13, R13 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13) func(Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) Tuple13[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13] {
return func(t Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) Tuple13[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13] {
return MakeTuple13(
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
f12(t.F12),
f13(t.F13),
)
}
}
// Replicate13 creates a [Tuple13] with all fields set to the input value `t`
func Replicate13[T any](t T) Tuple13[T, T, T, T, T, T, T, T, T, T, T, T, T] {
return MakeTuple13(t, t, t, t, t, t, t, t, t, t, t, t, t)
}
// String prints some debug info for the [Tuple13]
func (t Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) String() string {
return tupleString(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13)
}
// MarshalJSON marshals the [Tuple13] into a JSON array
func (t Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) MarshalJSON() ([]byte, error) {
return tupleMarshalJSON(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13)
}
// UnmarshalJSON unmarshals a JSON array into a [Tuple13]
func (t *Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) UnmarshalJSON(data []byte) error {
return tupleUnmarshalJSON(data, &t.F1, &t.F2, &t.F3, &t.F4, &t.F5, &t.F6, &t.F7, &t.F8, &t.F9, &t.F10, &t.F11, &t.F12, &t.F13)
}
// ToArray converts the [Tuple13] into an array of type [R] using 13 transformation functions from [T] to [R]
// The inverse function is [FromArray13]
func ToArray13[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, F8 ~func(T8) R, F9 ~func(T9) R, F10 ~func(T10) R, F11 ~func(T11) R, F12 ~func(T12) R, F13 ~func(T13) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13) func(t Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) []R {
return func(t Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) []R {
return []R{
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
f12(t.F12),
f13(t.F13),
}
}
}
// FromArray converts an array of [R] into a [Tuple13] using 13 functions from [R] to [T]
// The inverse function is [ToArray13]
func FromArray13[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, F8 ~func(R) T8, F9 ~func(R) T9, F10 ~func(R) T10, F11 ~func(R) T11, F12 ~func(R) T12, F13 ~func(R) T13, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13) func(r []R) Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] {
return func(r []R) Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] {
return MakeTuple13(
f1(r[0]),
f2(r[1]),
f3(r[2]),
f4(r[3]),
f5(r[4]),
f6(r[5]),
f7(r[6]),
f8(r[7]),
f9(r[8]),
f10(r[9]),
f11(r[10]),
f12(r[11]),
f13(r[12]),
)
}
}
// Push13 creates a [Tuple14] from a [Tuple13] by appending a constant value
func Push13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](value T14) func(Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] {
return func(t Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13]) Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] {
return MakeTuple14(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13, value)
}
}
// MakeTuple14 is a function that converts its 14 parameters into a [Tuple14]
func MakeTuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13, t14 T14) Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] {
return Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]{t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14}
}
// Tupled14 converts a function with 14 parameters into a function taking a Tuple14
// The inverse function is [Untupled14]
func Tupled14[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R any](f F) func(Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) R {
return func(t Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) R {
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13, t.F14)
}
}
// Untupled14 converts a function with a [Tuple14] parameter into a function with 14 parameters
// The inverse function is [Tupled14]
func Untupled14[F ~func(Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13, t14 T14) R {
return f(MakeTuple14(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14))
}
}
// Monoid14 creates a [Monoid] for a [Tuple14] based on 14 monoids for the contained types
func Monoid14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7], m8 M.Monoid[T8], m9 M.Monoid[T9], m10 M.Monoid[T10], m11 M.Monoid[T11], m12 M.Monoid[T12], m13 M.Monoid[T13], m14 M.Monoid[T14]) M.Monoid[Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] {
return M.MakeMonoid(func(l, r Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] {
return MakeTuple14(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9), m10.Concat(l.F10, r.F10), m11.Concat(l.F11, r.F11), m12.Concat(l.F12, r.F12), m13.Concat(l.F13, r.F13), m14.Concat(l.F14, r.F14))
}, MakeTuple14(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty(), m10.Empty(), m11.Empty(), m12.Empty(), m13.Empty(), m14.Empty()))
}
// Ord14 creates n [Ord] for a [Tuple14] based on 14 [Ord]s for the contained types
func Ord14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7], o8 O.Ord[T8], o9 O.Ord[T9], o10 O.Ord[T10], o11 O.Ord[T11], o12 O.Ord[T12], o13 O.Ord[T13], o14 O.Ord[T14]) O.Ord[Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]] {
return O.MakeOrd(func(l, r Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) int {
if c := o1.Compare(l.F1, r.F1); c != 0 {
return c
}
if c := o2.Compare(l.F2, r.F2); c != 0 {
return c
}
if c := o3.Compare(l.F3, r.F3); c != 0 {
return c
}
if c := o4.Compare(l.F4, r.F4); c != 0 {
return c
}
if c := o5.Compare(l.F5, r.F5); c != 0 {
return c
}
if c := o6.Compare(l.F6, r.F6); c != 0 {
return c
}
if c := o7.Compare(l.F7, r.F7); c != 0 {
return c
}
if c := o8.Compare(l.F8, r.F8); c != 0 {
return c
}
if c := o9.Compare(l.F9, r.F9); c != 0 {
return c
}
if c := o10.Compare(l.F10, r.F10); c != 0 {
return c
}
if c := o11.Compare(l.F11, r.F11); c != 0 {
return c
}
if c := o12.Compare(l.F12, r.F12); c != 0 {
return c
}
if c := o13.Compare(l.F13, r.F13); c != 0 {
return c
}
if c := o14.Compare(l.F14, r.F14); c != 0 {
return c
}
return 0
}, func(l, r Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) bool {
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9) && o10.Equals(l.F10, r.F10) && o11.Equals(l.F11, r.F11) && o12.Equals(l.F12, r.F12) && o13.Equals(l.F13, r.F13) && o14.Equals(l.F14, r.F14)
})
}
// Map14 maps each value of a [Tuple14] via a mapping function
func Map14[F1 ~func(T1) R1, F2 ~func(T2) R2, F3 ~func(T3) R3, F4 ~func(T4) R4, F5 ~func(T5) R5, F6 ~func(T6) R6, F7 ~func(T7) R7, F8 ~func(T8) R8, F9 ~func(T9) R9, F10 ~func(T10) R10, F11 ~func(T11) R11, F12 ~func(T12) R12, F13 ~func(T13) R13, F14 ~func(T14) R14, T1, R1, T2, R2, T3, R3, T4, R4, T5, R5, T6, R6, T7, R7, T8, R8, T9, R9, T10, R10, T11, R11, T12, R12, T13, R13, T14, R14 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14) func(Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) Tuple14[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14] {
return func(t Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) Tuple14[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14] {
return MakeTuple14(
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
f12(t.F12),
f13(t.F13),
f14(t.F14),
)
}
}
// Replicate14 creates a [Tuple14] with all fields set to the input value `t`
func Replicate14[T any](t T) Tuple14[T, T, T, T, T, T, T, T, T, T, T, T, T, T] {
return MakeTuple14(t, t, t, t, t, t, t, t, t, t, t, t, t, t)
}
// String prints some debug info for the [Tuple14]
func (t Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) String() string {
return tupleString(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13, t.F14)
}
// MarshalJSON marshals the [Tuple14] into a JSON array
func (t Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) MarshalJSON() ([]byte, error) {
return tupleMarshalJSON(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13, t.F14)
}
// UnmarshalJSON unmarshals a JSON array into a [Tuple14]
func (t *Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) UnmarshalJSON(data []byte) error {
return tupleUnmarshalJSON(data, &t.F1, &t.F2, &t.F3, &t.F4, &t.F5, &t.F6, &t.F7, &t.F8, &t.F9, &t.F10, &t.F11, &t.F12, &t.F13, &t.F14)
}
// ToArray converts the [Tuple14] into an array of type [R] using 14 transformation functions from [T] to [R]
// The inverse function is [FromArray14]
func ToArray14[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, F8 ~func(T8) R, F9 ~func(T9) R, F10 ~func(T10) R, F11 ~func(T11) R, F12 ~func(T12) R, F13 ~func(T13) R, F14 ~func(T14) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14) func(t Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) []R {
return func(t Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) []R {
return []R{
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
f12(t.F12),
f13(t.F13),
f14(t.F14),
}
}
}
// FromArray converts an array of [R] into a [Tuple14] using 14 functions from [R] to [T]
// The inverse function is [ToArray14]
func FromArray14[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, F8 ~func(R) T8, F9 ~func(R) T9, F10 ~func(R) T10, F11 ~func(R) T11, F12 ~func(R) T12, F13 ~func(R) T13, F14 ~func(R) T14, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14) func(r []R) Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] {
return func(r []R) Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] {
return MakeTuple14(
f1(r[0]),
f2(r[1]),
f3(r[2]),
f4(r[3]),
f5(r[4]),
f6(r[5]),
f7(r[6]),
f8(r[7]),
f9(r[8]),
f10(r[9]),
f11(r[10]),
f12(r[11]),
f13(r[12]),
f14(r[13]),
)
}
}
// Push14 creates a [Tuple15] from a [Tuple14] by appending a constant value
func Push14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](value T15) func(Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] {
return func(t Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14]) Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] {
return MakeTuple15(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13, t.F14, value)
}
}
// MakeTuple15 is a function that converts its 15 parameters into a [Tuple15]
func MakeTuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13, t14 T14, t15 T15) Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] {
return Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]{t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15}
}
// Tupled15 converts a function with 15 parameters into a function taking a Tuple15
// The inverse function is [Untupled15]
func Tupled15[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R any](f F) func(Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) R {
return func(t Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) R {
return f(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13, t.F14, t.F15)
}
}
// Untupled15 converts a function with a [Tuple15] parameter into a function with 15 parameters
// The inverse function is [Tupled15]
func Untupled15[F ~func(Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) R {
return func(t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9, t10 T10, t11 T11, t12 T12, t13 T13, t14 T14, t15 T15) R {
return f(MakeTuple15(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15))
}
}
// Monoid15 creates a [Monoid] for a [Tuple15] based on 15 monoids for the contained types
func Monoid15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](m1 M.Monoid[T1], m2 M.Monoid[T2], m3 M.Monoid[T3], m4 M.Monoid[T4], m5 M.Monoid[T5], m6 M.Monoid[T6], m7 M.Monoid[T7], m8 M.Monoid[T8], m9 M.Monoid[T9], m10 M.Monoid[T10], m11 M.Monoid[T11], m12 M.Monoid[T12], m13 M.Monoid[T13], m14 M.Monoid[T14], m15 M.Monoid[T15]) M.Monoid[Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] {
return M.MakeMonoid(func(l, r Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] {
return MakeTuple15(m1.Concat(l.F1, r.F1), m2.Concat(l.F2, r.F2), m3.Concat(l.F3, r.F3), m4.Concat(l.F4, r.F4), m5.Concat(l.F5, r.F5), m6.Concat(l.F6, r.F6), m7.Concat(l.F7, r.F7), m8.Concat(l.F8, r.F8), m9.Concat(l.F9, r.F9), m10.Concat(l.F10, r.F10), m11.Concat(l.F11, r.F11), m12.Concat(l.F12, r.F12), m13.Concat(l.F13, r.F13), m14.Concat(l.F14, r.F14), m15.Concat(l.F15, r.F15))
}, MakeTuple15(m1.Empty(), m2.Empty(), m3.Empty(), m4.Empty(), m5.Empty(), m6.Empty(), m7.Empty(), m8.Empty(), m9.Empty(), m10.Empty(), m11.Empty(), m12.Empty(), m13.Empty(), m14.Empty(), m15.Empty()))
}
// Ord15 creates n [Ord] for a [Tuple15] based on 15 [Ord]s for the contained types
func Ord15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](o1 O.Ord[T1], o2 O.Ord[T2], o3 O.Ord[T3], o4 O.Ord[T4], o5 O.Ord[T5], o6 O.Ord[T6], o7 O.Ord[T7], o8 O.Ord[T8], o9 O.Ord[T9], o10 O.Ord[T10], o11 O.Ord[T11], o12 O.Ord[T12], o13 O.Ord[T13], o14 O.Ord[T14], o15 O.Ord[T15]) O.Ord[Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]] {
return O.MakeOrd(func(l, r Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) int {
if c := o1.Compare(l.F1, r.F1); c != 0 {
return c
}
if c := o2.Compare(l.F2, r.F2); c != 0 {
return c
}
if c := o3.Compare(l.F3, r.F3); c != 0 {
return c
}
if c := o4.Compare(l.F4, r.F4); c != 0 {
return c
}
if c := o5.Compare(l.F5, r.F5); c != 0 {
return c
}
if c := o6.Compare(l.F6, r.F6); c != 0 {
return c
}
if c := o7.Compare(l.F7, r.F7); c != 0 {
return c
}
if c := o8.Compare(l.F8, r.F8); c != 0 {
return c
}
if c := o9.Compare(l.F9, r.F9); c != 0 {
return c
}
if c := o10.Compare(l.F10, r.F10); c != 0 {
return c
}
if c := o11.Compare(l.F11, r.F11); c != 0 {
return c
}
if c := o12.Compare(l.F12, r.F12); c != 0 {
return c
}
if c := o13.Compare(l.F13, r.F13); c != 0 {
return c
}
if c := o14.Compare(l.F14, r.F14); c != 0 {
return c
}
if c := o15.Compare(l.F15, r.F15); c != 0 {
return c
}
return 0
}, func(l, r Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) bool {
return o1.Equals(l.F1, r.F1) && o2.Equals(l.F2, r.F2) && o3.Equals(l.F3, r.F3) && o4.Equals(l.F4, r.F4) && o5.Equals(l.F5, r.F5) && o6.Equals(l.F6, r.F6) && o7.Equals(l.F7, r.F7) && o8.Equals(l.F8, r.F8) && o9.Equals(l.F9, r.F9) && o10.Equals(l.F10, r.F10) && o11.Equals(l.F11, r.F11) && o12.Equals(l.F12, r.F12) && o13.Equals(l.F13, r.F13) && o14.Equals(l.F14, r.F14) && o15.Equals(l.F15, r.F15)
})
}
// Map15 maps each value of a [Tuple15] via a mapping function
func Map15[F1 ~func(T1) R1, F2 ~func(T2) R2, F3 ~func(T3) R3, F4 ~func(T4) R4, F5 ~func(T5) R5, F6 ~func(T6) R6, F7 ~func(T7) R7, F8 ~func(T8) R8, F9 ~func(T9) R9, F10 ~func(T10) R10, F11 ~func(T11) R11, F12 ~func(T12) R12, F13 ~func(T13) R13, F14 ~func(T14) R14, F15 ~func(T15) R15, T1, R1, T2, R2, T3, R3, T4, R4, T5, R5, T6, R6, T7, R7, T8, R8, T9, R9, T10, R10, T11, R11, T12, R12, T13, R13, T14, R14, T15, R15 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15) func(Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) Tuple15[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15] {
return func(t Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) Tuple15[R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15] {
return MakeTuple15(
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
f12(t.F12),
f13(t.F13),
f14(t.F14),
f15(t.F15),
)
}
}
// Replicate15 creates a [Tuple15] with all fields set to the input value `t`
func Replicate15[T any](t T) Tuple15[T, T, T, T, T, T, T, T, T, T, T, T, T, T, T] {
return MakeTuple15(t, t, t, t, t, t, t, t, t, t, t, t, t, t, t)
}
// String prints some debug info for the [Tuple15]
func (t Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) String() string {
return tupleString(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13, t.F14, t.F15)
}
// MarshalJSON marshals the [Tuple15] into a JSON array
func (t Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) MarshalJSON() ([]byte, error) {
return tupleMarshalJSON(t.F1, t.F2, t.F3, t.F4, t.F5, t.F6, t.F7, t.F8, t.F9, t.F10, t.F11, t.F12, t.F13, t.F14, t.F15)
}
// UnmarshalJSON unmarshals a JSON array into a [Tuple15]
func (t *Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) UnmarshalJSON(data []byte) error {
return tupleUnmarshalJSON(data, &t.F1, &t.F2, &t.F3, &t.F4, &t.F5, &t.F6, &t.F7, &t.F8, &t.F9, &t.F10, &t.F11, &t.F12, &t.F13, &t.F14, &t.F15)
}
// ToArray converts the [Tuple15] into an array of type [R] using 15 transformation functions from [T] to [R]
// The inverse function is [FromArray15]
func ToArray15[F1 ~func(T1) R, F2 ~func(T2) R, F3 ~func(T3) R, F4 ~func(T4) R, F5 ~func(T5) R, F6 ~func(T6) R, F7 ~func(T7) R, F8 ~func(T8) R, F9 ~func(T9) R, F10 ~func(T10) R, F11 ~func(T11) R, F12 ~func(T12) R, F13 ~func(T13) R, F14 ~func(T14) R, F15 ~func(T15) R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15) func(t Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) []R {
return func(t Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15]) []R {
return []R{
f1(t.F1),
f2(t.F2),
f3(t.F3),
f4(t.F4),
f5(t.F5),
f6(t.F6),
f7(t.F7),
f8(t.F8),
f9(t.F9),
f10(t.F10),
f11(t.F11),
f12(t.F12),
f13(t.F13),
f14(t.F14),
f15(t.F15),
}
}
}
// FromArray converts an array of [R] into a [Tuple15] using 15 functions from [R] to [T]
// The inverse function is [ToArray15]
func FromArray15[F1 ~func(R) T1, F2 ~func(R) T2, F3 ~func(R) T3, F4 ~func(R) T4, F5 ~func(R) T5, F6 ~func(R) T6, F7 ~func(R) T7, F8 ~func(R) T8, F9 ~func(R) T9, F10 ~func(R) T10, F11 ~func(R) T11, F12 ~func(R) T12, F13 ~func(R) T13, F14 ~func(R) T14, F15 ~func(R) T15, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, R any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10, f11 F11, f12 F12, f13 F13, f14 F14, f15 F15) func(r []R) Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] {
return func(r []R) Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] {
return MakeTuple15(
f1(r[0]),
f2(r[1]),
f3(r[2]),
f4(r[3]),
f5(r[4]),
f6(r[5]),
f7(r[6]),
f8(r[7]),
f9(r[8]),
f10(r[9]),
f11(r[10]),
f12(r[11]),
f13(r[12]),
f14(r[13]),
f15(r[14]),
)
}
}

318
v2/README.md Normal file
View File

@@ -0,0 +1,318 @@
# fp-go V2: Enhanced Functional Programming for Go 1.24+
[![Go Reference](https://pkg.go.dev/badge/github.com/IBM/fp-go/v2.svg)](https://pkg.go.dev/github.com/IBM/fp-go/v2)
Version 2 of fp-go leverages [generic type aliases](https://github.com/golang/go/issues/46477) introduced in Go 1.24, providing a more ergonomic and streamlined API.
## 📚 Table of Contents
- [Requirements](#-requirements)
- [Breaking Changes](#-breaking-changes)
- [Key Improvements](#-key-improvements)
- [Migration Guide](#-migration-guide)
- [Installation](#-installation)
- [What's New](#-whats-new)
## 🔧 Requirements
- **Go 1.24 or later** (for generic type alias support)
## ⚠️ Breaking Changes
### 1. Generic Type Aliases
V2 uses [generic type aliases](https://github.com/golang/go/issues/46477) which require Go 1.24+. This is the most significant change and enables cleaner type definitions.
**V1:**
```go
type ReaderIOEither[R, E, A any] RD.Reader[R, IOE.IOEither[E, A]]
```
**V2:**
```go
type ReaderIOEither[R, E, A any] = RD.Reader[R, IOE.IOEither[E, A]]
```
### 2. Generic Type Parameter Ordering
Type parameters that **cannot** be inferred from function arguments now come first, improving type inference.
**V1:**
```go
// Ap in V1 - less intuitive ordering
func Ap[R, E, A, B any](fa ReaderIOEither[R, E, A]) func(ReaderIOEither[R, E, func(A) B]) ReaderIOEither[R, E, B]
```
**V2:**
```go
// Ap in V2 - B comes first as it cannot be inferred
func Ap[B, R, E, A any](fa ReaderIOEither[R, E, A]) func(ReaderIOEither[R, E, func(A) B]) ReaderIOEither[R, E, B]
```
This change allows the Go compiler to infer more types automatically, reducing the need for explicit type parameters.
### 3. Pair Monad Semantics
Monadic operations for `Pair` now operate on the **second argument** to align with the [Haskell definition](https://hackage.haskell.org/package/TypeCompose-0.9.14/docs/Data-Pair.html).
**V1:**
```go
// Operations on first element
pair := MakePair(1, "hello")
result := Map(func(x int) int { return x * 2 })(pair) // Pair(2, "hello")
```
**V2:**
```go
// Operations on second element (Haskell-compatible)
pair := MakePair(1, "hello")
result := Map(func(s string) string { return s + "!" })(pair) // Pair(1, "hello!")
```
## ✨ Key Improvements
### 1. Simplified Type Declarations
Generic type aliases eliminate the need for namespace imports in type declarations.
**V1 Approach:**
```go
import (
ET "github.com/IBM/fp-go/either"
OPT "github.com/IBM/fp-go/option"
)
func processData(input string) ET.Either[error, OPT.Option[int]] {
// implementation
}
```
**V2 Approach:**
```go
import (
"github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/option"
)
// Define type aliases once
type Either[A any] = either.Either[error, A]
type Option[A any] = option.Option[A]
// Use them throughout your codebase
func processData(input string) Either[Option[int]] {
// implementation
}
```
### 2. No More `generic` Subpackages
The library implementation no longer requires separate `generic` subpackages, making the codebase simpler and easier to understand.
**V1 Structure:**
```
either/
either.go
generic/
either.go // Generic implementation
```
**V2 Structure:**
```
either/
either.go // Single, clean implementation
```
### 3. Better Type Inference
The reordered type parameters allow the Go compiler to infer more types automatically:
**V1:**
```go
// Often need explicit type parameters
result := Map[Context, error, int, string](transform)(value)
```
**V2:**
```go
// Compiler can infer more types
result := Map(transform)(value) // Cleaner!
```
## 🚀 Migration Guide
### Step 1: Update Go Version
Ensure you're using Go 1.24 or later:
```bash
go version # Should show go1.24 or higher
```
### Step 2: Update Import Paths
Change all import paths from `github.com/IBM/fp-go` to `github.com/IBM/fp-go/v2`:
**Before:**
```go
import (
"github.com/IBM/fp-go/either"
"github.com/IBM/fp-go/option"
)
```
**After:**
```go
import (
"github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/option"
)
```
### Step 3: Remove `generic` Subpackage Imports
If you were using generic subpackages, remove them:
**Before:**
```go
import (
E "github.com/IBM/fp-go/either/generic"
)
```
**After:**
```go
import (
"github.com/IBM/fp-go/v2/either"
)
```
### Step 4: Update Type Parameter Order
Review functions like `Ap` where type parameter order has changed. The compiler will help identify these:
**Before:**
```go
result := Ap[Context, error, int, string](value)(funcInContext)
```
**After:**
```go
result := Ap[string, Context, error, int](value)(funcInContext)
// Or better yet, let the compiler infer:
result := Ap(value)(funcInContext)
```
### Step 5: Update Pair Operations
If you're using `Pair`, update operations to work on the second element:
**Before (V1):**
```go
pair := MakePair(42, "data")
// Map operates on first element
result := Map(func(x int) int { return x * 2 })(pair)
```
**After (V2):**
```go
pair := MakePair(42, "data")
// Map operates on second element
result := Map(func(s string) string { return s + "!" })(pair)
```
### Step 6: Simplify Type Aliases
Create project-wide type aliases for common patterns:
```go
// types.go - Define once, use everywhere
package myapp
import (
"github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/option"
"github.com/IBM/fp-go/v2/ioeither"
)
type Either[A any] = either.Either[error, A]
type Option[A any] = option.Option[A]
type IOEither[A any] = ioeither.IOEither[error, A]
```
## 📦 Installation
```bash
go get github.com/IBM/fp-go/v2
```
## 🆕 What's New
### Cleaner API Surface
The elimination of `generic` subpackages means:
- Fewer imports to manage
- Simpler package structure
- Easier to navigate documentation
- More intuitive API
### Example: Before and After
**V1 Complex Example:**
```go
import (
ET "github.com/IBM/fp-go/either"
EG "github.com/IBM/fp-go/either/generic"
IOET "github.com/IBM/fp-go/ioeither"
IOEG "github.com/IBM/fp-go/ioeither/generic"
)
func process() IOET.IOEither[error, string] {
return IOEG.Map[error, int, string](
func(x int) string { return fmt.Sprintf("%d", x) },
)(fetchData())
}
```
**V2 Simplified Example:**
```go
import (
"github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/ioeither"
)
type IOEither[A any] = ioeither.IOEither[error, A]
func process() IOEither[string] {
return ioeither.Map(
func(x int) string { return fmt.Sprintf("%d", x) },
)(fetchData())
}
```
## 📚 Additional Resources
- [Main README](../README.md) - Core concepts and design philosophy
- [API Documentation](https://pkg.go.dev/github.com/IBM/fp-go/v2)
- [Code Samples](../samples/)
- [Go 1.24 Release Notes](https://tip.golang.org/doc/go1.24)
## 🤔 Should I Migrate?
**Migrate to V2 if:**
- ✅ You can use Go 1.24+
- ✅ You want cleaner, more maintainable code
- ✅ You want better type inference
- ✅ You're starting a new project
**Stay on V1 if:**
- ⚠️ You're locked to Go < 1.24
- ⚠️ Migration effort outweighs benefits for your project
- ⚠️ You need stability in production (V2 is newer)
## 🐛 Issues and Feedback
Found a bug or have a suggestion? Please [open an issue](https://github.com/IBM/fp-go/issues) on GitHub.
## 📄 License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

50
v2/array/any.go Normal file
View File

@@ -0,0 +1,50 @@
// Copyright (c) 2023 - 2025 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
G "github.com/IBM/fp-go/v2/array/generic"
)
// AnyWithIndex tests if any of the elements in the array matches the predicate.
// The predicate receives both the index and the element.
// Returns true if at least one element satisfies the predicate, false otherwise.
//
// Example:
//
// hasEvenAtEvenIndex := array.AnyWithIndex(func(i, x int) bool {
// return i%2 == 0 && x%2 == 0
// })
// result := hasEvenAtEvenIndex([]int{1, 3, 4, 5}) // true (4 is at index 2)
//
//go:inline
func AnyWithIndex[A any](pred func(int, A) bool) func([]A) bool {
return G.AnyWithIndex[[]A](pred)
}
// Any tests if any of the elements in the array matches the predicate.
// Returns true if at least one element satisfies the predicate, false otherwise.
// Returns false for an empty array.
//
// Example:
//
// hasEven := array.Any(func(x int) bool { return x%2 == 0 })
// result := hasEven([]int{1, 3, 4, 5}) // true
//
//go:inline
func Any[A any](pred func(A) bool) func([]A) bool {
return G.Any[[]A](pred)
}

Some files were not shown because too many files have changed in this diff Show More