mirror of
https://github.com/IBM/fp-go.git
synced 2025-12-11 23:17:16 +02:00
Compare commits
1 Commits
cleue-bind
...
cleue-add-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bf432af49 |
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@@ -17,8 +17,8 @@ on:
|
|||||||
env:
|
env:
|
||||||
# Currently no way to detect automatically
|
# Currently no way to detect automatically
|
||||||
DEFAULT_BRANCH: main
|
DEFAULT_BRANCH: main
|
||||||
GO_VERSION: 1.21.6 # renovate: datasource=golang-version depName=golang
|
GO_VERSION: 1.20.6 # renovate: datasource=golang-version depName=golang
|
||||||
NODE_VERSION: 20
|
NODE_VERSION: 18
|
||||||
DRY_RUN: true
|
DRY_RUN: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -26,14 +26,14 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [ '1.20.x', '1.21.x']
|
go-version: [ '1.20.x', '1.21.x' ]
|
||||||
steps:
|
steps:
|
||||||
# full checkout for semantic-release
|
# full checkout for semantic-release
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set up go ${{ matrix.go-version }}
|
- name: Set up go ${{ matrix.go-version }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
-
|
-
|
||||||
@@ -60,12 +60,12 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Node.js ${{ env.NODE_VERSION }}
|
- name: Set up Node.js ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
|
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
|
||||||
- name: Set up go ${{env.GO_VERSION}}
|
- name: Set up go ${{env.GO_VERSION}}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ${{env.GO_VERSION}}
|
go-version: ${{env.GO_VERSION}}
|
||||||
|
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
fp-go.exe
|
fp-go.exe
|
||||||
main.exe
|
main.exe
|
||||||
build/
|
build/
|
||||||
.idea
|
|
||||||
@@ -17,7 +17,6 @@ package array
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
G "github.com/IBM/fp-go/array/generic"
|
G "github.com/IBM/fp-go/array/generic"
|
||||||
EM "github.com/IBM/fp-go/endomorphism"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
"github.com/IBM/fp-go/internal/array"
|
"github.com/IBM/fp-go/internal/array"
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
@@ -90,16 +89,16 @@ func filterMapRef[A, B any](fa []A, pred func(a *A) bool, f func(a *A) B) []B {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter returns a new array with all elements from the original array that match a predicate
|
// Filter returns a new array with all elements from the original array that match a predicate
|
||||||
func Filter[A any](pred func(A) bool) EM.Endomorphism[[]A] {
|
func Filter[A any](pred func(A) bool) func([]A) []A {
|
||||||
return G.Filter[[]A](pred)
|
return G.Filter[[]A](pred)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterWithIndex returns a new array with all elements from the original array that match a predicate
|
// FilterWithIndex returns a new array with all elements from the original array that match a predicate
|
||||||
func FilterWithIndex[A any](pred func(int, A) bool) EM.Endomorphism[[]A] {
|
func FilterWithIndex[A any](pred func(int, A) bool) func([]A) []A {
|
||||||
return G.FilterWithIndex[[]A](pred)
|
return G.FilterWithIndex[[]A](pred)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FilterRef[A any](pred func(*A) bool) EM.Endomorphism[[]A] {
|
func FilterRef[A any](pred func(*A) bool) func([]A) []A {
|
||||||
return F.Bind2nd(filterRef[A], pred)
|
return F.Bind2nd(filterRef[A], pred)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +227,7 @@ func Last[A any](as []A) O.Option[A] {
|
|||||||
return G.Last(as)
|
return G.Last(as)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrependAll[A any](middle A) EM.Endomorphism[[]A] {
|
func PrependAll[A any](middle A) func([]A) []A {
|
||||||
return func(as []A) []A {
|
return func(as []A) []A {
|
||||||
count := len(as)
|
count := len(as)
|
||||||
dst := count * 2
|
dst := count * 2
|
||||||
@@ -243,7 +242,7 @@ func PrependAll[A any](middle A) EM.Endomorphism[[]A] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Intersperse[A any](middle A) EM.Endomorphism[[]A] {
|
func Intersperse[A any](middle A) func([]A) []A {
|
||||||
prepend := PrependAll(middle)
|
prepend := PrependAll(middle)
|
||||||
return func(as []A) []A {
|
return func(as []A) []A {
|
||||||
if IsEmpty(as) {
|
if IsEmpty(as) {
|
||||||
@@ -272,7 +271,7 @@ func Lookup[A any](idx int) func([]A) O.Option[A] {
|
|||||||
return G.Lookup[[]A](idx)
|
return G.Lookup[[]A](idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpsertAt[A any](a A) EM.Endomorphism[[]A] {
|
func UpsertAt[A any](a A) func([]A) []A {
|
||||||
return G.UpsertAt[[]A](a)
|
return G.UpsertAt[[]A](a)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,20 +304,14 @@ func ConstNil[A any]() []A {
|
|||||||
return array.ConstNil[[]A]()
|
return array.ConstNil[[]A]()
|
||||||
}
|
}
|
||||||
|
|
||||||
func SliceRight[A any](start int) EM.Endomorphism[[]A] {
|
func SliceRight[A any](start int) func([]A) []A {
|
||||||
return G.SliceRight[[]A](start)
|
return G.SliceRight[[]A](start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy creates a shallow copy of the array
|
|
||||||
func Copy[A any](b []A) []A {
|
func Copy[A any](b []A) []A {
|
||||||
return G.Copy(b)
|
return G.Copy(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone creates a deep copy of the array using the provided endomorphism to clone the values
|
|
||||||
func Clone[A any](f func(A) A) func(as []A) []A {
|
|
||||||
return G.Clone[[]A](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FoldMap maps and folds an array. Map the Array passing each value to the iterating function. Then fold the results using the provided Monoid.
|
// FoldMap maps and folds an array. Map the Array passing each value to the iterating function. Then fold the results using the provided Monoid.
|
||||||
func FoldMap[A, B any](m M.Monoid[B]) func(func(A) B) func([]A) B {
|
func FoldMap[A, B any](m M.Monoid[B]) func(func(A) B) func([]A) B {
|
||||||
return G.FoldMap[[]A](m)
|
return G.FoldMap[[]A](m)
|
||||||
@@ -334,8 +327,8 @@ func Fold[A any](m M.Monoid[A]) func([]A) A {
|
|||||||
return G.Fold[[]A](m)
|
return G.Fold[[]A](m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Push[A any](a A) EM.Endomorphism[[]A] {
|
func Push[A any](a A) func([]A) []A {
|
||||||
return G.Push[EM.Endomorphism[[]A]](a)
|
return G.Push[[]A](a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadFlap[B, A any](fab []func(A) B, a A) []B {
|
func MonadFlap[B, A any](fab []func(A) B, a A) []B {
|
||||||
@@ -345,7 +338,3 @@ func MonadFlap[B, A any](fab []func(A) B, a A) []B {
|
|||||||
func Flap[B, A any](a A) func([]func(A) B) []B {
|
func Flap[B, A any](a A) func([]func(A) B) []B {
|
||||||
return G.Flap[func(A) B, []func(A) B, []B, A, B](a)
|
return G.Flap[func(A) B, []func(A) B, []B, A, B](a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Prepend[A any](head A) EM.Endomorphism[[]A] {
|
|
||||||
return G.Prepend[EM.Endomorphism[[]A]](head)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
// 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 array
|
|
||||||
|
|
||||||
import (
|
|
||||||
G "github.com/IBM/fp-go/array/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[S any](
|
|
||||||
empty S,
|
|
||||||
) []S {
|
|
||||||
return G.Do[[]S, S](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) []T,
|
|
||||||
) func([]S1) []S2 {
|
|
||||||
return G.Bind[[]S1, []S2, []T, S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func([]S1) []S2 {
|
|
||||||
return G.Let[[]S1, []S2, S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
b T,
|
|
||||||
) func([]S1) []S2 {
|
|
||||||
return G.LetTo[[]S1, []S2, S1, S2, T](setter, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func([]T) []S1 {
|
|
||||||
return G.BindTo[[]S1, []T, S1, T](setter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa []T,
|
|
||||||
) func([]S1) []S2 {
|
|
||||||
return G.ApS[[]S1, []S2, []T, S1, S2, T](setter, fa)
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
// 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 array
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/IBM/fp-go/internal/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getLastName(s utils.Initial) []string {
|
|
||||||
return Of("Doe")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGivenName(s utils.WithLastName) []string {
|
|
||||||
return Of("John")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
Bind(utils.SetLastName, getLastName),
|
|
||||||
Bind(utils.SetGivenName, getGivenName),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res, Of("John Doe"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApS(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
ApS(utils.SetLastName, Of("Doe")),
|
|
||||||
ApS(utils.SetGivenName, Of("John")),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res, Of("John Doe"))
|
|
||||||
}
|
|
||||||
@@ -304,11 +304,6 @@ func Copy[AS ~[]A, A any](b AS) AS {
|
|||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
func Clone[AS ~[]A, A any](f func(A) A) func(as AS) AS {
|
|
||||||
// implementation assumes that map does not optimize for the empty array
|
|
||||||
return Map[AS, AS](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FoldMap[AS ~[]A, A, B any](m M.Monoid[B]) func(func(A) B) func(AS) B {
|
func FoldMap[AS ~[]A, A, B any](m M.Monoid[B]) func(func(A) B) func(AS) B {
|
||||||
return func(f func(A) B) func(AS) B {
|
return func(f func(A) B) func(AS) B {
|
||||||
return func(as AS) B {
|
return func(as AS) B {
|
||||||
@@ -335,7 +330,7 @@ func Fold[AS ~[]A, A any](m M.Monoid[A]) func(AS) A {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Push[ENDO ~func(GA) GA, GA ~[]A, A any](a A) ENDO {
|
func Push[GA ~[]A, A any](a A) func(GA) GA {
|
||||||
return F.Bind2nd(array.Push[GA, A], a)
|
return F.Bind2nd(array.Push[GA, A], a)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +341,3 @@ func MonadFlap[FAB ~func(A) B, GFAB ~[]FAB, GB ~[]B, A, B any](fab GFAB, a A) GB
|
|||||||
func Flap[FAB ~func(A) B, GFAB ~[]FAB, GB ~[]B, A, B any](a A) func(GFAB) GB {
|
func Flap[FAB ~func(A) B, GFAB ~[]FAB, GB ~[]B, A, B any](a A) func(GFAB) GB {
|
||||||
return F.Bind2nd(MonadFlap[FAB, GFAB, GB, A, B], a)
|
return F.Bind2nd(MonadFlap[FAB, GFAB, GB, A, B], a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Prepend[ENDO ~func(AS) AS, AS []A, A any](head A) ENDO {
|
|
||||||
return array.Prepend[ENDO](head)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
A "github.com/IBM/fp-go/internal/apply"
|
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[GS ~[]S, S any](
|
|
||||||
empty S,
|
|
||||||
) GS {
|
|
||||||
return Of[GS](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[GS1 ~[]S1, GS2 ~[]S2, GT ~[]T, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) GT,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return C.Bind(
|
|
||||||
Chain[GS1, GS2, S1, S2],
|
|
||||||
Map[GT, GS2, T, S2],
|
|
||||||
setter,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[GS1 ~[]S1, GS2 ~[]S2, S1, S2, T any](
|
|
||||||
key func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return F.Let(
|
|
||||||
Map[GS1, GS2, S1, S2],
|
|
||||||
key,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[GS1 ~[]S1, GS2 ~[]S2, S1, S2, B any](
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
b B,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return F.LetTo(
|
|
||||||
Map[GS1, GS2, S1, S2],
|
|
||||||
key,
|
|
||||||
b,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[GS1 ~[]S1, GT ~[]T, S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(GT) GS1 {
|
|
||||||
return C.BindTo(
|
|
||||||
Map[GT, GS1, T, S1],
|
|
||||||
setter,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[GS1 ~[]S1, GS2 ~[]S2, GT ~[]T, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa GT,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return A.ApS(
|
|
||||||
Ap[GS2, []func(T) S2, GT, S2, T],
|
|
||||||
Map[GS1, []func(T) S2, S1, func(T) S2],
|
|
||||||
setter,
|
|
||||||
fa,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -24,10 +24,10 @@ import (
|
|||||||
func concat[T any](left, right []T) []T {
|
func concat[T any](left, right []T) []T {
|
||||||
// some performance checks
|
// some performance checks
|
||||||
ll := len(left)
|
ll := len(left)
|
||||||
|
lr := len(right)
|
||||||
if ll == 0 {
|
if ll == 0 {
|
||||||
return right
|
return right
|
||||||
}
|
}
|
||||||
lr := len(right)
|
|
||||||
if lr == 0 {
|
if lr == 0 {
|
||||||
return left
|
return left
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ package nonempty
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
G "github.com/IBM/fp-go/array/generic"
|
G "github.com/IBM/fp-go/array/generic"
|
||||||
EM "github.com/IBM/fp-go/endomorphism"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
"github.com/IBM/fp-go/internal/array"
|
"github.com/IBM/fp-go/internal/array"
|
||||||
S "github.com/IBM/fp-go/semigroup"
|
S "github.com/IBM/fp-go/semigroup"
|
||||||
@@ -66,12 +65,6 @@ func Reduce[A, B any](f func(B, A) B, initial B) func(NonEmptyArray[A]) B {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReduceRight[A, B any](f func(A, B) B, initial B) func(NonEmptyArray[A]) B {
|
|
||||||
return func(as NonEmptyArray[A]) B {
|
|
||||||
return array.ReduceRight(as, f, initial)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Tail[A any](as NonEmptyArray[A]) []A {
|
func Tail[A any](as NonEmptyArray[A]) []A {
|
||||||
return as[1:]
|
return as[1:]
|
||||||
}
|
}
|
||||||
@@ -129,8 +122,3 @@ func Fold[A any](s S.Semigroup[A]) func(NonEmptyArray[A]) A {
|
|||||||
return array.Reduce(Tail(as), s.Concat, Head(as))
|
return array.Reduce(Tail(as), s.Concat, Head(as))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepend prepends a single value to an array
|
|
||||||
func Prepend[A any](head A) EM.Endomorphism[NonEmptyArray[A]] {
|
|
||||||
return array.Prepend[EM.Endomorphism[NonEmptyArray[A]]](head)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
// 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"
|
|
||||||
|
|
||||||
RA "github.com/IBM/fp-go/array"
|
|
||||||
EQ "github.com/IBM/fp-go/eq"
|
|
||||||
L "github.com/IBM/fp-go/internal/monad/testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AssertLaws asserts the apply monad laws for the array monad
|
|
||||||
func AssertLaws[A, B, C any](t *testing.T,
|
|
||||||
eqa EQ.Eq[A],
|
|
||||||
eqb EQ.Eq[B],
|
|
||||||
eqc EQ.Eq[C],
|
|
||||||
|
|
||||||
ab func(A) B,
|
|
||||||
bc func(B) C,
|
|
||||||
) func(a A) bool {
|
|
||||||
|
|
||||||
return L.AssertLaws(t,
|
|
||||||
RA.Eq(eqa),
|
|
||||||
RA.Eq(eqb),
|
|
||||||
RA.Eq(eqc),
|
|
||||||
|
|
||||||
RA.Of[A],
|
|
||||||
RA.Of[B],
|
|
||||||
RA.Of[C],
|
|
||||||
|
|
||||||
RA.Of[func(A) A],
|
|
||||||
RA.Of[func(A) B],
|
|
||||||
RA.Of[func(B) C],
|
|
||||||
RA.Of[func(func(A) B) B],
|
|
||||||
|
|
||||||
RA.MonadMap[A, A],
|
|
||||||
RA.MonadMap[A, B],
|
|
||||||
RA.MonadMap[A, C],
|
|
||||||
RA.MonadMap[B, C],
|
|
||||||
|
|
||||||
RA.MonadMap[func(B) C, func(func(A) B) func(A) C],
|
|
||||||
|
|
||||||
RA.MonadChain[A, A],
|
|
||||||
RA.MonadChain[A, B],
|
|
||||||
RA.MonadChain[A, C],
|
|
||||||
RA.MonadChain[B, C],
|
|
||||||
|
|
||||||
RA.MonadAp[A, A],
|
|
||||||
RA.MonadAp[B, A],
|
|
||||||
RA.MonadAp[C, B],
|
|
||||||
RA.MonadAp[C, A],
|
|
||||||
|
|
||||||
RA.MonadAp[B, func(A) B],
|
|
||||||
RA.MonadAp[func(A) C, func(A) B],
|
|
||||||
|
|
||||||
ab,
|
|
||||||
bc,
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
// 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"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMonadLaws(t *testing.T) {
|
|
||||||
// some comparison
|
|
||||||
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, eqa, eqb, eqc, ab, bc)
|
|
||||||
|
|
||||||
assert.True(t, laws(true))
|
|
||||||
assert.True(t, laws(false))
|
|
||||||
}
|
|
||||||
@@ -34,6 +34,5 @@ func Commands() []*C.Command {
|
|||||||
IOEitherCommand(),
|
IOEitherCommand(),
|
||||||
IOCommand(),
|
IOCommand(),
|
||||||
IOOptionCommand(),
|
IOOptionCommand(),
|
||||||
DICommand(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
231
cli/di.go
231
cli/di.go
@@ -1,231 +0,0 @@
|
|||||||
// 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 cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
C "github.com/urfave/cli/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func generateMakeProvider(f *os.File, i int) {
|
|
||||||
// non generic version
|
|
||||||
fmt.Fprintf(f, "\n// MakeProvider%d creates a [DIE.Provider] for an [InjectionToken] from a function with %d dependencies\n", i, i)
|
|
||||||
fmt.Fprintf(f, "func MakeProvider%d[", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
if j > 0 {
|
|
||||||
fmt.Fprintf(f, ", ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, "T%d", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " any, R any](\n")
|
|
||||||
fmt.Fprintf(f, " token InjectionToken[R],\n")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " d%d Dependency[T%d],\n", j+1, j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " f func(")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
if j > 0 {
|
|
||||||
fmt.Fprintf(f, ", ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, "T%d", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, ") IOE.IOEither[error, R],\n")
|
|
||||||
fmt.Fprintf(f, ") DIE.Provider {\n")
|
|
||||||
fmt.Fprint(f, " return DIE.MakeProvider(\n")
|
|
||||||
fmt.Fprint(f, " token,\n")
|
|
||||||
fmt.Fprintf(f, " MakeProviderFactory%d(\n", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " d%d,\n", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprint(f, " f,\n")
|
|
||||||
fmt.Fprint(f, " ))\n")
|
|
||||||
fmt.Fprintf(f, "}\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateMakeTokenWithDefault(f *os.File, i int) {
|
|
||||||
// non generic version
|
|
||||||
fmt.Fprintf(f, "\n// MakeTokenWithDefault%d creates an [InjectionToken] with a default implementation with %d dependencies\n", i, i)
|
|
||||||
fmt.Fprintf(f, "func MakeTokenWithDefault%d[", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
if j > 0 {
|
|
||||||
fmt.Fprintf(f, ", ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, "T%d", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " any, R any](\n")
|
|
||||||
fmt.Fprintf(f, " name string,\n")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " d%d Dependency[T%d],\n", j+1, j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " f func(")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
if j > 0 {
|
|
||||||
fmt.Fprintf(f, ", ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, "T%d", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, ") IOE.IOEither[error, R],\n")
|
|
||||||
fmt.Fprintf(f, ") InjectionToken[R] {\n")
|
|
||||||
fmt.Fprintf(f, " return MakeTokenWithDefault[R](name, MakeProviderFactory%d(\n", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " d%d,\n", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprint(f, " f,\n")
|
|
||||||
fmt.Fprint(f, " ))\n")
|
|
||||||
fmt.Fprintf(f, "}\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateMakeProviderFactory(f *os.File, i int) {
|
|
||||||
// non generic version
|
|
||||||
fmt.Fprintf(f, "\n// MakeProviderFactory%d creates a [DIE.ProviderFactory] from a function with %d arguments and %d dependencies\n", i, i, i)
|
|
||||||
fmt.Fprintf(f, "func MakeProviderFactory%d[", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
if j > 0 {
|
|
||||||
fmt.Fprintf(f, ", ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, "T%d", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " any, R any](\n")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " d%d Dependency[T%d],\n", j+1, j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " f func(")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
if j > 0 {
|
|
||||||
fmt.Fprintf(f, ", ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, "T%d", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, ") IOE.IOEither[error, R],\n")
|
|
||||||
fmt.Fprintf(f, ") DIE.ProviderFactory {\n")
|
|
||||||
fmt.Fprint(f, " return DIE.MakeProviderFactory(\n")
|
|
||||||
fmt.Fprint(f, " A.From[DIE.Dependency](\n")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " d%d,\n", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprint(f, " ),\n")
|
|
||||||
fmt.Fprintf(f, " eraseProviderFactory%d(\n", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " d%d,\n", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprint(f, " f,\n")
|
|
||||||
fmt.Fprint(f, " ),\n")
|
|
||||||
fmt.Fprint(f, " )\n")
|
|
||||||
fmt.Fprintf(f, "}\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateEraseProviderFactory(f *os.File, i int) {
|
|
||||||
// non generic version
|
|
||||||
fmt.Fprintf(f, "\n// eraseProviderFactory%d creates a function that takes a variadic number of untyped arguments and from a function of %d strongly typed arguments and %d dependencies\n", i, i, i)
|
|
||||||
fmt.Fprintf(f, "func eraseProviderFactory%d[", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
if j > 0 {
|
|
||||||
fmt.Fprintf(f, ", ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, "T%d", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " any, R any](\n")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " d%d Dependency[T%d],\n", j+1, j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " f func(")
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
if j > 0 {
|
|
||||||
fmt.Fprintf(f, ", ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, "T%d", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, ") IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {\n")
|
|
||||||
fmt.Fprintf(f, " ft := eraseTuple(T.Tupled%d(f))\n", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " t%d := lookupAt[T%d](%d, d%d)\n", j+1, j+1, j, j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprint(f, " return func(params ...any) IOE.IOEither[error, any] {\n")
|
|
||||||
fmt.Fprintf(f, " return ft(E.SequenceT%d(\n", i)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
fmt.Fprintf(f, " t%d(params),\n", j+1)
|
|
||||||
}
|
|
||||||
fmt.Fprint(f, " ))\n")
|
|
||||||
fmt.Fprint(f, " }\n")
|
|
||||||
fmt.Fprintf(f, "}\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateDIHelpers(filename string, count int) error {
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
absDir, err := filepath.Abs(dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pkg := filepath.Base(absDir)
|
|
||||||
f, err := os.Create(filepath.Clean(filename))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
// log
|
|
||||||
log.Printf("Generating code in [%s] for package [%s] with [%d] repetitions ...", filename, pkg, count)
|
|
||||||
|
|
||||||
// some header
|
|
||||||
fmt.Fprintln(f, "// Code generated by go generate; DO NOT EDIT.")
|
|
||||||
fmt.Fprintln(f, "// This file was generated by robots at")
|
|
||||||
fmt.Fprintf(f, "// %s\n\n", time.Now())
|
|
||||||
|
|
||||||
fmt.Fprintf(f, "package %s\n\n", pkg)
|
|
||||||
|
|
||||||
fmt.Fprint(f, `
|
|
||||||
import (
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
A "github.com/IBM/fp-go/array"
|
|
||||||
DIE "github.com/IBM/fp-go/di/erasure"
|
|
||||||
)
|
|
||||||
`)
|
|
||||||
|
|
||||||
for i := 1; i <= count; i++ {
|
|
||||||
generateEraseProviderFactory(f, i)
|
|
||||||
generateMakeProviderFactory(f, i)
|
|
||||||
generateMakeTokenWithDefault(f, i)
|
|
||||||
generateMakeProvider(f, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DICommand() *C.Command {
|
|
||||||
return &C.Command{
|
|
||||||
Name: "di",
|
|
||||||
Usage: "generate code for the dependency injection package",
|
|
||||||
Flags: []C.Flag{
|
|
||||||
flagCount,
|
|
||||||
flagFilename,
|
|
||||||
},
|
|
||||||
Action: func(ctx *C.Context) error {
|
|
||||||
return generateDIHelpers(
|
|
||||||
ctx.String(keyFilename),
|
|
||||||
ctx.Int(keyCount),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
28
cli/pipe.go
28
cli/pipe.go
@@ -295,16 +295,15 @@ func recurseCurry(f *os.File, indent string, total, count int) {
|
|||||||
func generateCurry(f *os.File, i int) {
|
func generateCurry(f *os.File, i int) {
|
||||||
// Create the curry version
|
// Create the curry version
|
||||||
fmt.Fprintf(f, "\n// Curry%d takes a function with %d parameters and returns a cascade of functions each taking only one parameter.\n// The inverse function is [Uncurry%d]\n", i, i, i)
|
fmt.Fprintf(f, "\n// Curry%d takes a function with %d parameters and returns a cascade of functions each taking only one parameter.\n// The inverse function is [Uncurry%d]\n", i, i, i)
|
||||||
fmt.Fprintf(f, "func Curry%d[FCT ~func(T0", i)
|
fmt.Fprintf(f, "func Curry%d[T0", i)
|
||||||
for j := 1; j < i; j++ {
|
for j := 1; j <= i; j++ {
|
||||||
fmt.Fprintf(f, ", T%d", j)
|
fmt.Fprintf(f, ", T%d", j)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(f, ") T%d", i)
|
fmt.Fprintf(f, " any](f func(T0")
|
||||||
// type arguments
|
for j := 2; j <= i; j++ {
|
||||||
for j := 0; j <= i; j++ {
|
fmt.Fprintf(f, ", T%d", j-1)
|
||||||
fmt.Fprintf(f, ", T%d", j)
|
|
||||||
}
|
}
|
||||||
fmt.Fprintf(f, " any](f FCT) func(T0)")
|
fmt.Fprintf(f, ") T%d) func(T0)", i)
|
||||||
for j := 2; j <= i; j++ {
|
for j := 2; j <= i; j++ {
|
||||||
fmt.Fprintf(f, " func(T%d)", j-1)
|
fmt.Fprintf(f, " func(T%d)", j-1)
|
||||||
}
|
}
|
||||||
@@ -316,16 +315,15 @@ func generateCurry(f *os.File, i int) {
|
|||||||
func generateUncurry(f *os.File, i int) {
|
func generateUncurry(f *os.File, i int) {
|
||||||
// Create the uncurry version
|
// Create the uncurry version
|
||||||
fmt.Fprintf(f, "\n// Uncurry%d takes a cascade of %d functions each taking only one parameter and returns a function with %d parameters .\n// The inverse function is [Curry%d]\n", i, i, i, i)
|
fmt.Fprintf(f, "\n// Uncurry%d takes a cascade of %d functions each taking only one parameter and returns a function with %d parameters .\n// The inverse function is [Curry%d]\n", i, i, i, i)
|
||||||
fmt.Fprintf(f, "func Uncurry%d[FCT ~func(T0)", i)
|
fmt.Fprintf(f, "func Uncurry%d[T0", i)
|
||||||
for j := 1; j < i; j++ {
|
for j := 1; j <= i; j++ {
|
||||||
fmt.Fprintf(f, " func(T%d)", j)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(f, " T%d", i)
|
|
||||||
// the type parameters
|
|
||||||
for j := 0; j <= i; j++ {
|
|
||||||
fmt.Fprintf(f, ", T%d", j)
|
fmt.Fprintf(f, ", T%d", j)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(f, " any](f FCT) func(")
|
fmt.Fprintf(f, " any](f")
|
||||||
|
for j := 1; j <= i; j++ {
|
||||||
|
fmt.Fprintf(f, " func(T%d)", j-1)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(f, " T%d) func(", i)
|
||||||
for j := 1; j <= i; j++ {
|
for j := 1; j <= i; j++ {
|
||||||
if j > 1 {
|
if j > 1 {
|
||||||
fmt.Fprintf(f, ", ")
|
fmt.Fprintf(f, ", ")
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
// 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 readereither
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
G "github.com/IBM/fp-go/readereither/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[S any](
|
|
||||||
empty S,
|
|
||||||
) ReaderEither[S] {
|
|
||||||
return G.Do[ReaderEither[S], context.Context, error, S](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) ReaderEither[T],
|
|
||||||
) func(ReaderEither[S1]) ReaderEither[S2] {
|
|
||||||
return G.Bind[ReaderEither[S1], ReaderEither[S2], ReaderEither[T], context.Context, error, S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(ReaderEither[S1]) ReaderEither[S2] {
|
|
||||||
return G.Let[ReaderEither[S1], ReaderEither[S2], context.Context, error, S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
b T,
|
|
||||||
) func(ReaderEither[S1]) ReaderEither[S2] {
|
|
||||||
return G.LetTo[ReaderEither[S1], ReaderEither[S2], context.Context, error, S1, S2, T](setter, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(ReaderEither[T]) ReaderEither[S1] {
|
|
||||||
return G.BindTo[ReaderEither[S1], ReaderEither[T], context.Context, error, S1, T](setter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa ReaderEither[T],
|
|
||||||
) func(ReaderEither[S1]) ReaderEither[S2] {
|
|
||||||
return G.ApS[ReaderEither[S1], ReaderEither[S2], ReaderEither[T], context.Context, error, S1, S2, T](setter, fa)
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// 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 readereither
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/IBM/fp-go/internal/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getLastName(s utils.Initial) ReaderEither[string] {
|
|
||||||
return Of("Doe")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGivenName(s utils.WithLastName) ReaderEither[string] {
|
|
||||||
return Of("John")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
Bind(utils.SetLastName, getLastName),
|
|
||||||
Bind(utils.SetGivenName, getGivenName),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(context.Background()), E.Of[error]("John Doe"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApS(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
ApS(utils.SetLastName, Of("Doe")),
|
|
||||||
ApS(utils.SetGivenName, Of("John")),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(context.Background()), E.Of[error]("John Doe"))
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
// 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 readerioeither
|
|
||||||
|
|
||||||
import (
|
|
||||||
G "github.com/IBM/fp-go/context/readerioeither/generic"
|
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[S any](
|
|
||||||
empty S,
|
|
||||||
) ReaderIOEither[S] {
|
|
||||||
return G.Do[ReaderIOEither[S], IOE.IOEither[error, S], S](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) ReaderIOEither[T],
|
|
||||||
) func(ReaderIOEither[S1]) ReaderIOEither[S2] {
|
|
||||||
return G.Bind[ReaderIOEither[S1], ReaderIOEither[S2], ReaderIOEither[T], IOE.IOEither[error, S1], IOE.IOEither[error, S2], IOE.IOEither[error, T], S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(ReaderIOEither[S1]) ReaderIOEither[S2] {
|
|
||||||
return G.Let[ReaderIOEither[S1], ReaderIOEither[S2], IOE.IOEither[error, S1], IOE.IOEither[error, S2], S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
b T,
|
|
||||||
) func(ReaderIOEither[S1]) ReaderIOEither[S2] {
|
|
||||||
return G.LetTo[ReaderIOEither[S1], ReaderIOEither[S2], IOE.IOEither[error, S1], IOE.IOEither[error, S2], S1, S2, T](setter, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(ReaderIOEither[T]) ReaderIOEither[S1] {
|
|
||||||
return G.BindTo[ReaderIOEither[S1], ReaderIOEither[T], IOE.IOEither[error, S1], IOE.IOEither[error, T], S1, T](setter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa ReaderIOEither[T],
|
|
||||||
) func(ReaderIOEither[S1]) ReaderIOEither[S2] {
|
|
||||||
return G.ApS[ReaderIOEither[func(T) S2], ReaderIOEither[S1], ReaderIOEither[S2], ReaderIOEither[T], IOE.IOEither[error, func(T) S2], IOE.IOEither[error, S1], IOE.IOEither[error, S2], IOE.IOEither[error, T], S1, S2, T](setter, fa)
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// 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 readerioeither
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/IBM/fp-go/internal/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getLastName(s utils.Initial) ReaderIOEither[string] {
|
|
||||||
return Of("Doe")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGivenName(s utils.WithLastName) ReaderIOEither[string] {
|
|
||||||
return Of("John")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
Bind(utils.SetLastName, getLastName),
|
|
||||||
Bind(utils.SetGivenName, getGivenName),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(context.Background())(), E.Of[error]("John Doe"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApS(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
ApS(utils.SetLastName, Of("Doe")),
|
|
||||||
ApS(utils.SetGivenName, Of("John")),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(context.Background())(), E.Of[error]("John Doe"))
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
ET "github.com/IBM/fp-go/either"
|
|
||||||
A "github.com/IBM/fp-go/internal/apply"
|
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[GRS ~func(context.Context) GS, GS ~func() ET.Either[error, S], S any](
|
|
||||||
empty S,
|
|
||||||
) GRS {
|
|
||||||
return Of[GRS, GS, S](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[GRS1 ~func(context.Context) GS1, GRS2 ~func(context.Context) GS2, GRT ~func(context.Context) GT, GS1 ~func() ET.Either[error, S1], GS2 ~func() ET.Either[error, S2], GT ~func() ET.Either[error, T], S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) GRT,
|
|
||||||
) func(GRS1) GRS2 {
|
|
||||||
return C.Bind(
|
|
||||||
Chain[GRS1, GRS2, GS1, GS2, S1, S2],
|
|
||||||
Map[GRT, GRS2, GT, GS2, T, S2],
|
|
||||||
setter,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[GRS1 ~func(context.Context) GS1, GRS2 ~func(context.Context) GS2, GS1 ~func() ET.Either[error, S1], GS2 ~func() ET.Either[error, S2], S1, S2, T any](
|
|
||||||
key func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(GRS1) GRS2 {
|
|
||||||
return F.Let(
|
|
||||||
Map[GRS1, GRS2, GS1, GS2, S1, S2],
|
|
||||||
key,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[GRS1 ~func(context.Context) GS1, GRS2 ~func(context.Context) GS2, GS1 ~func() ET.Either[error, S1], GS2 ~func() ET.Either[error, S2], S1, S2, B any](
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
b B,
|
|
||||||
) func(GRS1) GRS2 {
|
|
||||||
return F.LetTo(
|
|
||||||
Map[GRS1, GRS2, GS1, GS2, S1, S2],
|
|
||||||
key,
|
|
||||||
b,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[GRS1 ~func(context.Context) GS1, GRT ~func(context.Context) GT, GS1 ~func() ET.Either[error, S1], GT ~func() ET.Either[error, T], S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(GRT) GRS1 {
|
|
||||||
return C.BindTo(
|
|
||||||
Map[GRT, GRS1, GT, GS1, T, S1],
|
|
||||||
setter,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[GRTS1 ~func(context.Context) GTS1, GRS1 ~func(context.Context) GS1, GRS2 ~func(context.Context) GS2, GRT ~func(context.Context) GT, GTS1 ~func() ET.Either[error, func(T) S2], GS1 ~func() ET.Either[error, S1], GS2 ~func() ET.Either[error, S2], GT ~func() ET.Either[error, T], S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa GRT,
|
|
||||||
) func(GRS1) GRS2 {
|
|
||||||
return A.ApS(
|
|
||||||
Ap[GRS2, GRTS1, GRT, GS2, GTS1, GT],
|
|
||||||
Map[GRS1, GRTS1, GS1, GTS1, S1, func(T) S2],
|
|
||||||
setter,
|
|
||||||
fa,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
// 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 builder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
RIOE "github.com/IBM/fp-go/context/readerioeither"
|
|
||||||
RIOEH "github.com/IBM/fp-go/context/readerioeither/http"
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
R "github.com/IBM/fp-go/http/builder"
|
|
||||||
H "github.com/IBM/fp-go/http/headers"
|
|
||||||
LZ "github.com/IBM/fp-go/lazy"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Requester(builder *R.Builder) RIOEH.Requester {
|
|
||||||
|
|
||||||
withBody := F.Curry3(func(data []byte, url string, method string) RIOE.ReaderIOEither[*http.Request] {
|
|
||||||
return RIOE.TryCatch(func(ctx context.Context) func() (*http.Request, error) {
|
|
||||||
return func() (*http.Request, error) {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, method, url, bytes.NewReader(data))
|
|
||||||
if err == nil {
|
|
||||||
req.Header.Set(H.ContentLength, strconv.Itoa(len(data)))
|
|
||||||
H.Monoid.Concat(req.Header, builder.GetHeaders())
|
|
||||||
}
|
|
||||||
return req, err
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
withoutBody := F.Curry2(func(url string, method string) RIOE.ReaderIOEither[*http.Request] {
|
|
||||||
return RIOE.TryCatch(func(ctx context.Context) func() (*http.Request, error) {
|
|
||||||
return func() (*http.Request, error) {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, method, url, nil)
|
|
||||||
if err == nil {
|
|
||||||
H.Monoid.Concat(req.Header, builder.GetHeaders())
|
|
||||||
}
|
|
||||||
return req, err
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return F.Pipe5(
|
|
||||||
builder.GetBody(),
|
|
||||||
O.Fold(LZ.Of(E.Of[error](withoutBody)), E.Map[error](withBody)),
|
|
||||||
E.Ap[func(string) RIOE.ReaderIOEither[*http.Request]](builder.GetTargetUrl()),
|
|
||||||
E.Flap[error, RIOE.ReaderIOEither[*http.Request]](builder.GetMethod()),
|
|
||||||
E.GetOrElse(RIOE.Left[*http.Request]),
|
|
||||||
RIOE.Map(func(req *http.Request) *http.Request {
|
|
||||||
req.Header = H.Monoid.Concat(req.Header, builder.GetHeaders())
|
|
||||||
return req
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
// 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 builder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
RIOE "github.com/IBM/fp-go/context/readerioeither"
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
R "github.com/IBM/fp-go/http/builder"
|
|
||||||
IO "github.com/IBM/fp-go/io"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBuilderWithQuery(t *testing.T) {
|
|
||||||
// add some query
|
|
||||||
withLimit := R.WithQueryArg("limit")("10")
|
|
||||||
withUrl := R.WithUrl("http://www.example.org?a=b")
|
|
||||||
|
|
||||||
b := F.Pipe2(
|
|
||||||
R.Default,
|
|
||||||
withLimit,
|
|
||||||
withUrl,
|
|
||||||
)
|
|
||||||
|
|
||||||
req := F.Pipe3(
|
|
||||||
b,
|
|
||||||
Requester,
|
|
||||||
RIOE.Map(func(r *http.Request) *url.URL {
|
|
||||||
return r.URL
|
|
||||||
}),
|
|
||||||
RIOE.ChainFirstIOK(func(u *url.URL) IO.IO[any] {
|
|
||||||
return IO.FromImpure(func() {
|
|
||||||
q := u.Query()
|
|
||||||
assert.Equal(t, "10", q.Get("limit"))
|
|
||||||
assert.Equal(t, "b", q.Get("a"))
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.True(t, E.IsRight(req(context.Background())()))
|
|
||||||
}
|
|
||||||
38
di/app.go
38
di/app.go
@@ -1,38 +0,0 @@
|
|||||||
// 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 di
|
|
||||||
|
|
||||||
import (
|
|
||||||
DIE "github.com/IBM/fp-go/di/erasure"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
IO "github.com/IBM/fp-go/io"
|
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// InjMain is the [InjectionToken] for the main application
|
|
||||||
InjMain = MakeToken[any]("APP")
|
|
||||||
|
|
||||||
// Main is the resolver for the main application
|
|
||||||
Main = Resolve(InjMain)
|
|
||||||
)
|
|
||||||
|
|
||||||
// RunMain runs the main application from a set of [DIE.Provider]s
|
|
||||||
var RunMain = F.Flow3(
|
|
||||||
DIE.MakeInjector,
|
|
||||||
Main,
|
|
||||||
IOE.Fold(IO.Of[error], F.Constant1[any](IO.Of[error](nil))),
|
|
||||||
)
|
|
||||||
43
di/doc.go
43
di/doc.go
@@ -1,43 +0,0 @@
|
|||||||
// 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 di implements functions and data types supporting dependency injection patterns
|
|
||||||
//
|
|
||||||
// The fundamental building block is the concept of a [Dependency]. This describes the abstract concept of a function, service or value together with its type.
|
|
||||||
// Examples for dependencies can be as simple as configuration values such as the API URL for a service, the current username, a [Dependency] could be the map
|
|
||||||
// of the configuration environment, an http client or as complex as a service interface. Important is that a [Dependency] only defines the concept but
|
|
||||||
// not the implementation.
|
|
||||||
//
|
|
||||||
// The implementation of a [Dependency] is called a [Provider], the dependency of an `API URL` could e.g. be realized by a provider that consults the environment to read the information
|
|
||||||
// or a config file or simply hardcode it.
|
|
||||||
// In many cases the implementation of a [Provider] depends in turn on other [Dependency] (but never directly on other [Provider]s), a provider for an `API URL` that reads
|
|
||||||
// the information from the environment would e.g. depend on a [Dependency] that represents this environment.
|
|
||||||
//
|
|
||||||
// It is the resposibility of the [InjectableFactory] to create an instance of a [Dependency]. All instances are considered singletons. Create an [InjectableFactory] via the [MakeInjector] method. Use [Resolve] to create a strongly typed
|
|
||||||
// factory for a particular [InjectionToken].
|
|
||||||
//
|
|
||||||
// In most cases it is not required to use [InjectableFactory] directly, instead you would create a [Provider] via the [MakeProvider2] method (suffix indicates the number of dependencies). In this call
|
|
||||||
// you give a number of (strongly typed) [Dependency] identifiers and a (strongly typed) factory function for the implementation. The dependency injection framework makes
|
|
||||||
// sure to resolve the dependencies before calling the factory method.
|
|
||||||
//
|
|
||||||
// For convenience purposes it can be helpful to attach a default implementation of a [Dependency]. In this case use the [MakeTokenWithDefault2] method (suffix indicates the number of dependencies)
|
|
||||||
// to define the [InjectionToken].
|
|
||||||
//
|
|
||||||
// [Provider]: [github.com/IBM/fp-go/di/erasure.Provider]
|
|
||||||
// [InjectableFactory]: [github.com/IBM/fp-go/di/erasure.InjectableFactory]
|
|
||||||
// [MakeInjector]: [github.com/IBM/fp-go/di/erasure.MakeInjector]
|
|
||||||
package di
|
|
||||||
|
|
||||||
//go:generate go run .. di --count 10 --filename gen.go
|
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -114,9 +115,6 @@ func itemProviderFactory(fcts []ProviderFactory) ProviderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MakeInjector creates an [InjectableFactory] based on a set of [Provider]s
|
// MakeInjector creates an [InjectableFactory] based on a set of [Provider]s
|
||||||
//
|
|
||||||
// The resulting [InjectableFactory] can then be used to retrieve service instances given their [Dependency]. The implementation
|
|
||||||
// makes sure to transitively resolve the required dependencies.
|
|
||||||
func MakeInjector(providers []Provider) InjectableFactory {
|
func MakeInjector(providers []Provider) InjectableFactory {
|
||||||
|
|
||||||
type Result = IOE.IOEither[error, any]
|
type Result = IOE.IOEither[error, any]
|
||||||
|
|||||||
@@ -31,29 +31,25 @@ import (
|
|||||||
R "github.com/IBM/fp-go/record"
|
R "github.com/IBM/fp-go/record"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type InjectableFactory = func(Dependency) IOE.IOEither[error, any]
|
||||||
// InjectableFactory is a factory function that can create an untyped instance of a service based on its [Dependency] identifier
|
type ProviderFactory = func(InjectableFactory) IOE.IOEither[error, any]
|
||||||
InjectableFactory = func(Dependency) IOE.IOEither[error, any]
|
|
||||||
ProviderFactory = func(InjectableFactory) IOE.IOEither[error, any]
|
|
||||||
|
|
||||||
paramIndex = map[int]int
|
type paramIndex = map[int]int
|
||||||
paramValue = map[int]any
|
type paramValue = map[int]any
|
||||||
handler = func(paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue]
|
type handler = func(paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue]
|
||||||
mapping = map[int]paramIndex
|
|
||||||
|
|
||||||
Provider interface {
|
type Provider interface {
|
||||||
fmt.Stringer
|
fmt.Stringer
|
||||||
// Provides returns the [Dependency] implemented by this provider
|
// Provides returns the [Dependency] implemented by this provider
|
||||||
Provides() Dependency
|
Provides() Dependency
|
||||||
// Factory returns s function that can create an instance of the dependency based on an [InjectableFactory]
|
// Factory returns s function that can create an instance of the dependency based on an [InjectableFactory]
|
||||||
Factory() ProviderFactory
|
Factory() ProviderFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
provider struct {
|
type provider struct {
|
||||||
provides Dependency
|
provides Dependency
|
||||||
factory ProviderFactory
|
factory ProviderFactory
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
func (p *provider) Provides() Dependency {
|
func (p *provider) Provides() Dependency {
|
||||||
return p.provides
|
return p.provides
|
||||||
@@ -76,16 +72,11 @@ func mapFromToken(idx int, token Dependency) map[int]paramIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Empty is the empty array of providers
|
|
||||||
Empty = A.Empty[Provider]()
|
|
||||||
|
|
||||||
mergeTokenMaps = R.UnionMonoid[int](R.UnionLastSemigroup[int, int]())
|
mergeTokenMaps = R.UnionMonoid[int](R.UnionLastSemigroup[int, int]())
|
||||||
foldDeps = A.FoldMapWithIndex[Dependency](mergeTokenMaps)(mapFromToken)
|
foldDeps = A.FoldMapWithIndex[Dependency](mergeTokenMaps)(mapFromToken)
|
||||||
mergeMaps = R.UnionLastMonoid[int, any]()
|
mergeMaps = R.UnionLastMonoid[int, any]()
|
||||||
collectParams = R.CollectOrd[any, any](Int.Ord)(F.SK[int, any])
|
collectParams = R.CollectOrd[any, any](Int.Ord)(F.SK[int, any])
|
||||||
|
|
||||||
mapDeps = F.Curry2(A.MonadMap[Dependency, IOE.IOEither[error, any]])
|
|
||||||
|
|
||||||
handlers = map[int]handler{
|
handlers = map[int]handler{
|
||||||
Identity: func(mp paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
Identity: func(mp paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||||
return func(res []IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
return func(res []IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||||
@@ -136,13 +127,15 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Mapping = map[int]paramIndex
|
||||||
|
|
||||||
func getAt[T any](ar []T) func(idx int) T {
|
func getAt[T any](ar []T) func(idx int) T {
|
||||||
return func(idx int) T {
|
return func(idx int) T {
|
||||||
return ar[idx]
|
return ar[idx]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMapping(mp mapping) func(res []IOE.IOEither[error, any]) IOE.IOEither[error, []any] {
|
func handleMapping(mp Mapping) func(res []IOE.IOEither[error, any]) IOE.IOEither[error, []any] {
|
||||||
preFct := F.Pipe1(
|
preFct := F.Pipe1(
|
||||||
mp,
|
mp,
|
||||||
R.Collect(func(idx int, p paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
R.Collect(func(idx int, p paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||||
@@ -174,7 +167,7 @@ func MakeProviderFactory(
|
|||||||
fct func(param ...any) IOE.IOEither[error, any]) ProviderFactory {
|
fct func(param ...any) IOE.IOEither[error, any]) ProviderFactory {
|
||||||
|
|
||||||
return F.Flow3(
|
return F.Flow3(
|
||||||
mapDeps(deps),
|
F.Curry2(A.MonadMap[Dependency, IOE.IOEither[error, any]])(deps),
|
||||||
handleMapping(foldDeps(deps)),
|
handleMapping(foldDeps(deps)),
|
||||||
IOE.Chain(F.Unvariadic0(fct)),
|
IOE.Chain(F.Unvariadic0(fct)),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
|||||||
119
di/provider.go
119
di/provider.go
@@ -12,7 +12,6 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package di
|
package di
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -22,6 +21,7 @@ import (
|
|||||||
"github.com/IBM/fp-go/errors"
|
"github.com/IBM/fp-go/errors"
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
|
T "github.com/IBM/fp-go/tuple"
|
||||||
)
|
)
|
||||||
|
|
||||||
func lookupAt[T any](idx int, token Dependency[T]) func(params []any) E.Either[error, T] {
|
func lookupAt[T any](idx int, token Dependency[T]) func(params []any) E.Either[error, T] {
|
||||||
@@ -32,25 +32,49 @@ func lookupAt[T any](idx int, token Dependency[T]) func(params []any) E.Either[e
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func eraseTuple[A, R any](f func(A) IOE.IOEither[error, R]) func(E.Either[error, A]) IOE.IOEither[error, any] {
|
func eraseProviderFactory0[R any](f func() IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
|
||||||
return F.Flow3(
|
|
||||||
IOE.FromEither[error, A],
|
|
||||||
IOE.Chain(f),
|
|
||||||
IOE.Map[error](F.ToAny[R]),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func eraseProviderFactory0[R any](f IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
|
|
||||||
return func(params ...any) IOE.IOEither[error, any] {
|
return func(params ...any) IOE.IOEither[error, any] {
|
||||||
return F.Pipe1(
|
return F.Pipe1(
|
||||||
f,
|
f(),
|
||||||
|
IOE.Map[error](F.ToAny[R]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func eraseProviderFactory1[T1 any, R any](
|
||||||
|
d1 Dependency[T1],
|
||||||
|
f func(T1) IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
|
||||||
|
ft := T.Tupled1(f)
|
||||||
|
t1 := lookupAt[T1](0, d1)
|
||||||
|
return func(params ...any) IOE.IOEither[error, any] {
|
||||||
|
return F.Pipe3(
|
||||||
|
E.SequenceT1(t1(params)),
|
||||||
|
IOE.FromEither[error, T.Tuple1[T1]],
|
||||||
|
IOE.Chain(ft),
|
||||||
|
IOE.Map[error](F.ToAny[R]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func eraseProviderFactory2[T1, T2 any, R any](
|
||||||
|
d1 Dependency[T1],
|
||||||
|
d2 Dependency[T2],
|
||||||
|
f func(T1, T2) IOE.IOEither[error, R]) func(params ...any) IOE.IOEither[error, any] {
|
||||||
|
ft := T.Tupled2(f)
|
||||||
|
t1 := lookupAt[T1](0, d1)
|
||||||
|
t2 := lookupAt[T2](1, d2)
|
||||||
|
return func(params ...any) IOE.IOEither[error, any] {
|
||||||
|
return F.Pipe3(
|
||||||
|
E.SequenceT2(t1(params), t2(params)),
|
||||||
|
IOE.FromEither[error, T.Tuple2[T1, T2]],
|
||||||
|
IOE.Chain(ft),
|
||||||
IOE.Map[error](F.ToAny[R]),
|
IOE.Map[error](F.ToAny[R]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeProviderFactory0[R any](
|
func MakeProviderFactory0[R any](
|
||||||
fct IOE.IOEither[error, R],
|
fct func() IOE.IOEither[error, R],
|
||||||
) DIE.ProviderFactory {
|
) DIE.ProviderFactory {
|
||||||
return DIE.MakeProviderFactory(
|
return DIE.MakeProviderFactory(
|
||||||
A.Empty[DIE.Dependency](),
|
A.Empty[DIE.Dependency](),
|
||||||
@@ -58,14 +82,14 @@ func MakeProviderFactory0[R any](
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeTokenWithDefault0 creates a unique [InjectionToken] for a specific type with an attached default [DIE.Provider]
|
// MakeTokenWithDefault0 create a unique `InjectionToken` for a specific type with an attached default provider
|
||||||
func MakeTokenWithDefault0[R any](name string, fct IOE.IOEither[error, R]) InjectionToken[R] {
|
func MakeTokenWithDefault0[R any](name string, fct func() IOE.IOEither[error, R]) InjectionToken[R] {
|
||||||
return MakeTokenWithDefault[R](name, MakeProviderFactory0(fct))
|
return MakeTokenWithDefault[R](name, MakeProviderFactory0(fct))
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeProvider0[R any](
|
func MakeProvider0[R any](
|
||||||
token InjectionToken[R],
|
token InjectionToken[R],
|
||||||
fct IOE.IOEither[error, R],
|
fct func() IOE.IOEither[error, R],
|
||||||
) DIE.Provider {
|
) DIE.Provider {
|
||||||
return DIE.MakeProvider(
|
return DIE.MakeProvider(
|
||||||
token,
|
token,
|
||||||
@@ -73,7 +97,70 @@ func MakeProvider0[R any](
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeProviderFactory1[T1, R any](
|
||||||
|
d1 Dependency[T1],
|
||||||
|
fct func(T1) IOE.IOEither[error, R],
|
||||||
|
) DIE.ProviderFactory {
|
||||||
|
|
||||||
|
return DIE.MakeProviderFactory(
|
||||||
|
A.From[DIE.Dependency](d1),
|
||||||
|
eraseProviderFactory1(d1, fct),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeTokenWithDefault1 create a unique `InjectionToken` for a specific type with an attached default provider
|
||||||
|
func MakeTokenWithDefault1[T1, R any](name string,
|
||||||
|
d1 Dependency[T1],
|
||||||
|
fct func(T1) IOE.IOEither[error, R]) InjectionToken[R] {
|
||||||
|
return MakeTokenWithDefault[R](name, MakeProviderFactory1(d1, fct))
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeProvider1[T1, R any](
|
||||||
|
token InjectionToken[R],
|
||||||
|
d1 Dependency[T1],
|
||||||
|
fct func(T1) IOE.IOEither[error, R],
|
||||||
|
) DIE.Provider {
|
||||||
|
|
||||||
|
return DIE.MakeProvider(
|
||||||
|
token,
|
||||||
|
MakeProviderFactory1(d1, fct),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeProviderFactory2[T1, T2, R any](
|
||||||
|
d1 Dependency[T1],
|
||||||
|
d2 Dependency[T2],
|
||||||
|
fct func(T1, T2) IOE.IOEither[error, R],
|
||||||
|
) DIE.ProviderFactory {
|
||||||
|
|
||||||
|
return DIE.MakeProviderFactory(
|
||||||
|
A.From[DIE.Dependency](d1, d2),
|
||||||
|
eraseProviderFactory2(d1, d2, fct),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeTokenWithDefault2 create a unique `InjectionToken` for a specific type with an attached default provider
|
||||||
|
func MakeTokenWithDefault2[T1, T2, R any](name string,
|
||||||
|
d1 Dependency[T1],
|
||||||
|
d2 Dependency[T2],
|
||||||
|
fct func(T1, T2) IOE.IOEither[error, R]) InjectionToken[R] {
|
||||||
|
return MakeTokenWithDefault[R](name, MakeProviderFactory2(d1, d2, fct))
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeProvider2[T1, T2, R any](
|
||||||
|
token InjectionToken[R],
|
||||||
|
d1 Dependency[T1],
|
||||||
|
d2 Dependency[T2],
|
||||||
|
fct func(T1, T2) IOE.IOEither[error, R],
|
||||||
|
) DIE.Provider {
|
||||||
|
|
||||||
|
return DIE.MakeProvider(
|
||||||
|
token,
|
||||||
|
MakeProviderFactory2(d1, d2, fct),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// ConstProvider simple implementation for a provider with a constant value
|
// ConstProvider simple implementation for a provider with a constant value
|
||||||
func ConstProvider[R any](token InjectionToken[R], value R) DIE.Provider {
|
func ConstProvider[R any](token InjectionToken[R], value R) DIE.Provider {
|
||||||
return MakeProvider0[R](token, IOE.Of[error](value))
|
return MakeProvider0[R](token, F.Constant(IOE.Of[error](value)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package di
|
package di
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -39,10 +38,12 @@ func TestSimpleProvider(t *testing.T) {
|
|||||||
|
|
||||||
var staticCount int
|
var staticCount int
|
||||||
|
|
||||||
staticValue := func(value string) IOE.IOEither[error, string] {
|
staticValue := func(value string) func() IOE.IOEither[error, string] {
|
||||||
return func() E.Either[error, string] {
|
return func() IOE.IOEither[error, string] {
|
||||||
staticCount++
|
return func() E.Either[error, string] {
|
||||||
return E.Of[error](fmt.Sprintf("Static based on [%s], at [%s]", value, time.Now()))
|
staticCount++
|
||||||
|
return E.Of[error](fmt.Sprintf("Static based on [%s], at [%s]", value, time.Now()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,10 +82,12 @@ func TestOptionalProvider(t *testing.T) {
|
|||||||
|
|
||||||
var staticCount int
|
var staticCount int
|
||||||
|
|
||||||
staticValue := func(value string) IOE.IOEither[error, string] {
|
staticValue := func(value string) func() IOE.IOEither[error, string] {
|
||||||
return func() E.Either[error, string] {
|
return func() IOE.IOEither[error, string] {
|
||||||
staticCount++
|
return func() E.Either[error, string] {
|
||||||
return E.Of[error](fmt.Sprintf("Static based on [%s], at [%s]", value, time.Now()))
|
staticCount++
|
||||||
|
return E.Of[error](fmt.Sprintf("Static based on [%s], at [%s]", value, time.Now()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,10 +182,12 @@ func TestEagerAndLazyProvider(t *testing.T) {
|
|||||||
|
|
||||||
var staticCount int
|
var staticCount int
|
||||||
|
|
||||||
staticValue := func(value string) IOE.IOEither[error, string] {
|
staticValue := func(value string) func() IOE.IOEither[error, string] {
|
||||||
return func() E.Either[error, string] {
|
return func() IOE.IOEither[error, string] {
|
||||||
staticCount++
|
return func() E.Either[error, string] {
|
||||||
return E.Of[error](fmt.Sprintf("Static based on [%s], at [%s]", value, time.Now()))
|
staticCount++
|
||||||
|
return E.Of[error](fmt.Sprintf("Static based on [%s], at [%s]", value, time.Now()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +307,7 @@ func TestTokenWithDefaultProvider(t *testing.T) {
|
|||||||
// token without a default
|
// token without a default
|
||||||
injToken1 := MakeToken[string]("Token1")
|
injToken1 := MakeToken[string]("Token1")
|
||||||
// token with a default
|
// token with a default
|
||||||
injToken2 := MakeTokenWithDefault0("Token2", IOE.Of[error]("Carsten"))
|
injToken2 := MakeTokenWithDefault0("Token2", F.Constant(IOE.Of[error]("Carsten")))
|
||||||
// dependency
|
// dependency
|
||||||
injToken3 := MakeToken[string]("Token3")
|
injToken3 := MakeToken[string]("Token3")
|
||||||
|
|
||||||
@@ -325,7 +330,7 @@ func TestTokenWithDefaultProvider(t *testing.T) {
|
|||||||
|
|
||||||
func TestTokenWithDefaultProviderAndOverride(t *testing.T) {
|
func TestTokenWithDefaultProviderAndOverride(t *testing.T) {
|
||||||
// token with a default
|
// token with a default
|
||||||
injToken2 := MakeTokenWithDefault0("Token2", IOE.Of[error]("Carsten"))
|
injToken2 := MakeTokenWithDefault0("Token2", F.Constant(IOE.Of[error]("Carsten")))
|
||||||
// dependency
|
// dependency
|
||||||
injToken3 := MakeToken[string]("Token3")
|
injToken3 := MakeToken[string]("Token3")
|
||||||
|
|
||||||
|
|||||||
17
di/token.go
17
di/token.go
@@ -42,21 +42,20 @@ type InjectionToken[T any] interface {
|
|||||||
// Identity idenifies this dependency as a mandatory, required dependency, it will be resolved eagerly and injected as `T`.
|
// Identity idenifies this dependency as a mandatory, required dependency, it will be resolved eagerly and injected as `T`.
|
||||||
// If the dependency cannot be resolved, the resolution process fails
|
// If the dependency cannot be resolved, the resolution process fails
|
||||||
Identity() Dependency[T]
|
Identity() Dependency[T]
|
||||||
// Option identifies this dependency as optional, it will be resolved eagerly and injected as [O.Option[T]].
|
// Option identifies this dependency as optional, it will be resolved eagerly and injected as `O.Option[T]`.
|
||||||
// If the dependency cannot be resolved, the resolution process continues and the dependency is represented as [O.None[T]]
|
// If the dependency cannot be resolved, the resolution process continues and the dependency is represented as `O.None[T]`
|
||||||
Option() Dependency[O.Option[T]]
|
Option() Dependency[O.Option[T]]
|
||||||
// IOEither identifies this dependency as mandatory but it will be resolved lazily as a [IOE.IOEither[error, T]]. This
|
// IOEither identifies this dependency as mandatory but it will be resolved lazily as a `IOE.IOEither[error, T]`. This
|
||||||
// value is memoized to make sure the dependency is a singleton.
|
// value is memoized to make sure the dependency is a singleton.
|
||||||
// If the dependency cannot be resolved, the resolution process fails
|
// If the dependency cannot be resolved, the resolution process fails
|
||||||
IOEither() Dependency[IOE.IOEither[error, T]]
|
IOEither() Dependency[IOE.IOEither[error, T]]
|
||||||
// IOOption identifies this dependency as optional but it will be resolved lazily as a [IOO.IOOption[T]]. This
|
// IOOption identifies this dependency as optional but it will be resolved lazily as a `IOO.IOOption[T]`. This
|
||||||
// value is memoized to make sure the dependency is a singleton.
|
// value is memoized to make sure the dependency is a singleton.
|
||||||
// If the dependency cannot be resolved, the resolution process continues and the dependency is represented as the none value.
|
// If the dependency cannot be resolved, the resolution process continues and the dependency is represented as the none value.
|
||||||
IOOption() Dependency[IOO.IOOption[T]]
|
IOOption() Dependency[IOO.IOOption[T]]
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultiInjectionToken uniquely identifies a dependency by giving it an Id, Type and name that can have multiple implementations.
|
// MultiInjectionToken uniquely identifies a dependency by giving it an Id, Type and name.
|
||||||
// Implementations are provided via the [MultiInjectionToken.Item] injection token.
|
|
||||||
type MultiInjectionToken[T any] interface {
|
type MultiInjectionToken[T any] interface {
|
||||||
// Container returns the injection token used to request an array of all provided items
|
// Container returns the injection token used to request an array of all provided items
|
||||||
Container() InjectionToken[[]T]
|
Container() InjectionToken[[]T]
|
||||||
@@ -147,7 +146,7 @@ func (m *multiInjectionToken[T]) Item() InjectionToken[T] {
|
|||||||
return m.item
|
return m.item
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeToken create a unique [InjectionToken] for a specific type
|
// makeToken create a unique `InjectionToken` for a specific type
|
||||||
func makeInjectionToken[T any](name string, providerFactory O.Option[DIE.ProviderFactory]) InjectionToken[T] {
|
func makeInjectionToken[T any](name string, providerFactory O.Option[DIE.ProviderFactory]) InjectionToken[T] {
|
||||||
id := genId()
|
id := genId()
|
||||||
toIdentity := toType[T]()
|
toIdentity := toType[T]()
|
||||||
@@ -159,12 +158,12 @@ func makeInjectionToken[T any](name string, providerFactory O.Option[DIE.Provide
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeToken create a unique [InjectionToken] for a specific type
|
// MakeToken create a unique `InjectionToken` for a specific type
|
||||||
func MakeToken[T any](name string) InjectionToken[T] {
|
func MakeToken[T any](name string) InjectionToken[T] {
|
||||||
return makeInjectionToken[T](name, O.None[DIE.ProviderFactory]())
|
return makeInjectionToken[T](name, O.None[DIE.ProviderFactory]())
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeToken create a unique [InjectionToken] for a specific type
|
// MakeToken create a unique `InjectionToken` for a specific type
|
||||||
func MakeTokenWithDefault[T any](name string, providerFactory DIE.ProviderFactory) InjectionToken[T] {
|
func MakeTokenWithDefault[T any](name string, providerFactory DIE.ProviderFactory) InjectionToken[T] {
|
||||||
return makeInjectionToken[T](name, O.Of(providerFactory))
|
return makeInjectionToken[T](name, O.Of(providerFactory))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package di
|
package di
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package di
|
package di
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
// 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 either
|
|
||||||
|
|
||||||
import (
|
|
||||||
A "github.com/IBM/fp-go/internal/apply"
|
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[E, S any](
|
|
||||||
empty S,
|
|
||||||
) Either[E, S] {
|
|
||||||
return Of[E](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[E, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) Either[E, T],
|
|
||||||
) func(Either[E, S1]) Either[E, S2] {
|
|
||||||
return C.Bind(
|
|
||||||
Chain[E, S1, S2],
|
|
||||||
Map[E, T, S2],
|
|
||||||
setter,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[E, S1, S2, T any](
|
|
||||||
key func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(Either[E, S1]) Either[E, S2] {
|
|
||||||
return F.Let(
|
|
||||||
Map[E, S1, S2],
|
|
||||||
key,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[E, S1, S2, T any](
|
|
||||||
key func(T) func(S1) S2,
|
|
||||||
b T,
|
|
||||||
) func(Either[E, S1]) Either[E, S2] {
|
|
||||||
return F.LetTo(
|
|
||||||
Map[E, S1, S2],
|
|
||||||
key,
|
|
||||||
b,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[E, S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(Either[E, T]) Either[E, S1] {
|
|
||||||
return C.BindTo(
|
|
||||||
Map[E, T, S1],
|
|
||||||
setter,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[E, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa Either[E, T],
|
|
||||||
) func(Either[E, S1]) Either[E, S2] {
|
|
||||||
return A.ApS(
|
|
||||||
Ap[S2, E, T],
|
|
||||||
Map[E, S1, func(T) S2],
|
|
||||||
setter,
|
|
||||||
fa,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
// 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 either
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/IBM/fp-go/internal/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getLastName(s utils.Initial) Either[error, string] {
|
|
||||||
return Of[error]("Doe")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGivenName(s utils.WithLastName) Either[error, string] {
|
|
||||||
return Of[error]("John")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do[error](utils.Empty),
|
|
||||||
Bind(utils.SetLastName, getLastName),
|
|
||||||
Bind(utils.SetGivenName, getGivenName),
|
|
||||||
Map[error](utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res, Of[error]("John Doe"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApS(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do[error](utils.Empty),
|
|
||||||
ApS(utils.SetLastName, Of[error]("Doe")),
|
|
||||||
ApS(utils.SetGivenName, Of[error]("John")),
|
|
||||||
Map[error](utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res, Of[error]("John Doe"))
|
|
||||||
}
|
|
||||||
@@ -67,17 +67,16 @@ func MapTo[E, A, B any](b B) func(Either[E, A]) Either[E, B] {
|
|||||||
return F.Bind2nd(MonadMapTo[E, A, B], b)
|
return F.Bind2nd(MonadMapTo[E, A, B], b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadMapLeft[E1, A, E2 any](fa Either[E1, A], f func(E1) E2) Either[E2, A] {
|
func MonadMapLeft[E, A, B any](fa Either[E, A], f func(E) B) Either[B, A] {
|
||||||
return MonadFold(fa, F.Flow2(f, Left[A, E2]), Right[E2, A])
|
return MonadFold(fa, F.Flow2(f, Left[A, B]), Right[B, A])
|
||||||
}
|
}
|
||||||
|
|
||||||
func Map[E, A, B any](f func(a A) B) func(fa Either[E, A]) Either[E, B] {
|
func Map[E, A, B any](f func(a A) B) func(fa Either[E, A]) Either[E, B] {
|
||||||
return Chain(F.Flow2(f, Right[E, B]))
|
return Chain(F.Flow2(f, Right[E, B]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapLeft applies a mapping function to the error channel
|
func MapLeft[E, A, B any](f func(E) B) func(fa Either[E, A]) Either[B, A] {
|
||||||
func MapLeft[A, E1, E2 any](f func(E1) E2) func(fa Either[E1, A]) Either[E2, A] {
|
return F.Bind2nd(MonadMapLeft[E, A, B], f)
|
||||||
return F.Bind2nd(MonadMapLeft[E1, A, E2], f)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChain[E, A, B any](fa Either[E, A], f func(a A) Either[E, B]) Either[E, B] {
|
func MonadChain[E, A, B any](fa Either[E, A], f func(a A) Either[E, B]) Either[E, B] {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func Eq[E, A any](e EQ.Eq[E], a EQ.Eq[A]) EQ.Eq[Either[E, A]] {
|
|||||||
return EQ.FromEquals(F.Uncurry2(fld))
|
return EQ.FromEquals(F.Uncurry2(fld))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
// FromStrictEquals constructs an `Eq` from the canonical comparison function
|
||||||
func FromStrictEquals[E, A comparable]() EQ.Eq[Either[E, A]] {
|
func FromStrictEquals[E, A comparable]() EQ.Eq[Either[E, A]] {
|
||||||
return Eq(EQ.FromStrictEquals[E](), EQ.FromStrictEquals[A]())
|
return Eq(EQ.FromStrictEquals[E](), EQ.FromStrictEquals[A]())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
// 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 endomorphism
|
|
||||||
|
|
||||||
import (
|
|
||||||
G "github.com/IBM/fp-go/endomorphism/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Curry2 curries a binary function
|
|
||||||
func Curry2[FCT ~func(T0, T1) T1, T0, T1 any](f FCT) func(T0) Endomorphism[T1] {
|
|
||||||
return G.Curry2[Endomorphism[T1]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Curry3 curries a ternary function
|
|
||||||
func Curry3[FCT ~func(T0, T1, T2) T2, T0, T1, T2 any](f FCT) func(T0) func(T1) Endomorphism[T2] {
|
|
||||||
return G.Curry3[Endomorphism[T2]](f)
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
// 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 endomorphism
|
|
||||||
|
|
||||||
import (
|
|
||||||
G "github.com/IBM/fp-go/endomorphism/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
func MonadAp[A any](fab Endomorphism[A], fa A) A {
|
|
||||||
return G.MonadAp[Endomorphism[A]](fab, fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Ap[A any](fa A) func(Endomorphism[A]) A {
|
|
||||||
return G.Ap[Endomorphism[A]](fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChain[A any](ma Endomorphism[A], f Endomorphism[A]) Endomorphism[A] {
|
|
||||||
return G.MonadChain[Endomorphism[A]](ma, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Chain[A any](f Endomorphism[A]) Endomorphism[Endomorphism[A]] {
|
|
||||||
return G.Chain[Endomorphism[Endomorphism[A]], Endomorphism[A], A](f)
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
// 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
|
|
||||||
|
|
||||||
// Curry2 is a duplicate of [F.Curry2] but because of the type system it's not compatible otherwise
|
|
||||||
func Curry2[GT1 ~func(T1) T1, FCT ~func(T0, T1) T1, T0, T1 any](f FCT) func(T0) GT1 {
|
|
||||||
return func(t0 T0) GT1 {
|
|
||||||
return func(t1 T1) T1 {
|
|
||||||
return f(t0, t1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Curry2 is a duplicate of [F.Curry2] but because of the type system it's not compatible otherwise
|
|
||||||
func Curry3[GT2 ~func(T2) T2, FCT ~func(T0, T1, T2) T2, T0, T1, T2 any](f FCT) func(T0) func(T1) GT2 {
|
|
||||||
return func(t0 T0) func(T1) GT2 {
|
|
||||||
return func(t1 T1) GT2 {
|
|
||||||
return func(t2 T2) T2 {
|
|
||||||
return f(t0, t1, t2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
I "github.com/IBM/fp-go/identity/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
func MonadAp[GA ~func(A) A, A any](fab GA, fa A) A {
|
|
||||||
return I.MonadAp[GA, A, A](fab, fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Ap[GA ~func(A) A, A any](fa A) func(GA) A {
|
|
||||||
return I.Ap[GA, A, A](fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChain[GA ~func(A) A, A any](ma GA, f GA) GA {
|
|
||||||
return Compose(ma, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Chain[ENDO ~func(GA) GA, GA ~func(A) A, A any](f GA) ENDO {
|
|
||||||
return Of[ENDO](F.Bind2nd(Compose[GA], f))
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
M "github.com/IBM/fp-go/monoid"
|
|
||||||
S "github.com/IBM/fp-go/semigroup"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Of converts any function to an [Endomorphism]
|
|
||||||
func Of[ENDO ~func(A) A, F ~func(A) A, A any](f F) ENDO {
|
|
||||||
return func(a A) A {
|
|
||||||
return f(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap converts any function to an [Endomorphism]
|
|
||||||
func Wrap[ENDO ~func(A) A, F ~func(A) A, A any](f F) ENDO {
|
|
||||||
return Of[ENDO](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap converts any [Endomorphism] to a normal function
|
|
||||||
func Unwrap[F ~func(A) A, ENDO ~func(A) A, A any](f ENDO) F {
|
|
||||||
return Of[F](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Identity[ENDO ~func(A) A, A any]() ENDO {
|
|
||||||
return Of[ENDO](F.Identity[A])
|
|
||||||
}
|
|
||||||
|
|
||||||
func Compose[ENDO ~func(A) A, A any](f1, f2 ENDO) ENDO {
|
|
||||||
return Of[ENDO](F.Flow2(f1, f2))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Semigroup for the Endomorphism where the `concat` operation is the usual function composition.
|
|
||||||
func Semigroup[ENDO ~func(A) A, A any]() S.Semigroup[ENDO] {
|
|
||||||
return S.MakeSemigroup(Compose[ENDO])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Monoid for the Endomorphism where the `concat` operation is the usual function composition.
|
|
||||||
func Monoid[ENDO ~func(A) A, A any]() M.Monoid[ENDO] {
|
|
||||||
return M.MakeMonoid(Compose[ENDO], Identity[ENDO]())
|
|
||||||
}
|
|
||||||
@@ -16,40 +16,17 @@
|
|||||||
package endomorphism
|
package endomorphism
|
||||||
|
|
||||||
import (
|
import (
|
||||||
G "github.com/IBM/fp-go/endomorphism/generic"
|
F "github.com/IBM/fp-go/function"
|
||||||
M "github.com/IBM/fp-go/monoid"
|
M "github.com/IBM/fp-go/monoid"
|
||||||
S "github.com/IBM/fp-go/semigroup"
|
S "github.com/IBM/fp-go/semigroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Endomorphism is a function that
|
|
||||||
type Endomorphism[A any] func(A) A
|
|
||||||
|
|
||||||
// Of converts any function to an [Endomorphism]
|
|
||||||
func Of[F ~func(A) A, A any](f F) Endomorphism[A] {
|
|
||||||
return G.Of[Endomorphism[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap converts any function to an [Endomorphism]
|
|
||||||
func Wrap[F ~func(A) A, A any](f F) Endomorphism[A] {
|
|
||||||
return G.Wrap[Endomorphism[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap converts any [Endomorphism] to a function
|
|
||||||
func Unwrap[F ~func(A) A, A any](f Endomorphism[A]) F {
|
|
||||||
return G.Unwrap[F](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Identity returns the identity [Endomorphism]
|
|
||||||
func Identity[A any]() Endomorphism[A] {
|
|
||||||
return G.Identity[Endomorphism[A]]()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Semigroup for the Endomorphism where the `concat` operation is the usual function composition.
|
// Semigroup for the Endomorphism where the `concat` operation is the usual function composition.
|
||||||
func Semigroup[A any]() S.Semigroup[Endomorphism[A]] {
|
func Semigroup[A any]() S.Semigroup[func(A) A] {
|
||||||
return G.Semigroup[Endomorphism[A]]()
|
return S.MakeSemigroup(F.Flow2[func(A) A, func(A) A])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monoid for the Endomorphism where the `concat` operation is the usual function composition.
|
// Monoid for the Endomorphism where the `concat` operation is the usual function composition.
|
||||||
func Monoid[A any]() M.Monoid[Endomorphism[A]] {
|
func Monoid[A any]() M.Monoid[func(A) A] {
|
||||||
return G.Monoid[Endomorphism[A]]()
|
return M.MakeMonoid(F.Flow2[func(A) A, func(A) A], F.Identity[A])
|
||||||
}
|
}
|
||||||
|
|||||||
4
eq/eq.go
4
eq/eq.go
@@ -35,12 +35,12 @@ func strictEq[A comparable](a, b A) bool {
|
|||||||
return a == b
|
return a == b
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
// FromStrictEquals constructs an `Eq` from the canonical comparison function
|
||||||
func FromStrictEquals[T comparable]() Eq[T] {
|
func FromStrictEquals[T comparable]() Eq[T] {
|
||||||
return FromEquals(strictEq[T])
|
return FromEquals(strictEq[T])
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromEquals constructs an [EQ.Eq] from the comparison function
|
// FromEquals constructs an `Eq` from the comparison function
|
||||||
func FromEquals[T any](c func(x, y T) bool) Eq[T] {
|
func FromEquals[T any](c func(x, y T) bool) Eq[T] {
|
||||||
return eq[T]{c: c}
|
return eq[T]{c: c}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,7 @@
|
|||||||
|
|
||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import "path/filepath"
|
||||||
"io"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Join appends a filename to a root path
|
// Join appends a filename to a root path
|
||||||
func Join(name string) func(root string) string {
|
func Join(name string) func(root string) string {
|
||||||
@@ -26,13 +23,3 @@ func Join(name string) func(root string) string {
|
|||||||
return filepath.Join(root, name)
|
return filepath.Join(root, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToReader converts a [io.Reader]
|
|
||||||
func ToReader[R io.Reader](r R) io.Reader {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToCloser converts a [io.Closer]
|
|
||||||
func ToCloser[C io.Closer](c C) io.Closer {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// This file was generated by robots at
|
// This file was generated by robots at
|
||||||
// 2023-12-18 09:38:59.1616876 +0100 CET m=+0.008641801
|
// 2023-10-23 08:30:44.6474482 +0200 CEST m=+0.150851901
|
||||||
|
|
||||||
package function
|
package function
|
||||||
|
|
||||||
|
|||||||
@@ -28,14 +28,3 @@ func Memoize[K comparable, T any](f func(K) T) func(K) T {
|
|||||||
func ContramapMemoize[A any, K comparable, T any](kf func(A) K) func(func(A) T) func(A) T {
|
func ContramapMemoize[A any, K comparable, T any](kf func(A) K) func(func(A) T) func(A) T {
|
||||||
return G.ContramapMemoize[func(A) T](kf)
|
return G.ContramapMemoize[func(A) T](kf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CacheCallback converts a unary function into a unary function that caches the value depending on the parameter
|
|
||||||
func CacheCallback[
|
|
||||||
A any, K comparable, T any](kf func(A) K, getOrCreate func(K, func() func() T) func() T) func(func(A) T) func(A) T {
|
|
||||||
return G.CacheCallback[func(func(A) T) func(A) T](kf, getOrCreate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SingleElementCache creates a cache function for use with the [CacheCallback] method that has a maximum capacity of one single item
|
|
||||||
func SingleElementCache[K comparable, T any]() func(K, func() func() T) func() T {
|
|
||||||
return G.SingleElementCache[func() func() T, K]()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
package function
|
package function
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -50,21 +48,3 @@ func TestCache(t *testing.T) {
|
|||||||
assert.Equal(t, 10, cached(10))
|
assert.Equal(t, 10, cached(10))
|
||||||
assert.Equal(t, 2, count)
|
assert.Equal(t, 2, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSingleElementCache(t *testing.T) {
|
|
||||||
f := func(key string) string {
|
|
||||||
return fmt.Sprintf("%s: %d", key, rand.Int())
|
|
||||||
}
|
|
||||||
cb := CacheCallback(func(s string) string { return s }, SingleElementCache[string, string]())
|
|
||||||
cf := cb(f)
|
|
||||||
|
|
||||||
v1 := cf("1")
|
|
||||||
v2 := cf("1")
|
|
||||||
v3 := cf("2")
|
|
||||||
v4 := cf("1")
|
|
||||||
|
|
||||||
assert.Equal(t, v1, v2)
|
|
||||||
assert.NotEqual(t, v2, v3)
|
|
||||||
assert.NotEqual(t, v3, v4)
|
|
||||||
assert.NotEqual(t, v1, v4)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Code generated by go generate; DO NOT EDIT.
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
// This file was generated by robots at
|
// This file was generated by robots at
|
||||||
// 2023-12-18 09:38:51.4946446 +0100 CET m=+0.008838401
|
// 2023-10-23 08:30:41.7972101 +0200 CEST m=+0.008029101
|
||||||
|
|
||||||
package function
|
package function
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ func Nullary1[F1 ~func() T1, T1 any](f1 F1) func() T1 {
|
|||||||
|
|
||||||
// Curry1 takes a function with 1 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry1 takes a function with 1 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry1]
|
// The inverse function is [Uncurry1]
|
||||||
func Curry1[FCT ~func(T0) T1, T0, T1 any](f FCT) func(T0) T1 {
|
func Curry1[T0, T1 any](f func(T0) T1) func(T0) T1 {
|
||||||
return func(t0 T0) T1 {
|
return func(t0 T0) T1 {
|
||||||
return f(t0)
|
return f(t0)
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ func Curry1[FCT ~func(T0) T1, T0, T1 any](f FCT) func(T0) T1 {
|
|||||||
|
|
||||||
// Uncurry1 takes a cascade of 1 functions each taking only one parameter and returns a function with 1 parameters .
|
// Uncurry1 takes a cascade of 1 functions each taking only one parameter and returns a function with 1 parameters .
|
||||||
// The inverse function is [Curry1]
|
// The inverse function is [Curry1]
|
||||||
func Uncurry1[FCT ~func(T0) T1, T0, T1 any](f FCT) func(T0) T1 {
|
func Uncurry1[T0, T1 any](f func(T0) T1) func(T0) T1 {
|
||||||
return func(t0 T0) T1 {
|
return func(t0 T0) T1 {
|
||||||
return f(t0)
|
return f(t0)
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ func Nullary2[F1 ~func() T1, F2 ~func(T1) T2, T1, T2 any](f1 F1, f2 F2) func() T
|
|||||||
|
|
||||||
// Curry2 takes a function with 2 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry2 takes a function with 2 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry2]
|
// The inverse function is [Uncurry2]
|
||||||
func Curry2[FCT ~func(T0, T1) T2, T0, T1, T2 any](f FCT) func(T0) func(T1) T2 {
|
func Curry2[T0, T1, T2 any](f func(T0, T1) T2) func(T0) func(T1) T2 {
|
||||||
return func(t0 T0) func(t1 T1) T2 {
|
return func(t0 T0) func(t1 T1) T2 {
|
||||||
return func(t1 T1) T2 {
|
return func(t1 T1) T2 {
|
||||||
return f(t0, t1)
|
return f(t0, t1)
|
||||||
@@ -125,7 +125,7 @@ func Curry2[FCT ~func(T0, T1) T2, T0, T1, T2 any](f FCT) func(T0) func(T1) T2 {
|
|||||||
|
|
||||||
// Uncurry2 takes a cascade of 2 functions each taking only one parameter and returns a function with 2 parameters .
|
// Uncurry2 takes a cascade of 2 functions each taking only one parameter and returns a function with 2 parameters .
|
||||||
// The inverse function is [Curry2]
|
// The inverse function is [Curry2]
|
||||||
func Uncurry2[FCT ~func(T0) func(T1) T2, T0, T1, T2 any](f FCT) func(T0, T1) T2 {
|
func Uncurry2[T0, T1, T2 any](f func(T0) func(T1) T2) func(T0, T1) T2 {
|
||||||
return func(t0 T0, t1 T1) T2 {
|
return func(t0 T0, t1 T1) T2 {
|
||||||
return f(t0)(t1)
|
return f(t0)(t1)
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ func Nullary3[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, T1, T2, T3 any](f
|
|||||||
|
|
||||||
// Curry3 takes a function with 3 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry3 takes a function with 3 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry3]
|
// The inverse function is [Uncurry3]
|
||||||
func Curry3[FCT ~func(T0, T1, T2) T3, T0, T1, T2, T3 any](f FCT) func(T0) func(T1) func(T2) T3 {
|
func Curry3[T0, T1, T2, T3 any](f func(T0, T1, T2) T3) func(T0) func(T1) func(T2) T3 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) T3 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) T3 {
|
||||||
return func(t1 T1) func(t2 T2) T3 {
|
return func(t1 T1) func(t2 T2) T3 {
|
||||||
return func(t2 T2) T3 {
|
return func(t2 T2) T3 {
|
||||||
@@ -190,7 +190,7 @@ func Curry3[FCT ~func(T0, T1, T2) T3, T0, T1, T2, T3 any](f FCT) func(T0) func(T
|
|||||||
|
|
||||||
// Uncurry3 takes a cascade of 3 functions each taking only one parameter and returns a function with 3 parameters .
|
// Uncurry3 takes a cascade of 3 functions each taking only one parameter and returns a function with 3 parameters .
|
||||||
// The inverse function is [Curry3]
|
// The inverse function is [Curry3]
|
||||||
func Uncurry3[FCT ~func(T0) func(T1) func(T2) T3, T0, T1, T2, T3 any](f FCT) func(T0, T1, T2) T3 {
|
func Uncurry3[T0, T1, T2, T3 any](f func(T0) func(T1) func(T2) T3) func(T0, T1, T2) T3 {
|
||||||
return func(t0 T0, t1 T1, t2 T2) T3 {
|
return func(t0 T0, t1 T1, t2 T2) T3 {
|
||||||
return f(t0)(t1)(t2)
|
return f(t0)(t1)(t2)
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ func Nullary4[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry4 takes a function with 4 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry4 takes a function with 4 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry4]
|
// The inverse function is [Uncurry4]
|
||||||
func Curry4[FCT ~func(T0, T1, T2, T3) T4, T0, T1, T2, T3, T4 any](f FCT) func(T0) func(T1) func(T2) func(T3) T4 {
|
func Curry4[T0, T1, T2, T3, T4 any](f func(T0, T1, T2, T3) T4) func(T0) func(T1) func(T2) func(T3) T4 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) T4 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) T4 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) T4 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) T4 {
|
||||||
return func(t2 T2) func(t3 T3) T4 {
|
return func(t2 T2) func(t3 T3) T4 {
|
||||||
@@ -258,7 +258,7 @@ func Curry4[FCT ~func(T0, T1, T2, T3) T4, T0, T1, T2, T3, T4 any](f FCT) func(T0
|
|||||||
|
|
||||||
// Uncurry4 takes a cascade of 4 functions each taking only one parameter and returns a function with 4 parameters .
|
// Uncurry4 takes a cascade of 4 functions each taking only one parameter and returns a function with 4 parameters .
|
||||||
// The inverse function is [Curry4]
|
// The inverse function is [Curry4]
|
||||||
func Uncurry4[FCT ~func(T0) func(T1) func(T2) func(T3) T4, T0, T1, T2, T3, T4 any](f FCT) func(T0, T1, T2, T3) T4 {
|
func Uncurry4[T0, T1, T2, T3, T4 any](f func(T0) func(T1) func(T2) func(T3) T4) func(T0, T1, T2, T3) T4 {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) T4 {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3) T4 {
|
||||||
return f(t0)(t1)(t2)(t3)
|
return f(t0)(t1)(t2)(t3)
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,7 @@ func Nullary5[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry5 takes a function with 5 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry5 takes a function with 5 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry5]
|
// The inverse function is [Uncurry5]
|
||||||
func Curry5[FCT ~func(T0, T1, T2, T3, T4) T5, T0, T1, T2, T3, T4, T5 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) T5 {
|
func Curry5[T0, T1, T2, T3, T4, T5 any](f func(T0, T1, T2, T3, T4) T5) func(T0) func(T1) func(T2) func(T3) func(T4) T5 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) T5 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) T5 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) T5 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) T5 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) T5 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) T5 {
|
||||||
@@ -329,7 +329,7 @@ func Curry5[FCT ~func(T0, T1, T2, T3, T4) T5, T0, T1, T2, T3, T4, T5 any](f FCT)
|
|||||||
|
|
||||||
// Uncurry5 takes a cascade of 5 functions each taking only one parameter and returns a function with 5 parameters .
|
// Uncurry5 takes a cascade of 5 functions each taking only one parameter and returns a function with 5 parameters .
|
||||||
// The inverse function is [Curry5]
|
// The inverse function is [Curry5]
|
||||||
func Uncurry5[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) T5, T0, T1, T2, T3, T4, T5 any](f FCT) func(T0, T1, T2, T3, T4) T5 {
|
func Uncurry5[T0, T1, T2, T3, T4, T5 any](f func(T0) func(T1) func(T2) func(T3) func(T4) T5) func(T0, T1, T2, T3, T4) T5 {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) T5 {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) T5 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)
|
return f(t0)(t1)(t2)(t3)(t4)
|
||||||
}
|
}
|
||||||
@@ -385,7 +385,7 @@ func Nullary6[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry6 takes a function with 6 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry6 takes a function with 6 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry6]
|
// The inverse function is [Uncurry6]
|
||||||
func Curry6[FCT ~func(T0, T1, T2, T3, T4, T5) T6, T0, T1, T2, T3, T4, T5, T6 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) T6 {
|
func Curry6[T0, T1, T2, T3, T4, T5, T6 any](f func(T0, T1, T2, T3, T4, T5) T6) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) T6 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) T6 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) T6 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) T6 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) T6 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) T6 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) T6 {
|
||||||
@@ -403,7 +403,7 @@ func Curry6[FCT ~func(T0, T1, T2, T3, T4, T5) T6, T0, T1, T2, T3, T4, T5, T6 any
|
|||||||
|
|
||||||
// Uncurry6 takes a cascade of 6 functions each taking only one parameter and returns a function with 6 parameters .
|
// Uncurry6 takes a cascade of 6 functions each taking only one parameter and returns a function with 6 parameters .
|
||||||
// The inverse function is [Curry6]
|
// The inverse function is [Curry6]
|
||||||
func Uncurry6[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) T6, T0, T1, T2, T3, T4, T5, T6 any](f FCT) func(T0, T1, T2, T3, T4, T5) T6 {
|
func Uncurry6[T0, T1, T2, T3, T4, T5, T6 any](f func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) T6) func(T0, T1, T2, T3, T4, T5) T6 {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) T6 {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) T6 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)
|
||||||
}
|
}
|
||||||
@@ -460,7 +460,7 @@ func Nullary7[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry7 takes a function with 7 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry7 takes a function with 7 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry7]
|
// The inverse function is [Uncurry7]
|
||||||
func Curry7[FCT ~func(T0, T1, T2, T3, T4, T5, T6) T7, T0, T1, T2, T3, T4, T5, T6, T7 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) T7 {
|
func Curry7[T0, T1, T2, T3, T4, T5, T6, T7 any](f func(T0, T1, T2, T3, T4, T5, T6) T7) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) T7 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) T7 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) T7 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) T7 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) T7 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) T7 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) T7 {
|
||||||
@@ -480,7 +480,7 @@ func Curry7[FCT ~func(T0, T1, T2, T3, T4, T5, T6) T7, T0, T1, T2, T3, T4, T5, T6
|
|||||||
|
|
||||||
// Uncurry7 takes a cascade of 7 functions each taking only one parameter and returns a function with 7 parameters .
|
// Uncurry7 takes a cascade of 7 functions each taking only one parameter and returns a function with 7 parameters .
|
||||||
// The inverse function is [Curry7]
|
// The inverse function is [Curry7]
|
||||||
func Uncurry7[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) T7, T0, T1, T2, T3, T4, T5, T6, T7 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6) T7 {
|
func Uncurry7[T0, T1, T2, T3, T4, T5, T6, T7 any](f func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) T7) func(T0, T1, T2, T3, T4, T5, T6) T7 {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) T7 {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) T7 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)
|
||||||
}
|
}
|
||||||
@@ -538,7 +538,7 @@ func Nullary8[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry8 takes a function with 8 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry8 takes a function with 8 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry8]
|
// The inverse function is [Uncurry8]
|
||||||
func Curry8[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7) T8, T0, T1, T2, T3, T4, T5, T6, T7, T8 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T8 {
|
func Curry8[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](f func(T0, T1, T2, T3, T4, T5, T6, T7) T8) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T8 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) T8 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) T8 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) T8 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) T8 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) T8 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) T8 {
|
||||||
@@ -560,7 +560,7 @@ func Curry8[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7) T8, T0, T1, T2, T3, T4, T5
|
|||||||
|
|
||||||
// Uncurry8 takes a cascade of 8 functions each taking only one parameter and returns a function with 8 parameters .
|
// Uncurry8 takes a cascade of 8 functions each taking only one parameter and returns a function with 8 parameters .
|
||||||
// The inverse function is [Curry8]
|
// The inverse function is [Curry8]
|
||||||
func Uncurry8[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T8, T0, T1, T2, T3, T4, T5, T6, T7, T8 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7) T8 {
|
func Uncurry8[T0, T1, T2, T3, T4, T5, T6, T7, T8 any](f func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) T8) func(T0, T1, T2, T3, T4, T5, T6, T7) T8 {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) T8 {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) T8 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)
|
||||||
}
|
}
|
||||||
@@ -619,7 +619,7 @@ func Nullary9[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry9 takes a function with 9 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry9 takes a function with 9 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry9]
|
// The inverse function is [Uncurry9]
|
||||||
func Curry9[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) T9, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T9 {
|
func Curry9[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8) T9) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T9 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) T9 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) T9 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) T9 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) T9 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) T9 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) T9 {
|
||||||
@@ -643,7 +643,7 @@ func Curry9[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) T9, T0, T1, T2, T3, T4
|
|||||||
|
|
||||||
// Uncurry9 takes a cascade of 9 functions each taking only one parameter and returns a function with 9 parameters .
|
// Uncurry9 takes a cascade of 9 functions each taking only one parameter and returns a function with 9 parameters .
|
||||||
// The inverse function is [Curry9]
|
// The inverse function is [Curry9]
|
||||||
func Uncurry9[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T9, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) T9 {
|
func Uncurry9[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 any](f func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) T9) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) T9 {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) T9 {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) T9 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)
|
||||||
}
|
}
|
||||||
@@ -703,7 +703,7 @@ func Nullary10[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry10 takes a function with 10 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry10 takes a function with 10 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry10]
|
// The inverse function is [Uncurry10]
|
||||||
func Curry10[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) T10, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T10 {
|
func Curry10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) T10) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T10 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) T10 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) T10 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) T10 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) T10 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) T10 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) T10 {
|
||||||
@@ -729,7 +729,7 @@ func Curry10[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) T10, T0, T1, T2,
|
|||||||
|
|
||||||
// Uncurry10 takes a cascade of 10 functions each taking only one parameter and returns a function with 10 parameters .
|
// Uncurry10 takes a cascade of 10 functions each taking only one parameter and returns a function with 10 parameters .
|
||||||
// The inverse function is [Curry10]
|
// The inverse function is [Curry10]
|
||||||
func Uncurry10[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T10, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) T10 {
|
func Uncurry10[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](f func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) T10) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) T10 {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) T10 {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) T10 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)
|
||||||
}
|
}
|
||||||
@@ -790,7 +790,7 @@ func Nullary11[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry11 takes a function with 11 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry11 takes a function with 11 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry11]
|
// The inverse function is [Uncurry11]
|
||||||
func Curry11[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) T11, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T11 {
|
func Curry11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) T11) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T11 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) T11 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) T11 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) T11 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) T11 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) T11 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) T11 {
|
||||||
@@ -818,7 +818,7 @@ func Curry11[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) T11, T0, T1,
|
|||||||
|
|
||||||
// Uncurry11 takes a cascade of 11 functions each taking only one parameter and returns a function with 11 parameters .
|
// Uncurry11 takes a cascade of 11 functions each taking only one parameter and returns a function with 11 parameters .
|
||||||
// The inverse function is [Curry11]
|
// The inverse function is [Curry11]
|
||||||
func Uncurry11[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T11, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) T11 {
|
func Uncurry11[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 any](f func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) T11) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) T11 {
|
||||||
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 {
|
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 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)
|
||||||
}
|
}
|
||||||
@@ -880,7 +880,7 @@ func Nullary12[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry12 takes a function with 12 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry12 takes a function with 12 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry12]
|
// The inverse function is [Uncurry12]
|
||||||
func Curry12[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) T12, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T12 {
|
func Curry12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) T12) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T12 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) T12 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) T12 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) T12 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) T12 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) T12 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) T12 {
|
||||||
@@ -910,7 +910,7 @@ func Curry12[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) T12, T0
|
|||||||
|
|
||||||
// Uncurry12 takes a cascade of 12 functions each taking only one parameter and returns a function with 12 parameters .
|
// Uncurry12 takes a cascade of 12 functions each taking only one parameter and returns a function with 12 parameters .
|
||||||
// The inverse function is [Curry12]
|
// The inverse function is [Curry12]
|
||||||
func Uncurry12[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T12, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) T12 {
|
func Uncurry12[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 any](f func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) T12) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) T12 {
|
||||||
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 {
|
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 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)
|
||||||
}
|
}
|
||||||
@@ -973,7 +973,7 @@ func Nullary13[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry13 takes a function with 13 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry13 takes a function with 13 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry13]
|
// The inverse function is [Uncurry13]
|
||||||
func Curry13[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) T13, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](f FCT) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T13 {
|
func Curry13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) T13) func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T13 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) T13 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) T13 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) T13 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) T13 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) T13 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) T13 {
|
||||||
@@ -1005,7 +1005,7 @@ func Curry13[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) T1
|
|||||||
|
|
||||||
// Uncurry13 takes a cascade of 13 functions each taking only one parameter and returns a function with 13 parameters .
|
// Uncurry13 takes a cascade of 13 functions each taking only one parameter and returns a function with 13 parameters .
|
||||||
// The inverse function is [Curry13]
|
// The inverse function is [Curry13]
|
||||||
func Uncurry13[FCT ~func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T13, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) T13 {
|
func Uncurry13[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 any](f func(T0) func(T1) func(T2) func(T3) func(T4) func(T5) func(T6) func(T7) func(T8) func(T9) func(T10) func(T11) func(T12) T13) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) T13 {
|
||||||
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 {
|
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 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)
|
||||||
}
|
}
|
||||||
@@ -1069,7 +1069,7 @@ func Nullary14[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry14 takes a function with 14 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry14 takes a function with 14 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry14]
|
// The inverse function is [Uncurry14]
|
||||||
func Curry14[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) T14, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](f FCT) func(T0) func(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) T14 {
|
func Curry14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) T14) func(T0) func(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) T14 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) T14 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) T14 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) T14 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) T14 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) T14 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) T14 {
|
||||||
@@ -1103,7 +1103,7 @@ func Curry14[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T1
|
|||||||
|
|
||||||
// Uncurry14 takes a cascade of 14 functions each taking only one parameter and returns a function with 14 parameters .
|
// Uncurry14 takes a cascade of 14 functions each taking only one parameter and returns a function with 14 parameters .
|
||||||
// The inverse function is [Curry14]
|
// The inverse function is [Curry14]
|
||||||
func Uncurry14[FCT ~func(T0) func(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) T14, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) T14 {
|
func Uncurry14[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 any](f func(T0) func(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) T14) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) T14 {
|
||||||
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 {
|
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 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)
|
||||||
}
|
}
|
||||||
@@ -1168,7 +1168,7 @@ func Nullary15[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry15 takes a function with 15 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry15 takes a function with 15 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry15]
|
// The inverse function is [Uncurry15]
|
||||||
func Curry15[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) T15, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](f FCT) func(T0) func(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) T15 {
|
func Curry15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) T15) func(T0) func(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) T15 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) T15 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) T15 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) T15 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) T15 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) T15 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) T15 {
|
||||||
@@ -1204,7 +1204,7 @@ func Curry15[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T1
|
|||||||
|
|
||||||
// Uncurry15 takes a cascade of 15 functions each taking only one parameter and returns a function with 15 parameters .
|
// Uncurry15 takes a cascade of 15 functions each taking only one parameter and returns a function with 15 parameters .
|
||||||
// The inverse function is [Curry15]
|
// The inverse function is [Curry15]
|
||||||
func Uncurry15[FCT ~func(T0) func(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) T15, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) T15 {
|
func Uncurry15[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 any](f func(T0) func(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) T15) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) T15 {
|
||||||
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) T15 {
|
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) T15 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)
|
||||||
}
|
}
|
||||||
@@ -1270,7 +1270,7 @@ func Nullary16[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry16 takes a function with 16 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry16 takes a function with 16 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry16]
|
// The inverse function is [Uncurry16]
|
||||||
func Curry16[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) T16, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16 any](f FCT) func(T0) func(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) T16 {
|
func Curry16[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) T16) func(T0) func(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) T16 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) T16 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) T16 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) T16 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) T16 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) T16 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) T16 {
|
||||||
@@ -1308,7 +1308,7 @@ func Curry16[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T1
|
|||||||
|
|
||||||
// Uncurry16 takes a cascade of 16 functions each taking only one parameter and returns a function with 16 parameters .
|
// Uncurry16 takes a cascade of 16 functions each taking only one parameter and returns a function with 16 parameters .
|
||||||
// The inverse function is [Curry16]
|
// The inverse function is [Curry16]
|
||||||
func Uncurry16[FCT ~func(T0) func(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) T16, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) T16 {
|
func Uncurry16[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16 any](f func(T0) func(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) T16) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) T16 {
|
||||||
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, t15 T15) T16 {
|
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, t15 T15) T16 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)
|
||||||
}
|
}
|
||||||
@@ -1375,7 +1375,7 @@ func Nullary17[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry17 takes a function with 17 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry17 takes a function with 17 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry17]
|
// The inverse function is [Uncurry17]
|
||||||
func Curry17[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) T17, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17 any](f FCT) func(T0) func(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) func(T16) T17 {
|
func Curry17[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) T17) func(T0) func(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) func(T16) T17 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) T17 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) T17 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) T17 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) T17 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) T17 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) T17 {
|
||||||
@@ -1415,7 +1415,7 @@ func Curry17[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T1
|
|||||||
|
|
||||||
// Uncurry17 takes a cascade of 17 functions each taking only one parameter and returns a function with 17 parameters .
|
// Uncurry17 takes a cascade of 17 functions each taking only one parameter and returns a function with 17 parameters .
|
||||||
// The inverse function is [Curry17]
|
// The inverse function is [Curry17]
|
||||||
func Uncurry17[FCT ~func(T0) func(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) func(T16) T17, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) T17 {
|
func Uncurry17[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17 any](f func(T0) func(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) func(T16) T17) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) T17 {
|
||||||
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, t15 T15, t16 T16) T17 {
|
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, t15 T15, t16 T16) T17 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)(t16)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)(t16)
|
||||||
}
|
}
|
||||||
@@ -1483,7 +1483,7 @@ func Nullary18[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry18 takes a function with 18 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry18 takes a function with 18 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry18]
|
// The inverse function is [Uncurry18]
|
||||||
func Curry18[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) T18, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18 any](f FCT) func(T0) func(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) func(T16) func(T17) T18 {
|
func Curry18[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) T18) func(T0) func(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) func(T16) func(T17) T18 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) T18 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) T18 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) T18 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) T18 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) T18 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) T18 {
|
||||||
@@ -1525,7 +1525,7 @@ func Curry18[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T1
|
|||||||
|
|
||||||
// Uncurry18 takes a cascade of 18 functions each taking only one parameter and returns a function with 18 parameters .
|
// Uncurry18 takes a cascade of 18 functions each taking only one parameter and returns a function with 18 parameters .
|
||||||
// The inverse function is [Curry18]
|
// The inverse function is [Curry18]
|
||||||
func Uncurry18[FCT ~func(T0) func(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) func(T16) func(T17) T18, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) T18 {
|
func Uncurry18[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18 any](f func(T0) func(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) func(T16) func(T17) T18) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17) T18 {
|
||||||
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, t15 T15, t16 T16, t17 T17) T18 {
|
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, t15 T15, t16 T16, t17 T17) T18 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)(t16)(t17)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)(t16)(t17)
|
||||||
}
|
}
|
||||||
@@ -1594,7 +1594,7 @@ func Nullary19[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry19 takes a function with 19 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry19 takes a function with 19 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry19]
|
// The inverse function is [Uncurry19]
|
||||||
func Curry19[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) T19, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19 any](f FCT) func(T0) func(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) func(T16) func(T17) func(T18) T19 {
|
func Curry19[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) T19) func(T0) func(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) func(T16) func(T17) func(T18) T19 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) T19 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) T19 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) T19 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) T19 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) T19 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) T19 {
|
||||||
@@ -1638,7 +1638,7 @@ func Curry19[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T1
|
|||||||
|
|
||||||
// Uncurry19 takes a cascade of 19 functions each taking only one parameter and returns a function with 19 parameters .
|
// Uncurry19 takes a cascade of 19 functions each taking only one parameter and returns a function with 19 parameters .
|
||||||
// The inverse function is [Curry19]
|
// The inverse function is [Curry19]
|
||||||
func Uncurry19[FCT ~func(T0) func(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) func(T16) func(T17) func(T18) T19, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) T19 {
|
func Uncurry19[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19 any](f func(T0) func(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) func(T16) func(T17) func(T18) T19) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18) T19 {
|
||||||
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, t15 T15, t16 T16, t17 T17, t18 T18) T19 {
|
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, t15 T15, t16 T16, t17 T17, t18 T18) T19 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)(t16)(t17)(t18)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)(t16)(t17)(t18)
|
||||||
}
|
}
|
||||||
@@ -1708,7 +1708,7 @@ func Nullary20[F1 ~func() T1, F2 ~func(T1) T2, F3 ~func(T2) T3, F4 ~func(T3) T4,
|
|||||||
|
|
||||||
// Curry20 takes a function with 20 parameters and returns a cascade of functions each taking only one parameter.
|
// Curry20 takes a function with 20 parameters and returns a cascade of functions each taking only one parameter.
|
||||||
// The inverse function is [Uncurry20]
|
// The inverse function is [Uncurry20]
|
||||||
func Curry20[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) T20, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20 any](f FCT) func(T0) func(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) func(T16) func(T17) func(T18) func(T19) T20 {
|
func Curry20[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20 any](f func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) T20) func(T0) func(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) func(T16) func(T17) func(T18) func(T19) T20 {
|
||||||
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) func(t19 T19) T20 {
|
return func(t0 T0) func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) func(t19 T19) T20 {
|
||||||
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) func(t19 T19) T20 {
|
return func(t1 T1) func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) func(t19 T19) T20 {
|
||||||
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) func(t19 T19) T20 {
|
return func(t2 T2) func(t3 T3) func(t4 T4) func(t5 T5) func(t6 T6) func(t7 T7) func(t8 T8) func(t9 T9) func(t10 T10) func(t11 T11) func(t12 T12) func(t13 T13) func(t14 T14) func(t15 T15) func(t16 T16) func(t17 T17) func(t18 T18) func(t19 T19) T20 {
|
||||||
@@ -1754,7 +1754,7 @@ func Curry20[FCT ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T1
|
|||||||
|
|
||||||
// Uncurry20 takes a cascade of 20 functions each taking only one parameter and returns a function with 20 parameters .
|
// Uncurry20 takes a cascade of 20 functions each taking only one parameter and returns a function with 20 parameters .
|
||||||
// The inverse function is [Curry20]
|
// The inverse function is [Curry20]
|
||||||
func Uncurry20[FCT ~func(T0) func(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) func(T16) func(T17) func(T18) func(T19) T20, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20 any](f FCT) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) T20 {
|
func Uncurry20[T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20 any](f func(T0) func(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) func(T16) func(T17) func(T18) func(T19) T20) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19) T20 {
|
||||||
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, t15 T15, t16 T16, t17 T17, t18 T18, t19 T19) T20 {
|
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, t15 T15, t16 T16, t17 T17, t18 T18, t19 T19) T20 {
|
||||||
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)(t16)(t17)(t18)(t19)
|
return f(t0)(t1)(t2)(t3)(t4)(t5)(t6)(t7)(t8)(t9)(t10)(t11)(t12)(t13)(t14)(t15)(t16)(t17)(t18)(t19)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func Memoize[F ~func(K) T, K comparable, T any](f F) F {
|
|||||||
|
|
||||||
// ContramapMemoize converts a unary function into a unary function that caches the value depending on the parameter
|
// ContramapMemoize converts a unary function into a unary function that caches the value depending on the parameter
|
||||||
func ContramapMemoize[F ~func(A) T, KF func(A) K, A any, K comparable, T any](kf KF) func(F) F {
|
func ContramapMemoize[F ~func(A) T, KF func(A) K, A any, K comparable, T any](kf KF) func(F) F {
|
||||||
return CacheCallback[func(F) F, func() func() T](kf, getOrCreate[K, T]())
|
return CacheCallback[F](kf, getOrCreate[K, T]())
|
||||||
}
|
}
|
||||||
|
|
||||||
// getOrCreate is a naive implementation of a cache, without bounds
|
// getOrCreate is a naive implementation of a cache, without bounds
|
||||||
@@ -50,51 +50,13 @@ func getOrCreate[K comparable, T any]() func(K, func() func() T) func() T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SingleElementCache is a cache with a capacity of a single element
|
|
||||||
func SingleElementCache[
|
|
||||||
LLT ~func() LT, // generator of the generator
|
|
||||||
K comparable, // key into the cache
|
|
||||||
LT ~func() T, // generator of a value
|
|
||||||
T any, // the cached data type
|
|
||||||
]() func(K, LLT) LT {
|
|
||||||
var l sync.Mutex
|
|
||||||
|
|
||||||
var key K
|
|
||||||
var value LT
|
|
||||||
hasKey := false
|
|
||||||
|
|
||||||
return func(k K, gen LLT) LT {
|
|
||||||
l.Lock()
|
|
||||||
|
|
||||||
existing := value
|
|
||||||
if !hasKey || key != k {
|
|
||||||
existing = gen()
|
|
||||||
// update state
|
|
||||||
key = k
|
|
||||||
value = existing
|
|
||||||
hasKey = true
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Unlock()
|
|
||||||
|
|
||||||
return existing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CacheCallback converts a unary function into a unary function that caches the value depending on the parameter
|
// CacheCallback converts a unary function into a unary function that caches the value depending on the parameter
|
||||||
func CacheCallback[
|
func CacheCallback[F ~func(A) T, KF func(A) K, C ~func(K, func() func() T) func() T, A any, K comparable, T any](kf KF, getOrCreate C) func(F) F {
|
||||||
EM ~func(F) F, // endomorphism of the function
|
|
||||||
LLT ~func() LT, // generator of the generator
|
|
||||||
LT ~func() T, // generator of a value
|
|
||||||
F ~func(A) T, // function to actually cache
|
|
||||||
KF func(A) K, // extracts the cache key from the input
|
|
||||||
C ~func(K, LLT) LT, // the cache callback function
|
|
||||||
A any, K comparable, T any](kf KF, getOrCreate C) EM {
|
|
||||||
return func(f F) F {
|
return func(f F) F {
|
||||||
return func(a A) T {
|
return func(a A) T {
|
||||||
// cache entry
|
// cache entry
|
||||||
return getOrCreate(kf(a), func() LT {
|
return getOrCreate(kf(a), func() func() T {
|
||||||
return L.Memoize[LT](func() T {
|
return L.Memoize[func() T](func() T {
|
||||||
return f(a)
|
return f(a)
|
||||||
})
|
})
|
||||||
})()
|
})()
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -4,7 +4,7 @@ go 1.20
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
github.com/urfave/cli/v2 v2.27.1
|
github.com/urfave/cli/v2 v2.25.7
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -12,6 +12,6 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.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-20201216005158-039620a65673 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -8,10 +8,10 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
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 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
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.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
|
||||||
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI=
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
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/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -1,311 +0,0 @@
|
|||||||
// 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 builder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
ENDO "github.com/IBM/fp-go/endomorphism"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
C "github.com/IBM/fp-go/http/content"
|
|
||||||
FM "github.com/IBM/fp-go/http/form"
|
|
||||||
H "github.com/IBM/fp-go/http/headers"
|
|
||||||
J "github.com/IBM/fp-go/json"
|
|
||||||
LZ "github.com/IBM/fp-go/lazy"
|
|
||||||
L "github.com/IBM/fp-go/optics/lens"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
S "github.com/IBM/fp-go/string"
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
Builder struct {
|
|
||||||
method O.Option[string]
|
|
||||||
url string
|
|
||||||
headers http.Header
|
|
||||||
body O.Option[E.Either[error, []byte]]
|
|
||||||
query url.Values
|
|
||||||
}
|
|
||||||
|
|
||||||
// Endomorphism returns an [ENDO.Endomorphism] that transforms a builder
|
|
||||||
Endomorphism = ENDO.Endomorphism[*Builder]
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Default is the default builder
|
|
||||||
Default = &Builder{method: O.Some(defaultMethod()), headers: make(http.Header), body: noBody}
|
|
||||||
|
|
||||||
defaultMethod = F.Constant(http.MethodGet)
|
|
||||||
|
|
||||||
// Monoid is the [M.Monoid] for the [Endomorphism]
|
|
||||||
Monoid = ENDO.Monoid[*Builder]()
|
|
||||||
|
|
||||||
// Url is a [L.Lens] for the URL
|
|
||||||
Url = L.MakeLensRef((*Builder).GetUrl, (*Builder).SetUrl)
|
|
||||||
// Method is a [L.Lens] for the HTTP method
|
|
||||||
Method = L.MakeLensRef((*Builder).GetMethod, (*Builder).SetMethod)
|
|
||||||
// Body is a [L.Lens] for the request body
|
|
||||||
Body = L.MakeLensRef((*Builder).GetBody, (*Builder).SetBody)
|
|
||||||
// Headers is a [L.Lens] for the complete set of request headers
|
|
||||||
Headers = L.MakeLensRef((*Builder).GetHeaders, (*Builder).SetHeaders)
|
|
||||||
// Query is a [L.Lens] for the set of query parameters
|
|
||||||
Query = L.MakeLensRef((*Builder).GetQuery, (*Builder).SetQuery)
|
|
||||||
|
|
||||||
rawQuery = L.MakeLensRef(getRawQuery, setRawQuery)
|
|
||||||
|
|
||||||
getHeader = F.Bind2of2((*Builder).GetHeader)
|
|
||||||
delHeader = F.Bind2of2((*Builder).DelHeader)
|
|
||||||
setHeader = F.Bind2of3((*Builder).SetHeader)
|
|
||||||
|
|
||||||
noHeader = O.None[string]()
|
|
||||||
noBody = O.None[E.Either[error, []byte]]()
|
|
||||||
noQueryArg = O.None[string]()
|
|
||||||
|
|
||||||
parseUrl = E.Eitherize1(url.Parse)
|
|
||||||
parseQuery = E.Eitherize1(url.ParseQuery)
|
|
||||||
|
|
||||||
// WithQuery creates a [Endomorphism] for a complete set of query parameters
|
|
||||||
WithQuery = Query.Set
|
|
||||||
// WithMethod creates a [Endomorphism] for a certain method
|
|
||||||
WithMethod = Method.Set
|
|
||||||
// WithUrl creates a [Endomorphism] for a certain method
|
|
||||||
WithUrl = Url.Set
|
|
||||||
// WithHeaders creates a [Endomorphism] for a set of headers
|
|
||||||
WithHeaders = Headers.Set
|
|
||||||
// WithBody creates a [Endomorphism] for a request body
|
|
||||||
WithBody = F.Flow2(
|
|
||||||
O.Of[E.Either[error, []byte]],
|
|
||||||
Body.Set,
|
|
||||||
)
|
|
||||||
// WithBytes creates a [Endomorphism] for a request body using bytes
|
|
||||||
WithBytes = F.Flow2(
|
|
||||||
E.Of[error, []byte],
|
|
||||||
WithBody,
|
|
||||||
)
|
|
||||||
// WithContentType adds the [H.ContentType] header
|
|
||||||
WithContentType = WithHeader(H.ContentType)
|
|
||||||
// WithAuthorization adds the [H.Authorization] header
|
|
||||||
WithAuthorization = WithHeader(H.Authorization)
|
|
||||||
|
|
||||||
// WithGet adds the [http.MethodGet] method
|
|
||||||
WithGet = WithMethod(http.MethodGet)
|
|
||||||
// WithPost adds the [http.MethodPost] method
|
|
||||||
WithPost = WithMethod(http.MethodPost)
|
|
||||||
// WithPut adds the [http.MethodPut] method
|
|
||||||
WithPut = WithMethod(http.MethodPut)
|
|
||||||
// WithDelete adds the [http.MethodDelete] method
|
|
||||||
WithDelete = WithMethod(http.MethodDelete)
|
|
||||||
|
|
||||||
// WithBearer creates a [Endomorphism] to add a Bearer [H.Authorization] header
|
|
||||||
WithBearer = F.Flow2(
|
|
||||||
S.Format[string]("Bearer %s"),
|
|
||||||
WithAuthorization,
|
|
||||||
)
|
|
||||||
|
|
||||||
// WithoutBody creates a [Endomorphism] to remove the body
|
|
||||||
WithoutBody = F.Pipe1(
|
|
||||||
noBody,
|
|
||||||
Body.Set,
|
|
||||||
)
|
|
||||||
|
|
||||||
// WithFormData creates a [Endomorphism] to send form data payload
|
|
||||||
WithFormData = F.Flow4(
|
|
||||||
url.Values.Encode,
|
|
||||||
S.ToBytes,
|
|
||||||
WithBytes,
|
|
||||||
ENDO.Chain(WithContentType(C.FormEncoded)),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
func setRawQuery(u *url.URL, raw string) *url.URL {
|
|
||||||
u.RawQuery = raw
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRawQuery(u *url.URL) string {
|
|
||||||
return u.RawQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) clone() *Builder {
|
|
||||||
cpy := *builder
|
|
||||||
cpy.headers = cpy.headers.Clone()
|
|
||||||
return &cpy
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTargetUrl constructs a full URL with query parameters on top of the provided URL string
|
|
||||||
func (builder *Builder) GetTargetUrl() E.Either[error, string] {
|
|
||||||
// construct the final URL
|
|
||||||
return F.Pipe3(
|
|
||||||
builder,
|
|
||||||
Url.Get,
|
|
||||||
parseUrl,
|
|
||||||
E.Chain(F.Flow4(
|
|
||||||
T.Replicate2[*url.URL],
|
|
||||||
T.Map2(
|
|
||||||
F.Flow2(
|
|
||||||
F.Curry2(setRawQuery),
|
|
||||||
E.Of[error, func(string) *url.URL],
|
|
||||||
),
|
|
||||||
F.Flow3(
|
|
||||||
rawQuery.Get,
|
|
||||||
parseQuery,
|
|
||||||
E.Map[error](F.Flow2(
|
|
||||||
F.Curry2(FM.ValuesMonoid.Concat)(builder.GetQuery()),
|
|
||||||
(url.Values).Encode,
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
T.Tupled2(E.MonadAp[*url.URL, error, string]),
|
|
||||||
E.Map[error]((*url.URL).String),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) GetUrl() string {
|
|
||||||
return builder.url
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) GetMethod() string {
|
|
||||||
return F.Pipe1(
|
|
||||||
builder.method,
|
|
||||||
O.GetOrElse(defaultMethod),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) GetHeaders() http.Header {
|
|
||||||
return builder.headers
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) GetQuery() url.Values {
|
|
||||||
return builder.query
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) SetQuery(query url.Values) *Builder {
|
|
||||||
builder.query = query
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) GetBody() O.Option[E.Either[error, []byte]] {
|
|
||||||
return builder.body
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) SetMethod(method string) *Builder {
|
|
||||||
builder.method = O.Some(method)
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) SetUrl(url string) *Builder {
|
|
||||||
builder.url = url
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) SetHeaders(headers http.Header) *Builder {
|
|
||||||
builder.headers = headers
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) SetBody(body O.Option[E.Either[error, []byte]]) *Builder {
|
|
||||||
builder.body = body
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) SetHeader(name, value string) *Builder {
|
|
||||||
builder.headers.Set(name, value)
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) DelHeader(name string) *Builder {
|
|
||||||
builder.headers.Del(name)
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) GetHeader(name string) O.Option[string] {
|
|
||||||
return F.Pipe2(
|
|
||||||
name,
|
|
||||||
builder.headers.Get,
|
|
||||||
O.FromPredicate(S.IsNonEmpty),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (builder *Builder) GetHeaderValues(name string) []string {
|
|
||||||
return builder.headers.Values(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Header returns a [L.Lens] for a single header
|
|
||||||
func Header(name string) L.Lens[*Builder, O.Option[string]] {
|
|
||||||
get := getHeader(name)
|
|
||||||
set := F.Bind1of2(setHeader(name))
|
|
||||||
del := F.Flow2(
|
|
||||||
LZ.Of[*Builder],
|
|
||||||
LZ.Map(delHeader(name)),
|
|
||||||
)
|
|
||||||
|
|
||||||
return L.MakeLens(get, func(b *Builder, value O.Option[string]) *Builder {
|
|
||||||
cpy := b.clone()
|
|
||||||
return F.Pipe1(
|
|
||||||
value,
|
|
||||||
O.Fold(del(cpy), set(cpy)),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithHeader creates a [Endomorphism] for a certain header
|
|
||||||
func WithHeader(name string) func(value string) Endomorphism {
|
|
||||||
return F.Flow2(
|
|
||||||
O.Of[string],
|
|
||||||
Header(name).Set,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutHeader creates a [Endomorphism] to remove a certain header
|
|
||||||
func WithoutHeader(name string) Endomorphism {
|
|
||||||
return Header(name).Set(noHeader)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithJson creates a [Endomorphism] to send JSON payload
|
|
||||||
func WithJson[T any](data T) Endomorphism {
|
|
||||||
return Monoid.Concat(
|
|
||||||
F.Pipe2(
|
|
||||||
data,
|
|
||||||
J.Marshal[T],
|
|
||||||
WithBody,
|
|
||||||
),
|
|
||||||
WithContentType(C.Json),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryArg is a [L.Lens] for the first value of a query argument
|
|
||||||
func QueryArg(name string) L.Lens[*Builder, O.Option[string]] {
|
|
||||||
return F.Pipe1(
|
|
||||||
Query,
|
|
||||||
L.Compose[*Builder](FM.AtValue(name)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithQueryArg creates a [Endomorphism] for a certain query argument
|
|
||||||
func WithQueryArg(name string) func(value string) Endomorphism {
|
|
||||||
return F.Flow2(
|
|
||||||
O.Of[string],
|
|
||||||
QueryArg(name).Set,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutQueryArg creates a [Endomorphism] that removes a query argument
|
|
||||||
func WithoutQueryArg(name string) Endomorphism {
|
|
||||||
return QueryArg(name).Set(noQueryArg)
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
// 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 builder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
C "github.com/IBM/fp-go/http/content"
|
|
||||||
FD "github.com/IBM/fp-go/http/form"
|
|
||||||
H "github.com/IBM/fp-go/http/headers"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBuilder(t *testing.T) {
|
|
||||||
|
|
||||||
name := H.ContentType
|
|
||||||
withContentType := WithHeader(name)
|
|
||||||
withoutContentType := WithoutHeader(name)
|
|
||||||
|
|
||||||
b1 := F.Pipe1(
|
|
||||||
Default,
|
|
||||||
withContentType(C.Json),
|
|
||||||
)
|
|
||||||
|
|
||||||
b2 := F.Pipe1(
|
|
||||||
b1,
|
|
||||||
withContentType(C.TextPlain),
|
|
||||||
)
|
|
||||||
|
|
||||||
b3 := F.Pipe1(
|
|
||||||
b2,
|
|
||||||
withoutContentType,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, O.None[string](), Default.GetHeader(name))
|
|
||||||
assert.Equal(t, O.Of(C.Json), b1.GetHeader(name))
|
|
||||||
assert.Equal(t, O.Of(C.TextPlain), b2.GetHeader(name))
|
|
||||||
assert.Equal(t, O.None[string](), b3.GetHeader(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithFormData(t *testing.T) {
|
|
||||||
data := F.Pipe1(
|
|
||||||
FD.Default,
|
|
||||||
FD.WithValue("a")("b"),
|
|
||||||
)
|
|
||||||
|
|
||||||
res := F.Pipe1(
|
|
||||||
Default,
|
|
||||||
WithFormData(data),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, C.FormEncoded, Headers.Get(res).Get(H.ContentType))
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
// 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 content
|
|
||||||
|
|
||||||
const (
|
|
||||||
TextPlain = "text/plain"
|
|
||||||
Json = "application/json"
|
|
||||||
FormEncoded = "application/x-www-form-urlencoded"
|
|
||||||
)
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
// 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 form
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/url"
|
|
||||||
|
|
||||||
A "github.com/IBM/fp-go/array"
|
|
||||||
ENDO "github.com/IBM/fp-go/endomorphism"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
L "github.com/IBM/fp-go/optics/lens"
|
|
||||||
LA "github.com/IBM/fp-go/optics/lens/array"
|
|
||||||
LRG "github.com/IBM/fp-go/optics/lens/record/generic"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
RG "github.com/IBM/fp-go/record/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
// Endomorphism returns an [ENDO.Endomorphism] that transforms a form
|
|
||||||
Endomorphism = ENDO.Endomorphism[url.Values]
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Default is the default form field
|
|
||||||
Default = make(url.Values)
|
|
||||||
|
|
||||||
noField = O.None[string]()
|
|
||||||
|
|
||||||
// Monoid is the [M.Monoid] for the [Endomorphism]
|
|
||||||
Monoid = ENDO.Monoid[url.Values]()
|
|
||||||
|
|
||||||
// ValuesMonoid is a [M.Monoid] to concatenate [url.Values] maps
|
|
||||||
ValuesMonoid = RG.UnionMonoid[url.Values](A.Semigroup[string]())
|
|
||||||
|
|
||||||
// AtValues is a [L.Lens] that focusses on the values of a form field
|
|
||||||
AtValues = LRG.AtRecord[url.Values, []string]
|
|
||||||
|
|
||||||
composeHead = F.Pipe1(
|
|
||||||
LA.AtHead[string](),
|
|
||||||
L.ComposeOptions[url.Values, string](A.Empty[string]()),
|
|
||||||
)
|
|
||||||
|
|
||||||
// AtValue is a [L.Lens] that focusses on first value in form fields
|
|
||||||
AtValue = F.Flow2(
|
|
||||||
AtValues,
|
|
||||||
composeHead,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// WithValue creates a [FormBuilder] for a certain field
|
|
||||||
func WithValue(name string) func(value string) Endomorphism {
|
|
||||||
return F.Flow2(
|
|
||||||
O.Of[string],
|
|
||||||
AtValue(name).Set,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithoutValue creates a [FormBuilder] that removes a field
|
|
||||||
func WithoutValue(name string) Endomorphism {
|
|
||||||
return AtValue(name).Set(noField)
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
// 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 form
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
A "github.com/IBM/fp-go/array"
|
|
||||||
"github.com/IBM/fp-go/eq"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
LT "github.com/IBM/fp-go/optics/lens/testing"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
RG "github.com/IBM/fp-go/record/generic"
|
|
||||||
S "github.com/IBM/fp-go/string"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
sEq = eq.FromEquals(S.Eq)
|
|
||||||
valuesEq = RG.Eq[url.Values](A.Eq(sEq))
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLaws(t *testing.T) {
|
|
||||||
name := "Content-Type"
|
|
||||||
fieldLaws := LT.AssertLaws[url.Values, O.Option[string]](t, O.Eq(sEq), valuesEq)(AtValue(name))
|
|
||||||
|
|
||||||
n := O.None[string]()
|
|
||||||
s1 := O.Some("s1")
|
|
||||||
|
|
||||||
v1 := F.Pipe1(
|
|
||||||
Default,
|
|
||||||
WithValue(name)("v1"),
|
|
||||||
)
|
|
||||||
|
|
||||||
v2 := F.Pipe1(
|
|
||||||
Default,
|
|
||||||
WithValue("Other-Header")("v2"),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.True(t, fieldLaws(Default, n))
|
|
||||||
assert.True(t, fieldLaws(v1, n))
|
|
||||||
assert.True(t, fieldLaws(v2, n))
|
|
||||||
|
|
||||||
assert.True(t, fieldLaws(Default, s1))
|
|
||||||
assert.True(t, fieldLaws(v1, s1))
|
|
||||||
assert.True(t, fieldLaws(v2, s1))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFormField(t *testing.T) {
|
|
||||||
|
|
||||||
v1 := F.Pipe1(
|
|
||||||
Default,
|
|
||||||
WithValue("h1")("v1"),
|
|
||||||
)
|
|
||||||
|
|
||||||
v2 := F.Pipe1(
|
|
||||||
v1,
|
|
||||||
WithValue("h2")("v2"),
|
|
||||||
)
|
|
||||||
|
|
||||||
// make sure the code does not change structures
|
|
||||||
assert.False(t, valuesEq.Equals(Default, v1))
|
|
||||||
assert.False(t, valuesEq.Equals(Default, v2))
|
|
||||||
assert.False(t, valuesEq.Equals(v1, v2))
|
|
||||||
|
|
||||||
// check for existence of values
|
|
||||||
assert.Equal(t, "v1", v1.Get("h1"))
|
|
||||||
assert.Equal(t, "v1", v2.Get("h1"))
|
|
||||||
assert.Equal(t, "v2", v2.Get("h2"))
|
|
||||||
|
|
||||||
// check getter on lens
|
|
||||||
|
|
||||||
l1 := AtValue("h1")
|
|
||||||
l2 := AtValue("h2")
|
|
||||||
|
|
||||||
assert.Equal(t, O.Of("v1"), l1.Get(v1))
|
|
||||||
assert.Equal(t, O.Of("v1"), l1.Get(v2))
|
|
||||||
assert.Equal(t, O.Of("v2"), l2.Get(v2))
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// 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 headers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/textproto"
|
|
||||||
|
|
||||||
A "github.com/IBM/fp-go/array"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
L "github.com/IBM/fp-go/optics/lens"
|
|
||||||
LA "github.com/IBM/fp-go/optics/lens/array"
|
|
||||||
LRG "github.com/IBM/fp-go/optics/lens/record/generic"
|
|
||||||
RG "github.com/IBM/fp-go/record/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HTTP headers
|
|
||||||
const (
|
|
||||||
Accept = "Accept"
|
|
||||||
Authorization = "Authorization"
|
|
||||||
ContentType = "Content-Type"
|
|
||||||
ContentLength = "Content-Length"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Monoid is a [M.Monoid] to concatenate [http.Header] maps
|
|
||||||
Monoid = RG.UnionMonoid[http.Header](A.Semigroup[string]())
|
|
||||||
|
|
||||||
// AtValues is a [L.Lens] that focusses on the values of a header
|
|
||||||
AtValues = F.Flow2(
|
|
||||||
textproto.CanonicalMIMEHeaderKey,
|
|
||||||
LRG.AtRecord[http.Header, []string],
|
|
||||||
)
|
|
||||||
|
|
||||||
composeHead = F.Pipe1(
|
|
||||||
LA.AtHead[string](),
|
|
||||||
L.ComposeOptions[http.Header, string](A.Empty[string]()),
|
|
||||||
)
|
|
||||||
|
|
||||||
// AtValue is a [L.Lens] that focusses on first value of a header
|
|
||||||
AtValue = F.Flow2(
|
|
||||||
AtValues,
|
|
||||||
composeHead,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// 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 headers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
A "github.com/IBM/fp-go/array"
|
|
||||||
"github.com/IBM/fp-go/eq"
|
|
||||||
LT "github.com/IBM/fp-go/optics/lens/testing"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
RG "github.com/IBM/fp-go/record/generic"
|
|
||||||
S "github.com/IBM/fp-go/string"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
sEq = eq.FromEquals(S.Eq)
|
|
||||||
valuesEq = RG.Eq[http.Header](A.Eq(sEq))
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLaws(t *testing.T) {
|
|
||||||
name := "Content-Type"
|
|
||||||
fieldLaws := LT.AssertLaws[http.Header, O.Option[string]](t, O.Eq(sEq), valuesEq)(AtValue(name))
|
|
||||||
|
|
||||||
n := O.None[string]()
|
|
||||||
s1 := O.Some("s1")
|
|
||||||
|
|
||||||
def := make(http.Header)
|
|
||||||
|
|
||||||
v1 := make(http.Header)
|
|
||||||
v1.Set(name, "v1")
|
|
||||||
|
|
||||||
v2 := make(http.Header)
|
|
||||||
v2.Set("Other-Header", "v2")
|
|
||||||
|
|
||||||
assert.True(t, fieldLaws(def, n))
|
|
||||||
assert.True(t, fieldLaws(v1, n))
|
|
||||||
assert.True(t, fieldLaws(v2, n))
|
|
||||||
|
|
||||||
assert.True(t, fieldLaws(def, s1))
|
|
||||||
assert.True(t, fieldLaws(v1, s1))
|
|
||||||
assert.True(t, fieldLaws(v2, s1))
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
H "net/http"
|
H "net/http"
|
||||||
"net/url"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
A "github.com/IBM/fp-go/array"
|
A "github.com/IBM/fp-go/array"
|
||||||
@@ -34,13 +33,6 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
ParsedMediaType = T.Tuple2[string, map[string]string]
|
ParsedMediaType = T.Tuple2[string, map[string]string]
|
||||||
|
|
||||||
HttpError struct {
|
|
||||||
statusCode int
|
|
||||||
headers H.Header
|
|
||||||
body []byte
|
|
||||||
url *url.URL
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -80,31 +72,6 @@ func ParseMediaType(mediaType string) E.Either[error, ParsedMediaType] {
|
|||||||
return E.TryCatchError(T.MakeTuple2(m, p), err)
|
return E.TryCatchError(T.MakeTuple2(m, p), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error fulfills the error interface
|
|
||||||
func (r *HttpError) Error() string {
|
|
||||||
return fmt.Sprintf("invalid status code [%d] when accessing URL [%s]", r.statusCode, r.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HttpError) String() string {
|
|
||||||
return r.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HttpError) StatusCode() int {
|
|
||||||
return r.statusCode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HttpError) Headers() H.Header {
|
|
||||||
return r.headers
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HttpError) URL() *url.URL {
|
|
||||||
return r.url
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HttpError) Body() []byte {
|
|
||||||
return r.body
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetHeader(resp *H.Response) H.Header {
|
func GetHeader(resp *H.Response) H.Header {
|
||||||
return resp.Header
|
return resp.Header
|
||||||
}
|
}
|
||||||
@@ -117,13 +84,6 @@ func isValidStatus(resp *H.Response) bool {
|
|||||||
return resp.StatusCode >= H.StatusOK && resp.StatusCode < H.StatusMultipleChoices
|
return resp.StatusCode >= H.StatusOK && resp.StatusCode < H.StatusMultipleChoices
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusCodeError creates an instance of [HttpError] filled with information from the response
|
|
||||||
func StatusCodeError(resp *H.Response) error {
|
func StatusCodeError(resp *H.Response) error {
|
||||||
// read the body
|
return fmt.Errorf("invalid status code [%d] when accessing URL [%s]", resp.StatusCode, resp.Request.URL)
|
||||||
bodyRdr := GetBody(resp)
|
|
||||||
defer bodyRdr.Close()
|
|
||||||
// try to access body content
|
|
||||||
body, _ := io.ReadAll(bodyRdr)
|
|
||||||
// return an error with comprehensive information
|
|
||||||
return &HttpError{statusCode: resp.StatusCode, headers: GetHeader(resp).Clone(), body: body, url: resp.Request.URL}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import (
|
|||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
E "github.com/IBM/fp-go/either"
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
C "github.com/IBM/fp-go/http/content"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ func Error[A any](t *testing.T) func(E.Either[error, A]) bool {
|
|||||||
func TestValidateJsonContentTypeString(t *testing.T) {
|
func TestValidateJsonContentTypeString(t *testing.T) {
|
||||||
|
|
||||||
res := F.Pipe1(
|
res := F.Pipe1(
|
||||||
validateJsonContentTypeString(C.Json),
|
validateJsonContentTypeString("application/json"),
|
||||||
NoError[ParsedMediaType](t),
|
NoError[ParsedMediaType](t),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
// 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 identity
|
|
||||||
|
|
||||||
import (
|
|
||||||
A "github.com/IBM/fp-go/internal/apply"
|
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[S any](
|
|
||||||
empty S,
|
|
||||||
) S {
|
|
||||||
return empty
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(S1) S2 {
|
|
||||||
return C.Bind(
|
|
||||||
Chain[S1, S2],
|
|
||||||
Map[T, S2],
|
|
||||||
setter,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[S1, S2, T any](
|
|
||||||
key func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(S1) S2 {
|
|
||||||
return F.Let(
|
|
||||||
Map[S1, S2],
|
|
||||||
key,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[S1, S2, B any](
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
b B,
|
|
||||||
) func(S1) S2 {
|
|
||||||
return F.LetTo(
|
|
||||||
Map[S1, S2],
|
|
||||||
key,
|
|
||||||
b,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(T) S1 {
|
|
||||||
return C.BindTo(
|
|
||||||
Map[T, S1],
|
|
||||||
setter,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa T,
|
|
||||||
) func(S1) S2 {
|
|
||||||
return A.ApS(
|
|
||||||
Ap[S2, T],
|
|
||||||
Map[S1, func(T) S2],
|
|
||||||
setter,
|
|
||||||
fa,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -37,16 +37,6 @@ func MonadAp[HKTGA, HKTGB, HKTGAB, HKTFGAB, HKTFGGAB, HKTFGA, HKTFGB any](
|
|||||||
return fap(fmap(fab, F.Bind1st(F.Bind1st[HKTGAB, HKTGA, HKTGB], gap)), fa)
|
return fap(fmap(fab, F.Bind1st(F.Bind1st[HKTGAB, HKTGA, HKTGB], gap)), fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
// func Ap[HKTGA, HKTGB, HKTGAB, HKTFGAB, HKTFGGAB, HKTFGA, HKTFGB any](
|
|
||||||
// fap func(HKTFGA) func(HKTFGGAB) HKTFGB,
|
|
||||||
// fmap func(func(HKTGAB) func(HKTGA) HKTGB) func(HKTFGAB) HKTFGGAB,
|
|
||||||
// gap func(HKTGA) func(HKTGAB) HKTGB,
|
|
||||||
|
|
||||||
// fa HKTFGA) func(HKTFGAB) HKTFGB {
|
|
||||||
|
|
||||||
// return fap(fmap(F.Bind1st(F.Bind1st[HKTGAB, HKTGA, HKTGB], gap)), fa)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function ap<F, G>(
|
// export function ap<F, G>(
|
||||||
// F: Apply<F>,
|
// F: Apply<F>,
|
||||||
// G: Apply<G>
|
// G: Apply<G>
|
||||||
@@ -117,25 +107,3 @@ func ApSecond[HKTGA, HKTGB, HKTGBB, A, B any](
|
|||||||
return MonadApSecond(fap, fmap, first, second)
|
return MonadApSecond(fap, fmap, first, second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadApS[S1, S2, B, HKTBGBS2, HKTS1, HKTS2, HKTB any](
|
|
||||||
fap func(HKTBGBS2, HKTB) HKTS2,
|
|
||||||
fmap func(HKTS1, func(S1) func(B) S2) HKTBGBS2,
|
|
||||||
fa HKTS1,
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
fb HKTB,
|
|
||||||
) HKTS2 {
|
|
||||||
return fap(fmap(fa, F.Flip(key)), fb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ApS[S1, S2, B, HKTBGBS2, HKTS1, HKTS2, HKTB any](
|
|
||||||
fap func(HKTB) func(HKTBGBS2) HKTS2,
|
|
||||||
fmap func(func(S1) func(B) S2) func(HKTS1) HKTBGBS2,
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
fb HKTB,
|
|
||||||
) func(HKTS1) HKTS2 {
|
|
||||||
return F.Flow2(
|
|
||||||
fmap(F.Flip(key)),
|
|
||||||
fap(fb),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
// 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 array
|
|
||||||
|
|
||||||
// Prepend prepends a single value to an array
|
|
||||||
func Prepend[ENDO ~func(AS) AS, AS ~[]A, A any](head A) ENDO {
|
|
||||||
return func(as AS) AS {
|
|
||||||
l := len(as)
|
|
||||||
cpy := make(AS, l+1)
|
|
||||||
copy(cpy[1:], as)
|
|
||||||
cpy[0] = head
|
|
||||||
return cpy
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
75
internal/bindt/bind.go
Normal file
75
internal/bindt/bind.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// 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 bindt
|
||||||
|
|
||||||
|
import (
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
I "github.com/IBM/fp-go/identity"
|
||||||
|
T "github.com/IBM/fp-go/tuple"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Bind[SET ~func(B) func(S1) S2, FCT ~func(S1) HKTB, S1, S2, B, HKTS1, HKTS2, HKTB any](
|
||||||
|
mchain func(func(S1) HKTS2) func(HKTS1) HKTS2,
|
||||||
|
mmap func(func(B) S2) func(HKTB) HKTS2,
|
||||||
|
s SET,
|
||||||
|
f FCT,
|
||||||
|
) func(HKTS1) HKTS2 {
|
||||||
|
return mchain(F.Flow3(
|
||||||
|
T.Replicate2[S1],
|
||||||
|
T.Map2(F.Flow2(
|
||||||
|
I.Ap[S2, S1],
|
||||||
|
F.Flow2(
|
||||||
|
F.Bind1st(F.Flow2[SET, func(func(S1) S2) S2], s),
|
||||||
|
mmap,
|
||||||
|
)), f),
|
||||||
|
T.Tupled2(I.MonadAp[HKTS2, HKTB]),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func BindTo[SET ~func(B) S2, S2, B, HKTS2, HKTB any](
|
||||||
|
mmap func(func(B) S2) func(HKTB) HKTS2,
|
||||||
|
s SET,
|
||||||
|
) func(HKTB) HKTS2 {
|
||||||
|
return mmap(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ApS[
|
||||||
|
SET ~func(B) func(S1) S2,
|
||||||
|
S1, S2, B, HKTS1S2, HKTS1, HKTS2, HKTB any,
|
||||||
|
](
|
||||||
|
ap func(HKTS1) func(HKTS1S2) HKTS2,
|
||||||
|
mmap func(func(B) func(S1) S2) func(HKTB) HKTS1S2,
|
||||||
|
s SET, fb HKTB) func(HKTS1) HKTS2 {
|
||||||
|
|
||||||
|
return F.Flow2(
|
||||||
|
ap,
|
||||||
|
I.Ap[HKTS2, HKTS1S2](mmap(s)(fb)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Let[SET ~func(B) func(S1) S2, FCT ~func(S1) B, S1, S2, B, HKTS1, HKTS2 any](
|
||||||
|
mmap func(func(S1) S2) func(HKTS1) HKTS2,
|
||||||
|
s SET,
|
||||||
|
f FCT,
|
||||||
|
) func(HKTS1) HKTS2 {
|
||||||
|
return mmap(F.Flow3(
|
||||||
|
T.Replicate2[S1],
|
||||||
|
T.Map2(F.Flow2(
|
||||||
|
I.Ap[S2, S1],
|
||||||
|
F.Bind1st(F.Flow2[SET, func(func(S1) S2) S2], s)), f),
|
||||||
|
T.Tupled2(I.MonadAp[S2, B]),
|
||||||
|
))
|
||||||
|
}
|
||||||
@@ -52,59 +52,10 @@ func ChainFirst[A, B, HKTA, HKTB any](
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Chain[A, B, HKTA, HKTB any](
|
func Chain[A, B, HKTA, HKTB any](
|
||||||
mchain func(func(A) HKTB) func(HKTA) HKTB,
|
mchain func(HKTA, func(A) HKTB) HKTB,
|
||||||
f func(A) HKTB,
|
f func(A) HKTB,
|
||||||
) func(HKTA) HKTB {
|
) func(HKTA) HKTB {
|
||||||
return mchain(f)
|
return func(first HKTA) HKTB {
|
||||||
}
|
return MonadChain[A, B](mchain, first, f)
|
||||||
|
}
|
||||||
func MonadBind[S1, S2, B, HKTS1, HKTS2, HKTB any](
|
|
||||||
mchain func(HKTS1, func(S1) HKTS2) HKTS2,
|
|
||||||
mmap func(HKTB, func(B) S2) HKTS2,
|
|
||||||
first HKTS1,
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
f func(S1) HKTB,
|
|
||||||
) HKTS2 {
|
|
||||||
return mchain(first, func(s1 S1) HKTS2 {
|
|
||||||
return mmap(f(s1), func(b B) S2 {
|
|
||||||
return key(b)(s1)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Bind[S1, S2, B, HKTS1, HKTS2, HKTB any](
|
|
||||||
mchain func(func(S1) HKTS2) func(HKTS1) HKTS2,
|
|
||||||
mmap func(func(B) S2) func(HKTB) HKTS2,
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
f func(S1) HKTB,
|
|
||||||
) func(HKTS1) HKTS2 {
|
|
||||||
mapb := F.Flow2(
|
|
||||||
F.Flip(key),
|
|
||||||
mmap,
|
|
||||||
)
|
|
||||||
return mchain(func(s1 S1) HKTS2 {
|
|
||||||
return F.Pipe2(
|
|
||||||
s1,
|
|
||||||
f,
|
|
||||||
F.Pipe1(
|
|
||||||
s1,
|
|
||||||
mapb,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func BindTo[S1, B, HKTS1, HKTB any](
|
|
||||||
mmap func(func(B) S1) func(HKTB) HKTS1,
|
|
||||||
key func(B) S1,
|
|
||||||
) func(fa HKTB) HKTS1 {
|
|
||||||
return mmap(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadBindTo[S1, B, HKTS1, HKTB any](
|
|
||||||
mmap func(HKTB, func(B) S1) HKTS1,
|
|
||||||
first HKTB,
|
|
||||||
key func(B) S1,
|
|
||||||
) HKTS1 {
|
|
||||||
return mmap(first, key)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func MonadChainIOK[GR ~func() B, A, B, HKTA, HKTB any](
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ChainIOK[GR ~func() B, A, B, HKTA, HKTB any](
|
func ChainIOK[GR ~func() B, A, B, HKTA, HKTB any](
|
||||||
mchain func(func(A) HKTB) func(HKTA) HKTB,
|
mchain func(HKTA, func(A) HKTB) HKTB,
|
||||||
fromio func(GR) HKTB,
|
fromio func(GR) HKTB,
|
||||||
f func(A) GR) func(HKTA) HKTB {
|
f func(A) GR) func(HKTA) HKTB {
|
||||||
// chain
|
// chain
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func MonadChainIOEitherK[GIOB ~func() ET.Either[E, B], E, A, B, HKTA, HKTB any](
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ChainIOEitherK[GIOB ~func() ET.Either[E, B], E, A, B, HKTA, HKTB any](
|
func ChainIOEitherK[GIOB ~func() ET.Either[E, B], E, A, B, HKTA, HKTB any](
|
||||||
mchain func(func(A) HKTB) func(HKTA) HKTB,
|
mchain func(HKTA, func(A) HKTB) HKTB,
|
||||||
fromio func(GIOB) HKTB,
|
fromio func(GIOB) HKTB,
|
||||||
f func(A) GIOB) func(HKTA) HKTB {
|
f func(A) GIOB) func(HKTA) HKTB {
|
||||||
// chain
|
// chain
|
||||||
|
|||||||
@@ -21,54 +21,6 @@ import (
|
|||||||
|
|
||||||
// HKTFGA = HKT[F, HKT[G, A]]
|
// HKTFGA = HKT[F, HKT[G, A]]
|
||||||
// HKTFGB = HKT[F, HKT[G, B]]
|
// HKTFGB = HKT[F, HKT[G, B]]
|
||||||
func MonadMap[A, B, HKTGA, HKTGB, HKTFGA, HKTFGB any](
|
func MonadMap[A, B, HKTGA, HKTGB, HKTFGA, HKTFGB any](fmap func(HKTFGA, func(HKTGA) HKTGB) HKTFGB, gmap func(HKTGA, func(A) B) HKTGB, fa HKTFGA, f func(A) B) HKTFGB {
|
||||||
fmap func(HKTFGA, func(HKTGA) HKTGB) HKTFGB,
|
|
||||||
gmap func(HKTGA, func(A) B) HKTGB,
|
|
||||||
fa HKTFGA,
|
|
||||||
f func(A) B) HKTFGB {
|
|
||||||
return fmap(fa, F.Bind2nd(gmap, f))
|
return fmap(fa, F.Bind2nd(gmap, f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Map[A, B, HKTGA, HKTGB, HKTFGA, HKTFGB any](
|
|
||||||
fmap func(func(HKTGA) HKTGB) func(HKTFGA) HKTFGB,
|
|
||||||
gmap func(func(A) B) func(HKTGA) HKTGB,
|
|
||||||
f func(A) B) func(HKTFGA) HKTFGB {
|
|
||||||
return F.Pipe2(
|
|
||||||
f,
|
|
||||||
gmap,
|
|
||||||
fmap,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadLet[S1, S2, B, HKTS1, HKTS2 any](
|
|
||||||
mmap func(HKTS1, func(S1) S2) HKTS2,
|
|
||||||
first HKTS1,
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
f func(S1) B,
|
|
||||||
) HKTS2 {
|
|
||||||
return mmap(first, func(s1 S1) S2 {
|
|
||||||
return key(f(s1))(s1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Let[S1, S2, B, HKTS1, HKTS2 any](
|
|
||||||
mmap func(func(S1) S2) func(HKTS1) HKTS2,
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
f func(S1) B,
|
|
||||||
) func(HKTS1) HKTS2 {
|
|
||||||
return mmap(func(s1 S1) S2 {
|
|
||||||
return key(f(s1))(s1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func LetTo[S1, S2, B, HKTS1, HKTS2 any](
|
|
||||||
mmap func(func(S1) S2) func(HKTS1) HKTS2,
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
b B,
|
|
||||||
) func(HKTS1) HKTS2 {
|
|
||||||
return F.Pipe2(
|
|
||||||
b,
|
|
||||||
key,
|
|
||||||
mmap,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -49,21 +49,14 @@ func MonadChain[A, B, HKTFA, HKTFB any](
|
|||||||
return fchain(ma, O.Fold(F.Nullary2(O.None[B], fof), f))
|
return fchain(ma, O.Fold(F.Nullary2(O.None[B], fof), f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Chain[A, B, HKTFA, HKTFB any](
|
|
||||||
fchain func(HKTFA, func(O.Option[A]) HKTFB) HKTFB,
|
|
||||||
fof func(O.Option[B]) HKTFB,
|
|
||||||
f func(A) HKTFB) func(ma HKTFA) HKTFB {
|
|
||||||
// dispatch to the even more generic implementation
|
|
||||||
return func(ma HKTFA) HKTFB {
|
|
||||||
return MonadChain(fchain, fof, ma, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadAp[A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any](
|
func MonadAp[A, B, HKTFAB, HKTFGAB, HKTFA, HKTFB any](
|
||||||
fap func(HKTFGAB, HKTFA) HKTFB,
|
fap func(HKTFGAB, HKTFA) HKTFB,
|
||||||
fmap func(HKTFAB, func(O.Option[func(A) B]) func(O.Option[A]) O.Option[B]) HKTFGAB,
|
fmap func(HKTFAB, func(O.Option[func(A) B]) func(O.Option[A]) O.Option[B]) HKTFGAB,
|
||||||
fab HKTFAB,
|
fab HKTFAB,
|
||||||
fa HKTFA) HKTFB {
|
fa HKTFA) HKTFB {
|
||||||
|
// HKTGA = O.Option[A]
|
||||||
|
// HKTGB = O.Option[B]
|
||||||
|
// HKTGAB = O.Option[func(a A) B]
|
||||||
return apply.MonadAp(fap, fmap, O.MonadAp[B, A], fab, fa)
|
return apply.MonadAp(fap, fmap, O.MonadAp[B, A], fab, fa)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,25 +23,10 @@ import (
|
|||||||
// here we implement the monadic operations using callbacks from
|
// here we implement the monadic operations using callbacks from
|
||||||
// higher kinded types, as good a golang allows use to do this
|
// higher kinded types, as good a golang allows use to do this
|
||||||
|
|
||||||
func MonadMap[GEA ~func(E) HKTA, GEB ~func(E) HKTB, E, A, B, HKTA, HKTB any](
|
func MonadMap[GEA ~func(E) HKTA, GEB ~func(E) HKTB, E, A, B, HKTA, HKTB any](fmap func(HKTA, func(A) B) HKTB, fa GEA, f func(A) B) GEB {
|
||||||
fmap func(HKTA, func(A) B) HKTB,
|
|
||||||
fa GEA,
|
|
||||||
f func(A) B,
|
|
||||||
) GEB {
|
|
||||||
return R.MonadMap[GEA, GEB](fa, F.Bind2nd(fmap, f))
|
return R.MonadMap[GEA, GEB](fa, F.Bind2nd(fmap, f))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Map[GEA ~func(E) HKTA, GEB ~func(E) HKTB, E, A, B, HKTA, HKTB any](
|
|
||||||
fmap func(func(A) B) func(HKTA) HKTB,
|
|
||||||
f func(A) B,
|
|
||||||
) func(GEA) GEB {
|
|
||||||
return F.Pipe2(
|
|
||||||
f,
|
|
||||||
fmap,
|
|
||||||
R.Map[GEA, GEB, E, HKTA, HKTB],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChain[GEA ~func(E) HKTA, GEB ~func(E) HKTB, A, E, HKTA, HKTB any](fchain func(HKTA, func(A) HKTB) HKTB, ma GEA, f func(A) GEB) GEB {
|
func MonadChain[GEA ~func(E) HKTA, GEB ~func(E) HKTB, A, E, HKTA, HKTB any](fchain func(HKTA, func(A) HKTB) HKTB, ma GEA, f func(A) GEB) GEB {
|
||||||
return R.MakeReader(func(r E) HKTB {
|
return R.MakeReader(func(r E) HKTB {
|
||||||
return fchain(ma(r), func(a A) HKTB {
|
return fchain(ma(r), func(a A) HKTB {
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
// 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 utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
Initial struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
WithLastName struct {
|
|
||||||
Initial
|
|
||||||
LastName string
|
|
||||||
}
|
|
||||||
|
|
||||||
WithGivenName struct {
|
|
||||||
WithLastName
|
|
||||||
GivenName string
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Empty = Initial{}
|
|
||||||
|
|
||||||
SetLastName = F.Curry2(func(name string, s1 Initial) WithLastName {
|
|
||||||
return WithLastName{
|
|
||||||
Initial: s1,
|
|
||||||
LastName: name,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
SetGivenName = F.Curry2(func(name string, s1 WithLastName) WithGivenName {
|
|
||||||
return WithGivenName{
|
|
||||||
WithLastName: s1,
|
|
||||||
GivenName: name,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetFullName(s WithGivenName) string {
|
|
||||||
return fmt.Sprintf("%s %s", s.GivenName, s.LastName)
|
|
||||||
}
|
|
||||||
66
io/bind.go
66
io/bind.go
@@ -1,66 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
G "github.com/IBM/fp-go/io/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[S any](
|
|
||||||
empty S,
|
|
||||||
) IO[S] {
|
|
||||||
return G.Do[IO[S], S](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) IO[T],
|
|
||||||
) func(IO[S1]) IO[S2] {
|
|
||||||
return G.Bind[IO[S1], IO[S2], IO[T], S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(IO[S1]) IO[S2] {
|
|
||||||
return G.Let[IO[S1], IO[S2], S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
b T,
|
|
||||||
) func(IO[S1]) IO[S2] {
|
|
||||||
return G.LetTo[IO[S1], IO[S2], S1, S2, T](setter, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(IO[T]) IO[S1] {
|
|
||||||
return G.BindTo[IO[S1], IO[T], S1, T](setter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa IO[T],
|
|
||||||
) func(IO[S1]) IO[S2] {
|
|
||||||
return G.ApS[IO[S1], IO[S2], IO[T], S1, S2, T](setter, fa)
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/IBM/fp-go/internal/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getLastName(s utils.Initial) IO[string] {
|
|
||||||
return Of("Doe")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGivenName(s utils.WithLastName) IO[string] {
|
|
||||||
return Of("John")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
Bind(utils.SetLastName, getLastName),
|
|
||||||
Bind(utils.SetGivenName, getGivenName),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(), "John Doe")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApS(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
ApS(utils.SetLastName, Of("Doe")),
|
|
||||||
ApS(utils.SetGivenName, Of("John")),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(), "John Doe")
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
A "github.com/IBM/fp-go/internal/apply"
|
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[GS ~func() S, S any](
|
|
||||||
empty S,
|
|
||||||
) GS {
|
|
||||||
return Of[GS](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[GS1 ~func() S1, GS2 ~func() S2, GT ~func() T, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) GT,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return C.Bind(
|
|
||||||
Chain[GS1, GS2, S1, S2],
|
|
||||||
Map[GT, GS2, T, S2],
|
|
||||||
setter,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[GS1 ~func() S1, GS2 ~func() S2, S1, S2, T any](
|
|
||||||
key func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return F.Let(
|
|
||||||
Map[GS1, GS2, S1, S2],
|
|
||||||
key,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[GS1 ~func() S1, GS2 ~func() S2, S1, S2, B any](
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
b B,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return F.LetTo(
|
|
||||||
Map[GS1, GS2, S1, S2],
|
|
||||||
key,
|
|
||||||
b,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[GS1 ~func() S1, GT ~func() T, S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(GT) GS1 {
|
|
||||||
return C.BindTo(
|
|
||||||
Map[GT, GS1, T, S1],
|
|
||||||
setter,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[GS1 ~func() S1, GS2 ~func() S2, GT ~func() T, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa GT,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return A.ApS(
|
|
||||||
Ap[GS2, func() func(T) S2, GT, S2, T],
|
|
||||||
Map[GS1, func() func(T) S2, S1, func(T) S2],
|
|
||||||
setter,
|
|
||||||
fa,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
C "github.com/IBM/fp-go/internal/chain"
|
C "github.com/IBM/fp-go/internal/chain"
|
||||||
FC "github.com/IBM/fp-go/internal/functor"
|
FC "github.com/IBM/fp-go/internal/functor"
|
||||||
L "github.com/IBM/fp-go/internal/lazy"
|
L "github.com/IBM/fp-go/internal/lazy"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// type IO[A any] = func() A
|
// type IO[A any] = func() A
|
||||||
@@ -134,29 +133,6 @@ func Delay[GA ~func() A, A any](delay time.Duration) func(GA) GA {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func after(timestamp time.Time) func() {
|
|
||||||
return func() {
|
|
||||||
// check if we need to wait
|
|
||||||
current := time.Now()
|
|
||||||
if current.Before(timestamp) {
|
|
||||||
time.Sleep(timestamp.Sub(current))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// After creates an operation that passes after the given timestamp
|
|
||||||
func After[GA ~func() A, A any](timestamp time.Time) func(GA) GA {
|
|
||||||
aft := after(timestamp)
|
|
||||||
return func(ga GA) GA {
|
|
||||||
return MakeIO[GA](func() A {
|
|
||||||
// wait as long as necessary
|
|
||||||
aft()
|
|
||||||
// execute after wait
|
|
||||||
return ga()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now returns the current timestamp
|
// Now returns the current timestamp
|
||||||
func Now[GA ~func() time.Time]() GA {
|
func Now[GA ~func() time.Time]() GA {
|
||||||
return MakeIO[GA](time.Now)
|
return MakeIO[GA](time.Now)
|
||||||
@@ -176,23 +152,3 @@ func MonadFlap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](fab GFA
|
|||||||
func Flap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](a A) func(GFAB) GB {
|
func Flap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](a A) func(GFAB) GB {
|
||||||
return F.Bind2nd(MonadFlap[FAB, GFAB, GB, A, B], a)
|
return F.Bind2nd(MonadFlap[FAB, GFAB, GB, A, B], a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithTime returns an operation that measures the start and end timestamp of the operation
|
|
||||||
func WithTime[GTA ~func() T.Tuple3[A, time.Time, time.Time], GA ~func() A, A any](a GA) GTA {
|
|
||||||
return MakeIO[GTA](func() T.Tuple3[A, time.Time, time.Time] {
|
|
||||||
t0 := time.Now()
|
|
||||||
res := a()
|
|
||||||
t1 := time.Now()
|
|
||||||
return T.MakeTuple3(res, t0, t1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDuration returns an operation that measures the duration of the operation
|
|
||||||
func WithDuration[GTA ~func() T.Tuple2[A, time.Duration], GA ~func() A, A any](a GA) GTA {
|
|
||||||
return MakeIO[GTA](func() T.Tuple2[A, time.Duration] {
|
|
||||||
t0 := time.Now()
|
|
||||||
res := a()
|
|
||||||
t1 := time.Now()
|
|
||||||
return T.MakeTuple2(res, t1.Sub(t0))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
|
||||||
func WithResource[
|
|
||||||
GA ~func() A,
|
|
||||||
GR ~func() R,
|
|
||||||
GANY ~func() ANY,
|
|
||||||
R, A, ANY any](onCreate GR, onRelease func(R) GANY) func(func(R) GA) GA {
|
|
||||||
// simply map to implementation of bracket
|
|
||||||
return F.Bind13of3(Bracket[GR, GA, GANY, R, A, ANY])(onCreate, F.Ignore2of2[A](onRelease))
|
|
||||||
}
|
|
||||||
23
io/io.go
23
io/io.go
@@ -19,7 +19,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
G "github.com/IBM/fp-go/io/generic"
|
G "github.com/IBM/fp-go/io/generic"
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IO represents a synchronous computation that cannot fail
|
// IO represents a synchronous computation that cannot fail
|
||||||
@@ -144,26 +143,6 @@ func MonadFlap[B, A any](fab IO[func(A) B], a A) IO[B] {
|
|||||||
return G.MonadFlap[func(A) B, IO[func(A) B], IO[B], A, B](fab, a)
|
return G.MonadFlap[func(A) B, IO[func(A) B], IO[B], A, B](fab, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flap[B, A any](a A) func(IO[func(A) B]) IO[B] {
|
func Flap[FAB ~func(A) B, GFAB ~func() FAB, GB ~func() B, A, B any](a A) func(IO[func(A) B]) IO[B] {
|
||||||
return G.Flap[func(A) B, IO[func(A) B], IO[B], A, B](a)
|
return G.Flap[func(A) B, IO[func(A) B], IO[B], A, B](a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay creates an operation that passes in the value after some delay
|
|
||||||
func Delay[A any](delay time.Duration) func(IO[A]) IO[A] {
|
|
||||||
return G.Delay[IO[A]](delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
// After creates an operation that passes after the given timestamp
|
|
||||||
func After[A any](timestamp time.Time) func(IO[A]) IO[A] {
|
|
||||||
return G.After[IO[A]](timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithTime returns an operation that measures the start and end [time.Time] of the operation
|
|
||||||
func WithTime[A any](a IO[A]) IO[T.Tuple3[A, time.Time, time.Time]] {
|
|
||||||
return G.WithTime[IO[T.Tuple3[A, time.Time, time.Time]], IO[A]](a)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDuration returns an operation that measures the [time.Duration]
|
|
||||||
func WithDuration[A any](a IO[A]) IO[T.Tuple2[A, time.Duration]] {
|
|
||||||
return G.WithDuration[IO[T.Tuple2[A, time.Duration]], IO[A]](a)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
G "github.com/IBM/fp-go/io/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
|
||||||
func WithResource[
|
|
||||||
R, A, ANY any](onCreate IO[R], onRelease func(R) IO[ANY]) func(func(R) IO[A]) IO[A] {
|
|
||||||
// just dispatch
|
|
||||||
return G.WithResource[IO[A], IO[R], IO[ANY]](onCreate, onRelease)
|
|
||||||
}
|
|
||||||
@@ -19,48 +19,26 @@ import (
|
|||||||
G "github.com/IBM/fp-go/ioeither/generic"
|
G "github.com/IBM/fp-go/ioeither/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
// Bind applies a function to an input state and merges the result into that state
|
||||||
func Do[E, S any](
|
func Bind[E, A, S1, S2 any](s func(A) func(S1) S2, f func(S1) IOEither[E, A]) func(IOEither[E, S1]) IOEither[E, S2] {
|
||||||
empty S,
|
return G.Bind[IOEither[E, S1], IOEither[E, S2], IOEither[E, A], func(S1) IOEither[E, A]](s, f)
|
||||||
) IOEither[E, S] {
|
|
||||||
return G.Do[IOEither[E, S], E, S](empty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
// BindTo initializes some state based on a value
|
||||||
func Bind[E, S1, S2, T any](
|
func BindTo[
|
||||||
setter func(T) func(S1) S2,
|
E, A, S2 any](s func(A) S2) func(IOEither[E, A]) IOEither[E, S2] {
|
||||||
f func(S1) IOEither[E, T],
|
return G.BindTo[IOEither[E, S2], IOEither[E, A]](s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ApS[
|
||||||
|
E, A, S1, S2 any,
|
||||||
|
](s func(A) func(S1) S2, fa IOEither[E, A]) func(IOEither[E, S1]) IOEither[E, S2] {
|
||||||
|
return G.ApS[IOEither[E, S1], IOEither[E, S2], IOEither[E, A], IOEither[E, func(S1) S2]](s, fa)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Let[E, A, S1, S2 any](
|
||||||
|
s func(A) func(S1) S2,
|
||||||
|
f func(S1) A,
|
||||||
) func(IOEither[E, S1]) IOEither[E, S2] {
|
) func(IOEither[E, S1]) IOEither[E, S2] {
|
||||||
return G.Bind[IOEither[E, S1], IOEither[E, S2], IOEither[E, T], E, S1, S2, T](setter, f)
|
return G.Let[IOEither[E, S1], IOEither[E, S2]](s, f)
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[E, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(IOEither[E, S1]) IOEither[E, S2] {
|
|
||||||
return G.Let[IOEither[E, S1], IOEither[E, S2], E, S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[E, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
b T,
|
|
||||||
) func(IOEither[E, S1]) IOEither[E, S2] {
|
|
||||||
return G.LetTo[IOEither[E, S1], IOEither[E, S2], E, S1, S2, T](setter, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[E, S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(IOEither[E, T]) IOEither[E, S1] {
|
|
||||||
return G.BindTo[IOEither[E, S1], IOEither[E, T], E, S1, T](setter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[E, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa IOEither[E, T],
|
|
||||||
) func(IOEither[E, S1]) IOEither[E, S2] {
|
|
||||||
return G.ApS[IOEither[E, S1], IOEither[E, S2], IOEither[E, T], E, S1, S2, T](setter, fa)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/IBM/fp-go/internal/utils"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getLastName(s utils.Initial) IOEither[error, string] {
|
|
||||||
return Of[error]("Doe")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGivenName(s utils.WithLastName) IOEither[error, string] {
|
|
||||||
return Of[error]("John")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do[error](utils.Empty),
|
|
||||||
Bind(utils.SetLastName, getLastName),
|
|
||||||
Bind(utils.SetGivenName, getGivenName),
|
|
||||||
Map[error](utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(), E.Of[error]("John Doe"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApS(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do[error](utils.Empty),
|
|
||||||
ApS(utils.SetLastName, Of[error]("Doe")),
|
|
||||||
ApS(utils.SetGivenName, Of[error]("John")),
|
|
||||||
Map[error](utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(), E.Of[error]("John Doe"))
|
|
||||||
}
|
|
||||||
@@ -26,7 +26,7 @@ func Eq[E, A any](eq EQ.Eq[ET.Either[E, A]]) EQ.Eq[IOEither[E, A]] {
|
|||||||
return G.Eq[IOEither[E, A]](eq)
|
return G.Eq[IOEither[E, A]](eq)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
// FromStrictEquals constructs an `Eq` from the canonical comparison function
|
||||||
func FromStrictEquals[E, A comparable]() EQ.Eq[IOEither[E, A]] {
|
func FromStrictEquals[E, A comparable]() EQ.Eq[IOEither[E, A]] {
|
||||||
return G.FromStrictEquals[IOEither[E, A]]()
|
return G.FromStrictEquals[IOEither[E, A]]()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
// 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 file
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MkdirAll create a sequence of directories, see [os.MkdirAll]
|
|
||||||
func MkdirAll(path string, perm os.FileMode) IOE.IOEither[error, string] {
|
|
||||||
return IOE.TryCatchError(func() (string, error) {
|
|
||||||
return path, os.MkdirAll(path, perm)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mkdir create a directory, see [os.Mkdir]
|
|
||||||
func Mkdir(path string, perm os.FileMode) IOE.IOEither[error, string] {
|
|
||||||
return IOE.TryCatchError(func() (string, error) {
|
|
||||||
return path, os.Mkdir(path, perm)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -17,74 +17,63 @@ package generic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
ET "github.com/IBM/fp-go/either"
|
ET "github.com/IBM/fp-go/either"
|
||||||
A "github.com/IBM/fp-go/internal/apply"
|
G "github.com/IBM/fp-go/internal/bindt"
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
// Bind applies a function to an input state and merges the result into that state
|
||||||
func Do[GS ~func() ET.Either[E, S], E, S any](
|
func Bind[
|
||||||
empty S,
|
GS1 ~func() ET.Either[E, S1],
|
||||||
) GS {
|
GS2 ~func() ET.Either[E, S2],
|
||||||
return Of[GS, E, S](empty)
|
GA ~func() ET.Either[E, A],
|
||||||
}
|
FCT ~func(S1) GA,
|
||||||
|
E any,
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
SET ~func(A) func(S1) S2,
|
||||||
func Bind[GS1 ~func() ET.Either[E, S1], GS2 ~func() ET.Either[E, S2], GT ~func() ET.Either[E, T], E, S1, S2, T any](
|
A, S1, S2 any](s SET, f FCT) func(GS1) GS2 {
|
||||||
setter func(T) func(S1) S2,
|
return G.Bind(
|
||||||
f func(S1) GT,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return C.Bind(
|
|
||||||
Chain[GS1, GS2, E, S1, S2],
|
Chain[GS1, GS2, E, S1, S2],
|
||||||
Map[GT, GS2, E, T, S2],
|
Map[GA, GS2, E, A, S2],
|
||||||
setter,
|
s,
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
// BindTo initializes some state based on a value
|
||||||
func Let[GS1 ~func() ET.Either[E, S1], GS2 ~func() ET.Either[E, S2], E, S1, S2, T any](
|
func BindTo[
|
||||||
key func(T) func(S1) S2,
|
GS2 ~func() ET.Either[E, S2],
|
||||||
f func(S1) T,
|
GA ~func() ET.Either[E, A],
|
||||||
) func(GS1) GS2 {
|
E any,
|
||||||
return F.Let(
|
SET ~func(A) S2,
|
||||||
Map[GS1, GS2, E, S1, S2],
|
A, S2 any](s SET) func(GA) GS2 {
|
||||||
key,
|
return G.BindTo(
|
||||||
f,
|
Map[GA, GS2, E, A, S2],
|
||||||
|
s,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
func ApS[
|
||||||
func LetTo[GS1 ~func() ET.Either[E, S1], GS2 ~func() ET.Either[E, S2], E, S1, S2, B any](
|
GS1 ~func() ET.Either[E, S1],
|
||||||
key func(B) func(S1) S2,
|
GS2 ~func() ET.Either[E, S2],
|
||||||
b B,
|
GB ~func() ET.Either[E, B],
|
||||||
) func(GS1) GS2 {
|
GS1S2 ~func() ET.Either[E, func(S1) S2],
|
||||||
return F.LetTo(
|
SET ~func(B) func(S1) S2,
|
||||||
Map[GS1, GS2, E, S1, S2],
|
E, S1, S2, B any,
|
||||||
key,
|
](s SET, fb GB) func(GS1) GS2 {
|
||||||
b,
|
return G.ApS[SET, S1, S2, B, GS1S2, GS1, GS2, GB](
|
||||||
|
Ap[GS2, GS1S2, GS1, E, S1, S2],
|
||||||
|
Map[GB, GS1S2, E, B, func(S1) S2],
|
||||||
|
s,
|
||||||
|
fb,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
func Let[
|
||||||
func BindTo[GS1 ~func() ET.Either[E, S1], GT ~func() ET.Either[E, T], E, S1, S2, T any](
|
GS1 ~func() ET.Either[E, S1],
|
||||||
setter func(T) S1,
|
GS2 ~func() ET.Either[E, S2],
|
||||||
) func(GT) GS1 {
|
SET ~func(B) func(S1) S2,
|
||||||
return C.BindTo(
|
FCT ~func(S1) B,
|
||||||
Map[GT, GS1, E, T, S1],
|
E, S1, S2, B any](
|
||||||
setter,
|
s SET,
|
||||||
)
|
f FCT,
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[GS1 ~func() ET.Either[E, S1], GS2 ~func() ET.Either[E, S2], GT ~func() ET.Either[E, T], E, S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa GT,
|
|
||||||
) func(GS1) GS2 {
|
) func(GS1) GS2 {
|
||||||
return A.ApS(
|
return G.Let[SET, FCT, S1, S2, B, GS1, GS2](Map[GS1, GS2, E, S1, S2], s, f)
|
||||||
Ap[GS2, func() ET.Either[E, func(T) S2], GT, E, T, S2],
|
|
||||||
Map[GS1, func() ET.Either[E, func(T) S2], E, S1, func(T) S2],
|
|
||||||
setter,
|
|
||||||
fa,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func Eq[GA ~func() ET.Either[E, A], E, A any](eq EQ.Eq[ET.Either[E, A]]) EQ.Eq[G
|
|||||||
return G.Eq[GA](eq)
|
return G.Eq[GA](eq)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
// FromStrictEquals constructs an `Eq` from the canonical comparison function
|
||||||
func FromStrictEquals[GA ~func() ET.Either[E, A], E, A comparable]() EQ.Eq[GA] {
|
func FromStrictEquals[GA ~func() ET.Either[E, A], E, A comparable]() EQ.Eq[GA] {
|
||||||
return Eq[GA](ET.FromStrictEquals[E, A]())
|
return Eq[GA](ET.FromStrictEquals[E, A]())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ func MonadChainIOK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GR ~f
|
|||||||
|
|
||||||
func ChainIOK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GR ~func() B, E, A, B any](f func(A) GR) func(GA) GB {
|
func ChainIOK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GR ~func() B, E, A, B any](f func(A) GR) func(GA) GB {
|
||||||
return FI.ChainIOK(
|
return FI.ChainIOK(
|
||||||
Chain[GA, GB, E, A, B],
|
MonadChain[GA, GB, E, A, B],
|
||||||
FromIO[GB, GR, E, B],
|
FromIO[GB, GR, E, B],
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
@@ -207,16 +207,11 @@ func MapLeft[GA1 ~func() ET.Either[E1, A], GA2 ~func() ET.Either[E2, A], E1, E2,
|
|||||||
return F.Bind2nd(MonadMapLeft[GA1, GA2, E1, E2, A], f)
|
return F.Bind2nd(MonadMapLeft[GA1, GA2, E1, E2, A], f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay creates an operation that passes in the value after some [time.Duration]
|
// Delay creates an operation that passes in the value after some delay
|
||||||
func Delay[GA ~func() ET.Either[E, A], E, A any](delay time.Duration) func(GA) GA {
|
func Delay[GA ~func() ET.Either[E, A], E, A any](delay time.Duration) func(GA) GA {
|
||||||
return IO.Delay[GA](delay)
|
return IO.Delay[GA](delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
// After creates an operation that passes after the given [time.Time]
|
|
||||||
func After[GA ~func() ET.Either[E, A], E, A any](timestamp time.Time) func(GA) GA {
|
|
||||||
return IO.After[GA](timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadBiMap[GA ~func() ET.Either[E1, A], GB ~func() ET.Either[E2, B], E1, E2, A, B any](fa GA, f func(E1) E2, g func(A) B) GB {
|
func MonadBiMap[GA ~func() ET.Either[E1, A], GB ~func() ET.Either[E2, B], E1, E2, A, B any](fa GA, f func(E1) E2, g func(A) B) GB {
|
||||||
return eithert.MonadBiMap(IO.MonadMap[GA, GB, ET.Either[E1, A], ET.Either[E2, B]], fa, f, g)
|
return eithert.MonadBiMap(IO.MonadMap[GA, GB, ET.Either[E1, A], ET.Either[E2, B]], fa, f, g)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"encoding/json"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
B "github.com/IBM/fp-go/bytes"
|
|
||||||
ET "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LogJson converts the argument to JSON and then logs it via the format string
|
|
||||||
// Can be used with [ChainFirst]
|
|
||||||
func LogJson[GA ~func() ET.Either[error, any], A any](prefix string) func(A) GA {
|
|
||||||
return func(a A) GA {
|
|
||||||
// log this
|
|
||||||
return F.Pipe3(
|
|
||||||
ET.TryCatchError(json.MarshalIndent(a, "", " ")),
|
|
||||||
ET.Map[error](B.ToString),
|
|
||||||
FromEither[func() ET.Either[error, string]],
|
|
||||||
Chain[func() ET.Either[error, string], GA](func(data string) GA {
|
|
||||||
return FromImpure[GA](func() {
|
|
||||||
log.Printf(prefix, data)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
// 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 builder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
R "github.com/IBM/fp-go/http/builder"
|
|
||||||
H "github.com/IBM/fp-go/http/headers"
|
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
|
||||||
IOEH "github.com/IBM/fp-go/ioeither/http"
|
|
||||||
LZ "github.com/IBM/fp-go/lazy"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Requester(builder *R.Builder) IOEH.Requester {
|
|
||||||
|
|
||||||
withBody := F.Curry3(func(data []byte, url string, method string) IOE.IOEither[error, *http.Request] {
|
|
||||||
return IOE.TryCatchError(func() (*http.Request, error) {
|
|
||||||
req, err := http.NewRequest(method, url, bytes.NewReader(data))
|
|
||||||
if err == nil {
|
|
||||||
req.Header.Set(H.ContentLength, strconv.Itoa(len(data)))
|
|
||||||
H.Monoid.Concat(req.Header, builder.GetHeaders())
|
|
||||||
}
|
|
||||||
return req, err
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
withoutBody := F.Curry2(func(url string, method string) IOE.IOEither[error, *http.Request] {
|
|
||||||
return IOE.TryCatchError(func() (*http.Request, error) {
|
|
||||||
req, err := http.NewRequest(method, url, nil)
|
|
||||||
if err == nil {
|
|
||||||
H.Monoid.Concat(req.Header, builder.GetHeaders())
|
|
||||||
}
|
|
||||||
return req, err
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return F.Pipe5(
|
|
||||||
builder.GetBody(),
|
|
||||||
O.Fold(LZ.Of(E.Of[error](withoutBody)), E.Map[error](withBody)),
|
|
||||||
E.Ap[func(string) IOE.IOEither[error, *http.Request]](builder.GetTargetUrl()),
|
|
||||||
E.Flap[error, IOE.IOEither[error, *http.Request]](builder.GetMethod()),
|
|
||||||
E.GetOrElse(IOE.Left[*http.Request, error]),
|
|
||||||
IOE.Map[error](func(req *http.Request) *http.Request {
|
|
||||||
req.Header = H.Monoid.Concat(req.Header, builder.GetHeaders())
|
|
||||||
return req
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// 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 builder
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
R "github.com/IBM/fp-go/http/builder"
|
|
||||||
IO "github.com/IBM/fp-go/io"
|
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBuilderWithQuery(t *testing.T) {
|
|
||||||
// add some query
|
|
||||||
withLimit := R.WithQueryArg("limit")("10")
|
|
||||||
withUrl := R.WithUrl("http://www.example.org?a=b")
|
|
||||||
|
|
||||||
b := F.Pipe2(
|
|
||||||
R.Default,
|
|
||||||
withLimit,
|
|
||||||
withUrl,
|
|
||||||
)
|
|
||||||
|
|
||||||
req := F.Pipe3(
|
|
||||||
b,
|
|
||||||
Requester,
|
|
||||||
IOE.Map[error](func(r *http.Request) *url.URL {
|
|
||||||
return r.URL
|
|
||||||
}),
|
|
||||||
IOE.ChainFirstIOK[error](func(u *url.URL) IO.IO[any] {
|
|
||||||
return IO.FromImpure(func() {
|
|
||||||
q := u.Query()
|
|
||||||
assert.Equal(t, "10", q.Get("limit"))
|
|
||||||
assert.Equal(t, "b", q.Get("a"))
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.True(t, E.IsRight(req()))
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
// 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 di
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
DI "github.com/IBM/fp-go/di"
|
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
|
||||||
IOEH "github.com/IBM/fp-go/ioeither/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// InjHttpClient is the [DI.InjectionToken] for the [http.DefaultClient]
|
|
||||||
InjHttpClient = DI.MakeTokenWithDefault0("HTTP_CLIENT", IOE.Of[error](http.DefaultClient))
|
|
||||||
|
|
||||||
// InjClient is the [DI.InjectionToken] for the default [IOEH.Client]
|
|
||||||
InjClient = DI.MakeTokenWithDefault1("CLIENT", InjHttpClient.IOEither(), IOE.Map[error](IOEH.MakeClient))
|
|
||||||
)
|
|
||||||
@@ -16,12 +16,10 @@
|
|||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
B "github.com/IBM/fp-go/bytes"
|
B "github.com/IBM/fp-go/bytes"
|
||||||
FL "github.com/IBM/fp-go/file"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
H "github.com/IBM/fp-go/http"
|
H "github.com/IBM/fp-go/http"
|
||||||
IOE "github.com/IBM/fp-go/ioeither"
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
@@ -53,24 +51,6 @@ var (
|
|||||||
MakeGetRequest = makeRequest("GET", nil)
|
MakeGetRequest = makeRequest("GET", nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeBodyRequest creates a request that carries a body
|
|
||||||
func MakeBodyRequest(method string, body IOE.IOEither[error, []byte]) func(url string) IOE.IOEither[error, *http.Request] {
|
|
||||||
onBody := F.Pipe1(
|
|
||||||
body,
|
|
||||||
IOE.Map[error](F.Flow2(
|
|
||||||
bytes.NewReader,
|
|
||||||
FL.ToReader[*bytes.Reader],
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
onRelease := IOE.Of[error, io.Reader]
|
|
||||||
withMethod := F.Bind1of3(MakeRequest)(method)
|
|
||||||
|
|
||||||
return F.Flow2(
|
|
||||||
F.Bind1of2(withMethod),
|
|
||||||
IOE.WithResource[*http.Request](onBody, onRelease),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client client) Do(req Requester) IOE.IOEither[error, *http.Response] {
|
func (client client) Do(req Requester) IOE.IOEither[error, *http.Response] {
|
||||||
return F.Pipe1(
|
return F.Pipe1(
|
||||||
req,
|
req,
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
package ioeither
|
package ioeither
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
ET "github.com/IBM/fp-go/either"
|
ET "github.com/IBM/fp-go/either"
|
||||||
I "github.com/IBM/fp-go/io"
|
I "github.com/IBM/fp-go/io"
|
||||||
G "github.com/IBM/fp-go/ioeither/generic"
|
G "github.com/IBM/fp-go/ioeither/generic"
|
||||||
@@ -175,7 +173,7 @@ func MonadMapLeft[E1, E2, A any](fa IOEither[E1, A], f func(E1) E2) IOEither[E2,
|
|||||||
return G.MonadMapLeft[IOEither[E1, A], IOEither[E2, A]](fa, f)
|
return G.MonadMapLeft[IOEither[E1, A], IOEither[E2, A]](fa, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MapLeft[A, E1, E2 any](f func(E1) E2) func(IOEither[E1, A]) IOEither[E2, A] {
|
func MapLeft[E1, E2, A any](f func(E1) E2) func(IOEither[E1, A]) IOEither[E2, A] {
|
||||||
return G.MapLeft[IOEither[E1, A], IOEither[E2, A]](f)
|
return G.MapLeft[IOEither[E1, A], IOEither[E2, A]](f)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,13 +276,3 @@ func Flap[E, B, A any](a A) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
|||||||
func ToIOOption[E, A any](ioe IOEither[E, A]) IOO.IOOption[A] {
|
func ToIOOption[E, A any](ioe IOEither[E, A]) IOO.IOOption[A] {
|
||||||
return G.ToIOOption[IOO.IOOption[A]](ioe)
|
return G.ToIOOption[IOO.IOOption[A]](ioe)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay creates an operation that passes in the value after some delay
|
|
||||||
func Delay[E, A any](delay time.Duration) func(IOEither[E, A]) IOEither[E, A] {
|
|
||||||
return G.Delay[IOEither[E, A]](delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
// After creates an operation that passes after the given [time.Time]
|
|
||||||
func After[E, A any](timestamp time.Time) func(IOEither[E, A]) IOEither[E, A] {
|
|
||||||
return G.After[IOEither[E, A]](timestamp)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
G "github.com/IBM/fp-go/ioeither/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LogJson converts the argument to pretty printed JSON and then logs it via the format string
|
|
||||||
// Can be used with [ChainFirst]
|
|
||||||
func LogJson[A any](prefix string) func(A) IOEither[error, any] {
|
|
||||||
return G.LogJson[IOEither[error, any], A](prefix)
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLogging(t *testing.T) {
|
|
||||||
|
|
||||||
type SomeData struct {
|
|
||||||
Key string `json:"key"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
src := &SomeData{Key: "key", Value: "value"}
|
|
||||||
|
|
||||||
res := F.Pipe1(
|
|
||||||
Of[error](src),
|
|
||||||
ChainFirst(LogJson[*SomeData]("Data: \n%s")),
|
|
||||||
)
|
|
||||||
|
|
||||||
dst := res()
|
|
||||||
assert.Equal(t, E.Of[error](src), dst)
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
// 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 iooption
|
|
||||||
|
|
||||||
import (
|
|
||||||
G "github.com/IBM/fp-go/iooption/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[S any](
|
|
||||||
empty S,
|
|
||||||
) IOOption[S] {
|
|
||||||
return G.Do[IOOption[S], S](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) IOOption[T],
|
|
||||||
) func(IOOption[S1]) IOOption[S2] {
|
|
||||||
return G.Bind[IOOption[S1], IOOption[S2], IOOption[T], S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(IOOption[S1]) IOOption[S2] {
|
|
||||||
return G.Let[IOOption[S1], IOOption[S2], S1, S2, T](setter, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
b T,
|
|
||||||
) func(IOOption[S1]) IOOption[S2] {
|
|
||||||
return G.LetTo[IOOption[S1], IOOption[S2], S1, S2, T](setter, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(IOOption[T]) IOOption[S1] {
|
|
||||||
return G.BindTo[IOOption[S1], IOOption[T], S1, T](setter)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa IOOption[T],
|
|
||||||
) func(IOOption[S1]) IOOption[S2] {
|
|
||||||
return G.ApS[IOOption[S1], IOOption[S2], IOOption[T], S1, S2, T](setter, fa)
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
// 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 iooption
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
"github.com/IBM/fp-go/internal/utils"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getLastName(s utils.Initial) IOOption[string] {
|
|
||||||
return Of("Doe")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGivenName(s utils.WithLastName) IOOption[string] {
|
|
||||||
return Of("John")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBind(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
Bind(utils.SetLastName, getLastName),
|
|
||||||
Bind(utils.SetGivenName, getGivenName),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(), O.Of("John Doe"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApS(t *testing.T) {
|
|
||||||
|
|
||||||
res := F.Pipe3(
|
|
||||||
Do(utils.Empty),
|
|
||||||
ApS(utils.SetLastName, Of("Doe")),
|
|
||||||
ApS(utils.SetGivenName, Of("John")),
|
|
||||||
Map(utils.GetFullName),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.Equal(t, res(), O.Of("John Doe"))
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
// 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 iooption
|
|
||||||
|
|
||||||
import (
|
|
||||||
EQ "github.com/IBM/fp-go/eq"
|
|
||||||
G "github.com/IBM/fp-go/iooption/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Eq implements the equals predicate for values contained in the IO monad
|
|
||||||
func Eq[A any](e EQ.Eq[A]) EQ.Eq[IOOption[A]] {
|
|
||||||
return G.Eq[IOOption[A]](e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
|
||||||
func FromStrictEquals[A comparable]() EQ.Eq[IOOption[A]] {
|
|
||||||
return G.FromStrictEquals[IOOption[A]]()
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
A "github.com/IBM/fp-go/internal/apply"
|
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
|
||||||
F "github.com/IBM/fp-go/internal/functor"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
|
||||||
func Do[GS ~func() O.Option[S], S any](
|
|
||||||
empty S,
|
|
||||||
) GS {
|
|
||||||
return Of[GS](empty)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Bind[GS1 ~func() O.Option[S1], GS2 ~func() O.Option[S2], GT ~func() O.Option[T], S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
f func(S1) GT,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return C.Bind(
|
|
||||||
Chain[GS1, GS2, S1, S2],
|
|
||||||
Map[GT, GS2, T, S2],
|
|
||||||
setter,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
|
||||||
func Let[GS1 ~func() O.Option[S1], GS2 ~func() O.Option[S2], S1, S2, T any](
|
|
||||||
key func(T) func(S1) S2,
|
|
||||||
f func(S1) T,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return F.Let(
|
|
||||||
Map[GS1, GS2, S1, S2],
|
|
||||||
key,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
|
||||||
func LetTo[GS1 ~func() O.Option[S1], GS2 ~func() O.Option[S2], S1, S2, B any](
|
|
||||||
key func(B) func(S1) S2,
|
|
||||||
b B,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return F.LetTo(
|
|
||||||
Map[GS1, GS2, S1, S2],
|
|
||||||
key,
|
|
||||||
b,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTo initializes a new state [S1] from a value [T]
|
|
||||||
func BindTo[GS1 ~func() O.Option[S1], GT ~func() O.Option[T], S1, T any](
|
|
||||||
setter func(T) S1,
|
|
||||||
) func(GT) GS1 {
|
|
||||||
return C.BindTo(
|
|
||||||
Map[GT, GS1, T, S1],
|
|
||||||
setter,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
|
|
||||||
func ApS[GS1 ~func() O.Option[S1], GS2 ~func() O.Option[S2], GT ~func() O.Option[T], S1, S2, T any](
|
|
||||||
setter func(T) func(S1) S2,
|
|
||||||
fa GT,
|
|
||||||
) func(GS1) GS2 {
|
|
||||||
return A.ApS(
|
|
||||||
Ap[GS2, func() O.Option[func(T) S2], GT, T, S2],
|
|
||||||
Map[GS1, func() O.Option[func(T) S2], S1, func(T) S2],
|
|
||||||
setter,
|
|
||||||
fa,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
// 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"
|
|
||||||
G "github.com/IBM/fp-go/io/generic"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Eq implements the equals predicate for values contained in the IO monad
|
|
||||||
func Eq[GA ~func() O.Option[A], A any](e EQ.Eq[A]) EQ.Eq[GA] {
|
|
||||||
return G.Eq[GA](O.Eq(e))
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
|
||||||
func FromStrictEquals[GA ~func() O.Option[A], A comparable]() EQ.Eq[GA] {
|
|
||||||
return Eq[GA](EQ.FromStrictEquals[A]())
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,6 @@ import (
|
|||||||
|
|
||||||
ET "github.com/IBM/fp-go/either"
|
ET "github.com/IBM/fp-go/either"
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
|
||||||
FI "github.com/IBM/fp-go/internal/fromio"
|
FI "github.com/IBM/fp-go/internal/fromio"
|
||||||
"github.com/IBM/fp-go/internal/optiont"
|
"github.com/IBM/fp-go/internal/optiont"
|
||||||
IO "github.com/IBM/fp-go/io/generic"
|
IO "github.com/IBM/fp-go/io/generic"
|
||||||
@@ -77,48 +76,8 @@ func MonadChain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](fa GA,
|
|||||||
return optiont.MonadChain(IO.MonadChain[GA, GB, O.Option[A], O.Option[B]], IO.MonadOf[GB, O.Option[B]], fa, f)
|
return optiont.MonadChain(IO.MonadChain[GA, GB, O.Option[A], O.Option[B]], IO.MonadOf[GB, O.Option[B]], fa, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MonadChainFirst runs the monad returned by the function but returns the result of the original monad
|
|
||||||
func MonadChainFirst[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](ma GA, f func(A) GB) GA {
|
|
||||||
return C.MonadChainFirst(
|
|
||||||
MonadChain[GA, GA, A, A],
|
|
||||||
MonadMap[GB, GA, B, A],
|
|
||||||
ma,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChainFirst runs the monad returned by the function but returns the result of the original monad
|
|
||||||
func ChainFirst[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GA {
|
|
||||||
return C.ChainFirst(
|
|
||||||
MonadChain[GA, GA, A, A],
|
|
||||||
MonadMap[GB, GA, B, A],
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MonadChainFirstIOK runs the monad returned by the function but returns the result of the original monad
|
|
||||||
func MonadChainFirstIOK[GA ~func() O.Option[A], GIOB ~func() B, A, B any](first GA, f func(A) GIOB) GA {
|
|
||||||
return FI.MonadChainFirstIOK(
|
|
||||||
MonadChain[GA, GA, A, A],
|
|
||||||
MonadMap[func() O.Option[B], GA, B, A],
|
|
||||||
FromIO[func() O.Option[B], GIOB, B],
|
|
||||||
first,
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChainFirstIOK runs the monad returned by the function but returns the result of the original monad
|
|
||||||
func ChainFirstIOK[GA ~func() O.Option[A], GIOB ~func() B, A, B any](f func(A) GIOB) func(GA) GA {
|
|
||||||
return FI.ChainFirstIOK(
|
|
||||||
MonadChain[GA, GA, A, A],
|
|
||||||
MonadMap[func() O.Option[B], GA, B, A],
|
|
||||||
FromIO[func() O.Option[B], GIOB, B],
|
|
||||||
f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Chain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GB {
|
func Chain[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](f func(A) GB) func(GA) GB {
|
||||||
return optiont.Chain(IO.MonadChain[GA, GB, O.Option[A], O.Option[B]], IO.MonadOf[GB, O.Option[B]], f)
|
return F.Bind2nd(MonadChain[GA, GB, A, B], f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](ma GA, f func(A) O.Option[B]) GB {
|
func MonadChainOptionK[GA ~func() O.Option[A], GB ~func() O.Option[B], A, B any](ma GA, f func(A) O.Option[B]) GB {
|
||||||
@@ -145,7 +104,7 @@ func MonadChainIOK[GA ~func() O.Option[A], GB ~func() O.Option[B], GR ~func() B,
|
|||||||
|
|
||||||
func ChainIOK[GA ~func() O.Option[A], GB ~func() O.Option[B], GR ~func() B, A, B any](f func(A) GR) func(GA) GB {
|
func ChainIOK[GA ~func() O.Option[A], GB ~func() O.Option[B], GR ~func() B, A, B any](f func(A) GR) func(GA) GB {
|
||||||
return FI.ChainIOK(
|
return FI.ChainIOK(
|
||||||
Chain[GA, GB, A, B],
|
MonadChain[GA, GB, A, B],
|
||||||
FromIO[GB, GR, B],
|
FromIO[GB, GR, B],
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
@@ -219,11 +178,6 @@ func Delay[GA ~func() O.Option[A], A any](delay time.Duration) func(GA) GA {
|
|||||||
return IO.Delay[GA](delay)
|
return IO.Delay[GA](delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
// After creates an operation that passes after the given [time.Time]
|
|
||||||
func After[GA ~func() O.Option[A], A any](timestamp time.Time) func(GA) GA {
|
|
||||||
return IO.After[GA](timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fold convers an IOOption into an IO
|
// Fold convers an IOOption into an IO
|
||||||
func Fold[GA ~func() O.Option[A], GB ~func() B, A, B any](onNone func() GB, onSome func(A) GB) func(GA) GB {
|
func Fold[GA ~func() O.Option[A], GB ~func() B, A, B any](onNone func() GB, onSome func(A) GB) func(GA) GB {
|
||||||
return optiont.MatchE(IO.MonadChain[GA, GB, O.Option[A], B], onNone, onSome)
|
return optiont.MatchE(IO.MonadChain[GA, GB, O.Option[A], B], onNone, onSome)
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
O "github.com/IBM/fp-go/option"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
|
||||||
func WithResource[
|
|
||||||
GA ~func() O.Option[A],
|
|
||||||
GR ~func() O.Option[R],
|
|
||||||
GANY ~func() O.Option[ANY],
|
|
||||||
R, A, ANY any](onCreate GR, onRelease func(R) GANY) func(func(R) GA) GA {
|
|
||||||
// simply map to implementation of bracket
|
|
||||||
return F.Bind13of3(Bracket[GR, GA, GANY, R, A, ANY])(onCreate, F.Ignore2of2[O.Option[A]](onRelease))
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user