mirror of
https://github.com/IBM/fp-go.git
synced 2025-09-05 20:26:12 +02:00
Compare commits
18 Commits
cleue-add-
...
v1.0.56
Author | SHA1 | Date | |
---|---|---|---|
|
c0b16c675b | ||
|
4b68e66528 | ||
|
5b7e5b153b | ||
|
d43fbeb375 | ||
|
57d507c1ba | ||
|
aa19857127 | ||
|
7766787cc1 | ||
|
6a9f38f990 | ||
|
e9584bc247 | ||
|
55252c5680 | ||
|
88bf35c4af | ||
|
da3c9683eb | ||
|
08d9fed9af | ||
|
83a0c6cdef | ||
|
9da484b79e | ||
|
e46cfd89d4 | ||
|
6a4cdfa891 | ||
|
93a7e9964b |
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
|||||||
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@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
- 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 }}
|
||||||
@@ -55,12 +55,12 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# full checkout for semantic-release
|
# full checkout for semantic-release
|
||||||
- name: Full checkout
|
- name: Full checkout
|
||||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
with:
|
with:
|
||||||
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@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
|
||||||
|
30
array/any.go
Normal file
30
array/any.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AnyWithIndex tests if any of the elements in the array matches the predicate
|
||||||
|
func AnyWithIndex[A any](pred func(int, A) bool) func([]A) bool {
|
||||||
|
return G.AnyWithIndex[[]A](pred)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any tests if any of the elements in the array matches the predicate
|
||||||
|
func Any[A any](pred func(A) bool) func([]A) bool {
|
||||||
|
return G.Any[[]A](pred)
|
||||||
|
}
|
30
array/any_test.go
Normal file
30
array/any_test.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// 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/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAny(t *testing.T) {
|
||||||
|
anyBool := Any(F.Identity[bool])
|
||||||
|
|
||||||
|
assert.True(t, anyBool(From(false, true, false)))
|
||||||
|
assert.False(t, anyBool(From(false, false, false)))
|
||||||
|
}
|
@@ -60,18 +60,6 @@ func MapRef[A, B any](f func(a *A) B) func([]A) []B {
|
|||||||
return F.Bind2nd(MonadMapRef[A, B], f)
|
return F.Bind2nd(MonadMapRef[A, B], f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func filter[A any](fa []A, pred func(A) bool) []A {
|
|
||||||
var result []A
|
|
||||||
count := len(fa)
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
a := fa[i]
|
|
||||||
if pred(a) {
|
|
||||||
result = append(result, a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func filterRef[A any](fa []A, pred func(a *A) bool) []A {
|
func filterRef[A any](fa []A, pred func(a *A) bool) []A {
|
||||||
var result []A
|
var result []A
|
||||||
count := len(fa)
|
count := len(fa)
|
||||||
@@ -96,23 +84,38 @@ func filterMapRef[A, B any](fa []A, pred func(a *A) bool, f func(a *A) B) []B {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter returns a new array with all elements from the original array that match a predicate
|
||||||
func Filter[A any](pred func(A) bool) func([]A) []A {
|
func Filter[A any](pred func(A) bool) func([]A) []A {
|
||||||
return F.Bind2nd(filter[A], pred)
|
return G.Filter[[]A](pred)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) func([]A) []A {
|
||||||
|
return G.FilterWithIndex[[]A](pred)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FilterRef[A any](pred func(*A) bool) func([]A) []A {
|
func FilterRef[A any](pred func(*A) bool) func([]A) []A {
|
||||||
return F.Bind2nd(filterRef[A], pred)
|
return F.Bind2nd(filterRef[A], pred)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadFilterMap[A, B any](fa []A, f func(a A) O.Option[B]) []B {
|
func MonadFilterMap[A, B any](fa []A, f func(A) O.Option[B]) []B {
|
||||||
return G.MonadFilterMap[[]A, []B](fa, f)
|
return G.MonadFilterMap[[]A, []B](fa, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterChain maps an array with an iterating function that returns an [O.Option] and it keeps only the Some values discarding the Nones.
|
func MonadFilterMapWithIndex[A, B any](fa []A, f func(int, A) O.Option[B]) []B {
|
||||||
func FilterMap[A, B any](f func(a A) O.Option[B]) func([]A) []B {
|
return G.MonadFilterMapWithIndex[[]A, []B](fa, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterMap maps an array with an iterating function that returns an [O.Option] and it keeps only the Some values discarding the Nones.
|
||||||
|
func FilterMap[A, B any](f func(A) O.Option[B]) func([]A) []B {
|
||||||
return G.FilterMap[[]A, []B](f)
|
return G.FilterMap[[]A, []B](f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterMapWithIndex maps an array with an iterating function that returns an [O.Option] and it keeps only the Some values discarding the Nones.
|
||||||
|
func FilterMapWithIndex[A, B any](f func(int, A) O.Option[B]) func([]A) []B {
|
||||||
|
return G.FilterMapWithIndex[[]A, []B](f)
|
||||||
|
}
|
||||||
|
|
||||||
// FilterChain maps an array with an iterating function that returns an [O.Option] of an array. It keeps only the Some values discarding the Nones and then flattens the result.
|
// FilterChain maps an array with an iterating function that returns an [O.Option] of an array. It keeps only the Some values discarding the Nones and then flattens the result.
|
||||||
func FilterChain[A, B any](f func(A) O.Option[[]B]) func([]A) []B {
|
func FilterChain[A, B any](f func(A) O.Option[[]B]) func([]A) []B {
|
||||||
return G.FilterChain[[]A](f)
|
return G.FilterChain[[]A](f)
|
||||||
@@ -134,9 +137,19 @@ func reduceRef[A, B any](fa []A, f func(B, *A) B, initial B) B {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Reduce[A, B any](f func(B, A) B, initial B) func([]A) B {
|
func Reduce[A, B any](f func(B, A) B, initial B) func([]A) B {
|
||||||
return func(as []A) B {
|
return G.Reduce[[]A](f, initial)
|
||||||
return array.Reduce(as, f, initial)
|
}
|
||||||
}
|
|
||||||
|
func ReduceWithIndex[A, B any](f func(int, B, A) B, initial B) func([]A) B {
|
||||||
|
return G.ReduceWithIndex[[]A](f, initial)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReduceRight[A, B any](f func(A, B) B, initial B) func([]A) B {
|
||||||
|
return G.ReduceRight[[]A](f, initial)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReduceRightWithIndex[A, B any](f func(int, A, B) B, initial B) func([]A) B {
|
||||||
|
return G.ReduceRightWithIndex[[]A](f, initial)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReduceRef[A, B any](f func(B, *A) B, initial B) func([]A) B {
|
func ReduceRef[A, B any](f func(B, *A) B, initial B) func([]A) B {
|
||||||
|
@@ -59,6 +59,17 @@ func TestMap(t *testing.T) {
|
|||||||
assert.Equal(t, dst, []string{"A", "B", "C"})
|
assert.Equal(t, dst, []string{"A", "B", "C"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReduceRight(t *testing.T) {
|
||||||
|
values := From("a", "b", "c")
|
||||||
|
f := func(a, acc string) string {
|
||||||
|
return fmt.Sprintf("%s%s", acc, a)
|
||||||
|
}
|
||||||
|
b := ""
|
||||||
|
|
||||||
|
assert.Equal(t, "cba", ReduceRight(f, b)(values))
|
||||||
|
assert.Equal(t, "", ReduceRight(f, b)(Empty[string]()))
|
||||||
|
}
|
||||||
|
|
||||||
func TestReduce(t *testing.T) {
|
func TestReduce(t *testing.T) {
|
||||||
|
|
||||||
values := MakeBy(101, F.Identity[int])
|
values := MakeBy(101, F.Identity[int])
|
||||||
|
77
array/example_any_test.go
Normal file
77
array/example_any_test.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
O "github.com/IBM/fp-go/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_any() {
|
||||||
|
|
||||||
|
pred := func(val int) bool {
|
||||||
|
return val&2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data1 := From(1, 2, 3)
|
||||||
|
|
||||||
|
fmt.Println(Any(pred)(data1))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_any_filter() {
|
||||||
|
|
||||||
|
pred := func(val int) bool {
|
||||||
|
return val&2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data1 := From(1, 2, 3)
|
||||||
|
|
||||||
|
// Any tests if any of the entries in the array matches the condition
|
||||||
|
Any := F.Flow2(
|
||||||
|
Filter(pred),
|
||||||
|
IsNonEmpty[int],
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(Any(data1))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_any_find() {
|
||||||
|
|
||||||
|
pred := func(val int) bool {
|
||||||
|
return val&2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data1 := From(1, 2, 3)
|
||||||
|
|
||||||
|
// Any tests if any of the entries in the array matches the condition
|
||||||
|
Any := F.Flow2(
|
||||||
|
FindFirst(pred),
|
||||||
|
O.IsSome[int],
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(Any(data1))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
}
|
55
array/example_find_test.go
Normal file
55
array/example_find_test.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_find() {
|
||||||
|
|
||||||
|
pred := func(val int) bool {
|
||||||
|
return val&2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data1 := From(1, 2, 3)
|
||||||
|
|
||||||
|
fmt.Println(FindFirst(pred)(data1))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Some[int](1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_find_filter() {
|
||||||
|
|
||||||
|
pred := func(val int) bool {
|
||||||
|
return val&2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data1 := From(1, 2, 3)
|
||||||
|
|
||||||
|
Find := F.Flow2(
|
||||||
|
Filter(pred),
|
||||||
|
Head[int],
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(Find(data1))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Some[int](1)
|
||||||
|
}
|
61
array/find.go
Normal file
61
array/find.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// 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"
|
||||||
|
O "github.com/IBM/fp-go/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FindFirst finds the first element which satisfies a predicate (or a refinement) function
|
||||||
|
func FindFirst[A any](pred func(A) bool) func([]A) O.Option[A] {
|
||||||
|
return G.FindFirst[[]A](pred)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFirstWithIndex finds the first element which satisfies a predicate (or a refinement) function
|
||||||
|
func FindFirstWithIndex[A any](pred func(int, A) bool) func([]A) O.Option[A] {
|
||||||
|
return G.FindFirstWithIndex[[]A](pred)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFirstMap finds the first element returned by an [O.Option] based selector function
|
||||||
|
func FindFirstMap[A, B any](sel func(A) O.Option[B]) func([]A) O.Option[B] {
|
||||||
|
return G.FindFirstMap[[]A](sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFirstMapWithIndex finds the first element returned by an [O.Option] based selector function
|
||||||
|
func FindFirstMapWithIndex[A, B any](sel func(int, A) O.Option[B]) func([]A) O.Option[B] {
|
||||||
|
return G.FindFirstMapWithIndex[[]A](sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLast finds the Last element which satisfies a predicate (or a refinement) function
|
||||||
|
func FindLast[A any](pred func(A) bool) func([]A) O.Option[A] {
|
||||||
|
return G.FindLast[[]A](pred)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLastWithIndex finds the Last element which satisfies a predicate (or a refinement) function
|
||||||
|
func FindLastWithIndex[A any](pred func(int, A) bool) func([]A) O.Option[A] {
|
||||||
|
return G.FindLastWithIndex[[]A](pred)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLastMap finds the Last element returned by an [O.Option] based selector function
|
||||||
|
func FindLastMap[A, B any](sel func(A) O.Option[B]) func([]A) O.Option[B] {
|
||||||
|
return G.FindLastMap[[]A](sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLastMapWithIndex finds the Last element returned by an [O.Option] based selector function
|
||||||
|
func FindLastMapWithIndex[A, B any](sel func(int, A) O.Option[B]) func([]A) O.Option[B] {
|
||||||
|
return G.FindLastMapWithIndex[[]A](sel)
|
||||||
|
}
|
34
array/generic/any.go
Normal file
34
array/generic/any.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AnyWithIndex tests if any of the elements in the array matches the predicate
|
||||||
|
func AnyWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](pred PRED) func(AS) bool {
|
||||||
|
return F.Flow2(
|
||||||
|
FindFirstWithIndex[AS](pred),
|
||||||
|
O.IsSome[A],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any tests if any of the elements in the array matches the predicate
|
||||||
|
func Any[AS ~[]A, PRED ~func(A) bool, A any](pred PRED) func(AS) bool {
|
||||||
|
return AnyWithIndex[AS](F.Ignore1of2[int](pred))
|
||||||
|
}
|
@@ -29,14 +29,46 @@ func Of[GA ~[]A, A any](value A) GA {
|
|||||||
return GA{value}
|
return GA{value}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Reduce[GA ~[]A, A, B any](fa GA, f func(B, A) B, initial B) B {
|
func Reduce[GA ~[]A, A, B any](f func(B, A) B, initial B) func(GA) B {
|
||||||
|
return func(as GA) B {
|
||||||
|
return MonadReduce[GA](as, f, initial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReduceWithIndex[GA ~[]A, A, B any](f func(int, B, A) B, initial B) func(GA) B {
|
||||||
|
return func(as GA) B {
|
||||||
|
return MonadReduceWithIndex[GA](as, f, initial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReduceRight[GA ~[]A, A, B any](f func(A, B) B, initial B) func(GA) B {
|
||||||
|
return func(as GA) B {
|
||||||
|
return MonadReduceRight[GA](as, f, initial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReduceRightWithIndex[GA ~[]A, A, B any](f func(int, A, B) B, initial B) func(GA) B {
|
||||||
|
return func(as GA) B {
|
||||||
|
return MonadReduceRightWithIndex[GA](as, f, initial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadReduce[GA ~[]A, A, B any](fa GA, f func(B, A) B, initial B) B {
|
||||||
return array.Reduce(fa, f, initial)
|
return array.Reduce(fa, f, initial)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReduceWithIndex[GA ~[]A, A, B any](fa GA, f func(int, B, A) B, initial B) B {
|
func MonadReduceWithIndex[GA ~[]A, A, B any](fa GA, f func(int, B, A) B, initial B) B {
|
||||||
return array.ReduceWithIndex(fa, f, initial)
|
return array.ReduceWithIndex(fa, f, initial)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MonadReduceRight[GA ~[]A, A, B any](fa GA, f func(A, B) B, initial B) B {
|
||||||
|
return array.ReduceRight(fa, f, initial)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadReduceRightWithIndex[GA ~[]A, A, B any](fa GA, f func(int, A, B) B, initial B) B {
|
||||||
|
return array.ReduceRightWithIndex(fa, f, initial)
|
||||||
|
}
|
||||||
|
|
||||||
// From constructs an array from a set of variadic arguments
|
// From constructs an array from a set of variadic arguments
|
||||||
func From[GA ~[]A, A any](data ...A) GA {
|
func From[GA ~[]A, A any](data ...A) GA {
|
||||||
return data
|
return data
|
||||||
@@ -122,16 +154,44 @@ func Size[GA ~[]A, A any](as GA) int {
|
|||||||
return len(as)
|
return len(as)
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(a A) O.Option[B]) GB {
|
func filterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(A) O.Option[B]) GB {
|
||||||
return array.Reduce(fa, func(bs GB, a A) GB {
|
return array.Reduce(fa, func(bs GB, a A) GB {
|
||||||
return O.MonadFold(f(a), F.Constant(bs), F.Bind1st(Append[GB, B], bs))
|
return O.MonadFold(f(a), F.Constant(bs), F.Bind1st(Append[GB, B], bs))
|
||||||
}, Empty[GB]())
|
}, Empty[GB]())
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadFilterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(a A) O.Option[B]) GB {
|
func filterMapWithIndex[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(int, A) O.Option[B]) GB {
|
||||||
|
return array.ReduceWithIndex(fa, func(idx int, bs GB, a A) GB {
|
||||||
|
return O.MonadFold(f(idx, a), F.Constant(bs), F.Bind1st(Append[GB, B], bs))
|
||||||
|
}, Empty[GB]())
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadFilterMap[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(A) O.Option[B]) GB {
|
||||||
return filterMap[GA, GB](fa, f)
|
return filterMap[GA, GB](fa, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MonadFilterMapWithIndex[GA ~[]A, GB ~[]B, A, B any](fa GA, f func(int, A) O.Option[B]) GB {
|
||||||
|
return filterMapWithIndex[GA, GB](fa, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](fa AS, pred PRED) AS {
|
||||||
|
result := make(AS, 0, len(fa))
|
||||||
|
for i, a := range fa {
|
||||||
|
if pred(i, a) {
|
||||||
|
result = append(result, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func FilterWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](pred PRED) func(AS) AS {
|
||||||
|
return F.Bind2nd(filterWithIndex[AS, PRED, A], pred)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Filter[AS ~[]A, PRED ~func(A) bool, A any](pred PRED) func(AS) AS {
|
||||||
|
return FilterWithIndex[AS](F.Ignore1of2[int](pred))
|
||||||
|
}
|
||||||
|
|
||||||
func FilterChain[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[GB]) func(GA) GB {
|
func FilterChain[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[GB]) func(GA) GB {
|
||||||
return F.Flow2(
|
return F.Flow2(
|
||||||
FilterMap[GA, []GB](f),
|
FilterMap[GA, []GB](f),
|
||||||
@@ -143,10 +203,14 @@ func Flatten[GAA ~[]GA, GA ~[]A, A any](mma GAA) GA {
|
|||||||
return MonadChain(mma, F.Identity[GA])
|
return MonadChain(mma, F.Identity[GA])
|
||||||
}
|
}
|
||||||
|
|
||||||
func FilterMap[GA ~[]A, GB ~[]B, A, B any](f func(a A) O.Option[B]) func(GA) GB {
|
func FilterMap[GA ~[]A, GB ~[]B, A, B any](f func(A) O.Option[B]) func(GA) GB {
|
||||||
return F.Bind2nd(MonadFilterMap[GA, GB, A, B], f)
|
return F.Bind2nd(MonadFilterMap[GA, GB, A, B], f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FilterMapWithIndex[GA ~[]A, GB ~[]B, A, B any](f func(int, A) O.Option[B]) func(GA) GB {
|
||||||
|
return F.Bind2nd(MonadFilterMapWithIndex[GA, GB, A, B], f)
|
||||||
|
}
|
||||||
|
|
||||||
func MonadPartition[GA ~[]A, A any](as GA, pred func(A) bool) tuple.Tuple2[GA, GA] {
|
func MonadPartition[GA ~[]A, A any](as GA, pred func(A) bool) tuple.Tuple2[GA, GA] {
|
||||||
left := Empty[GA]()
|
left := Empty[GA]()
|
||||||
right := Empty[GA]()
|
right := Empty[GA]()
|
||||||
|
97
array/generic/find.go
Normal file
97
array/generic/find.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FindFirstWithIndex finds the first element which satisfies a predicate (or a refinement) function
|
||||||
|
func FindFirstWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](pred PRED) func(AS) O.Option[A] {
|
||||||
|
none := O.None[A]()
|
||||||
|
return func(as AS) O.Option[A] {
|
||||||
|
for i, a := range as {
|
||||||
|
if pred(i, a) {
|
||||||
|
return O.Some(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFirst finds the first element which satisfies a predicate (or a refinement) function
|
||||||
|
func FindFirst[AS ~[]A, PRED ~func(A) bool, A any](pred PRED) func(AS) O.Option[A] {
|
||||||
|
return FindFirstWithIndex[AS](F.Ignore1of2[int](pred))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFirstMapWithIndex finds the first element returned by an [O.Option] based selector function
|
||||||
|
func FindFirstMapWithIndex[AS ~[]A, PRED ~func(int, A) O.Option[B], A, B any](pred PRED) func(AS) O.Option[B] {
|
||||||
|
none := O.None[B]()
|
||||||
|
return func(as AS) O.Option[B] {
|
||||||
|
count := len(as)
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
out := pred(i, as[i])
|
||||||
|
if O.IsSome(out) {
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindFirstMap finds the first element returned by an [O.Option] based selector function
|
||||||
|
func FindFirstMap[AS ~[]A, PRED ~func(A) O.Option[B], A, B any](pred PRED) func(AS) O.Option[B] {
|
||||||
|
return FindFirstMapWithIndex[AS](F.Ignore1of2[int](pred))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLastWithIndex finds the first element which satisfies a predicate (or a refinement) function
|
||||||
|
func FindLastWithIndex[AS ~[]A, PRED ~func(int, A) bool, A any](pred PRED) func(AS) O.Option[A] {
|
||||||
|
none := O.None[A]()
|
||||||
|
return func(as AS) O.Option[A] {
|
||||||
|
for i := len(as) - 1; i >= 0; i-- {
|
||||||
|
a := as[i]
|
||||||
|
if pred(i, a) {
|
||||||
|
return O.Some(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLast finds the first element which satisfies a predicate (or a refinement) function
|
||||||
|
func FindLast[AS ~[]A, PRED ~func(A) bool, A any](pred PRED) func(AS) O.Option[A] {
|
||||||
|
return FindLastWithIndex[AS](F.Ignore1of2[int](pred))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLastMapWithIndex finds the first element returned by an [O.Option] based selector function
|
||||||
|
func FindLastMapWithIndex[AS ~[]A, PRED ~func(int, A) O.Option[B], A, B any](pred PRED) func(AS) O.Option[B] {
|
||||||
|
none := O.None[B]()
|
||||||
|
return func(as AS) O.Option[B] {
|
||||||
|
for i := len(as) - 1; i >= 0; i-- {
|
||||||
|
out := pred(i, as[i])
|
||||||
|
if O.IsSome(out) {
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindLastMap finds the first element returned by an [O.Option] based selector function
|
||||||
|
func FindLastMap[AS ~[]A, PRED ~func(A) O.Option[B], A, B any](pred PRED) func(AS) O.Option[B] {
|
||||||
|
return FindLastMapWithIndex[AS](F.Ignore1of2[int](pred))
|
||||||
|
}
|
109
assert/assert_test.go
Normal file
109
assert/assert_test.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// 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 assert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errTest = fmt.Errorf("test failure")
|
||||||
|
|
||||||
|
// Eq is the equal predicate checking if objects are equal
|
||||||
|
Eq = EQ.FromEquals(assert.ObjectsAreEqual)
|
||||||
|
)
|
||||||
|
|
||||||
|
func wrap1[T any](wrapped func(t assert.TestingT, expected, actual any, msgAndArgs ...any) bool, t *testing.T, expected T) func(actual T) E.Either[error, T] {
|
||||||
|
return func(actual T) E.Either[error, T] {
|
||||||
|
ok := wrapped(t, expected, actual)
|
||||||
|
if ok {
|
||||||
|
return E.Of[error](actual)
|
||||||
|
}
|
||||||
|
return E.Left[T](errTest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotEqual tests if the expected and the actual values are not equal
|
||||||
|
func NotEqual[T any](t *testing.T, expected T) func(actual T) E.Either[error, T] {
|
||||||
|
return wrap1(assert.NotEqual, t, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal tests if the expected and the actual values are equal
|
||||||
|
func Equal[T any](t *testing.T, expected T) func(actual T) E.Either[error, T] {
|
||||||
|
return wrap1(assert.Equal, t, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length tests if an array has the expected length
|
||||||
|
func Length[T any](t *testing.T, expected int) func(actual []T) E.Either[error, []T] {
|
||||||
|
return func(actual []T) E.Either[error, []T] {
|
||||||
|
ok := assert.Len(t, actual, expected)
|
||||||
|
if ok {
|
||||||
|
return E.Of[error](actual)
|
||||||
|
}
|
||||||
|
return E.Left[[]T](errTest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoError validates that there is no error
|
||||||
|
func NoError[T any](t *testing.T) func(actual E.Either[error, T]) E.Either[error, T] {
|
||||||
|
return func(actual E.Either[error, T]) E.Either[error, T] {
|
||||||
|
return E.MonadFold(actual, func(e error) E.Either[error, T] {
|
||||||
|
assert.NoError(t, e)
|
||||||
|
return E.Left[T](e)
|
||||||
|
}, func(value T) E.Either[error, T] {
|
||||||
|
assert.NoError(t, nil)
|
||||||
|
return E.Right[error](value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArrayContains tests if a value is contained in an array
|
||||||
|
func ArrayContains[T any](t *testing.T, expected T) func(actual []T) E.Either[error, []T] {
|
||||||
|
return func(actual []T) E.Either[error, []T] {
|
||||||
|
ok := assert.Contains(t, actual, expected)
|
||||||
|
if ok {
|
||||||
|
return E.Of[error](actual)
|
||||||
|
}
|
||||||
|
return E.Left[[]T](errTest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsKey tests if a key is contained in a map
|
||||||
|
func ContainsKey[T any, K comparable](t *testing.T, expected K) func(actual map[K]T) E.Either[error, map[K]T] {
|
||||||
|
return func(actual map[K]T) E.Either[error, map[K]T] {
|
||||||
|
ok := assert.Contains(t, actual, expected)
|
||||||
|
if ok {
|
||||||
|
return E.Of[error](actual)
|
||||||
|
}
|
||||||
|
return E.Left[map[K]T](errTest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotContainsKey tests if a key is not contained in a map
|
||||||
|
func NotContainsKey[T any, K comparable](t *testing.T, expected K) func(actual map[K]T) E.Either[error, map[K]T] {
|
||||||
|
return func(actual map[K]T) E.Either[error, map[K]T] {
|
||||||
|
ok := assert.NotContains(t, actual, expected)
|
||||||
|
if ok {
|
||||||
|
return E.Of[error](actual)
|
||||||
|
}
|
||||||
|
return E.Left[map[K]T](errTest)
|
||||||
|
}
|
||||||
|
}
|
59
boolean/boolean.go
Normal file
59
boolean/boolean.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// 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 boolean
|
||||||
|
|
||||||
|
import (
|
||||||
|
EQ "github.com/IBM/fp-go/eq"
|
||||||
|
M "github.com/IBM/fp-go/monoid"
|
||||||
|
O "github.com/IBM/fp-go/ord"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// MonoidAny is the boolean [M.Monoid] under disjunction
|
||||||
|
MonoidAny = M.MakeMonoid(
|
||||||
|
func(l, r bool) bool {
|
||||||
|
return l || r
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
|
||||||
|
// MonoidAll is the boolean [M.Monoid] under conjuction
|
||||||
|
MonoidAll = M.MakeMonoid(
|
||||||
|
func(l, r bool) bool {
|
||||||
|
return l && r
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Eq is the equals predicate for boolean
|
||||||
|
Eq = EQ.FromStrictEquals[bool]()
|
||||||
|
|
||||||
|
// Ord is the strict ordering for boolean
|
||||||
|
Ord = O.MakeOrd(func(l, r bool) int {
|
||||||
|
if l {
|
||||||
|
if r {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return +1
|
||||||
|
}
|
||||||
|
if r {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}, func(l, r bool) bool {
|
||||||
|
return l == r
|
||||||
|
})
|
||||||
|
)
|
@@ -115,16 +115,14 @@ func generateEitherize(f *os.File, i int) {
|
|||||||
fmt.Fprintf(f, "t%d T%d", j, j)
|
fmt.Fprintf(f, "t%d T%d", j, j)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(f, ") Either[error, R] {\n")
|
fmt.Fprintf(f, ") Either[error, R] {\n")
|
||||||
fmt.Fprintf(f, " return TryCatchError(func() (R, error) {\n")
|
fmt.Fprintf(f, " return TryCatchError(f(")
|
||||||
fmt.Fprintf(f, " return f(")
|
|
||||||
for j := 0; j < i; j++ {
|
for j := 0; j < i; j++ {
|
||||||
if j > 0 {
|
if j > 0 {
|
||||||
fmt.Fprintf(f, ", ")
|
fmt.Fprintf(f, ", ")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(f, "t%d", j)
|
fmt.Fprintf(f, "t%d", j)
|
||||||
}
|
}
|
||||||
fmt.Fprintln(f, ")")
|
fmt.Fprintln(f, "))")
|
||||||
fmt.Fprintln(f, " })")
|
|
||||||
fmt.Fprintln(f, " }")
|
fmt.Fprintln(f, " }")
|
||||||
fmt.Fprintln(f, "}")
|
fmt.Fprintln(f, "}")
|
||||||
}
|
}
|
||||||
|
@@ -22,30 +22,28 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Const[E, A any] struct {
|
type Const[E, A any] struct {
|
||||||
Value E
|
value E
|
||||||
}
|
}
|
||||||
|
|
||||||
func Make[E, A any](e E) Const[E, A] {
|
func Make[E, A any](e E) Const[E, A] {
|
||||||
return Const[E, A]{Value: e}
|
return Const[E, A]{value: e}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unwrap[E, A any](c Const[E, A]) E {
|
func Unwrap[E, A any](c Const[E, A]) E {
|
||||||
return c.Value
|
return c.value
|
||||||
}
|
}
|
||||||
|
|
||||||
func Of[E, A any](m M.Monoid[E]) func(A) Const[E, A] {
|
func Of[E, A any](m M.Monoid[E]) func(A) Const[E, A] {
|
||||||
return func(a A) Const[E, A] {
|
return F.Constant1[A](Make[E, A](m.Empty()))
|
||||||
return Make[E, A](m.Empty())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadMap[E, A, B any](fa Const[E, A], f func(A) B) Const[E, B] {
|
func MonadMap[E, A, B any](fa Const[E, A], f func(A) B) Const[E, B] {
|
||||||
return Make[E, B](fa.Value)
|
return Make[E, B](fa.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadAp[E, A, B any](s S.Semigroup[E]) func(fab Const[E, func(A) B], fa Const[E, A]) Const[E, B] {
|
func MonadAp[E, A, B any](s S.Semigroup[E]) func(fab Const[E, func(A) B], fa Const[E, A]) Const[E, B] {
|
||||||
return func(fab Const[E, func(A) B], fa Const[E, A]) Const[E, B] {
|
return func(fab Const[E, func(A) B], fa Const[E, A]) Const[E, B] {
|
||||||
return Make[E, B](s.Concat(fab.Value, fa.Value))
|
return Make[E, B](s.Concat(fab.value, fa.value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,15 +19,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
E "github.com/IBM/fp-go/either"
|
E "github.com/IBM/fp-go/either"
|
||||||
ET "github.com/IBM/fp-go/either"
|
|
||||||
IOE "github.com/IBM/fp-go/ioeither/generic"
|
IOE "github.com/IBM/fp-go/ioeither/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// withContext wraps an existing IOEither and performs a context check for cancellation before delegating
|
// WithContext wraps an existing IOEither and performs a context check for cancellation before delegating
|
||||||
func WithContext[GIO ~func() E.Either[error, A], A any](ctx context.Context, ma GIO) GIO {
|
func WithContext[GIO ~func() E.Either[error, A], A any](ctx context.Context, ma GIO) GIO {
|
||||||
return IOE.MakeIO[GIO](func() E.Either[error, A] {
|
return IOE.MakeIO[GIO](func() E.Either[error, A] {
|
||||||
if err := context.Cause(ctx); err != nil {
|
if err := context.Cause(ctx); err != nil {
|
||||||
return ET.Left[A](err)
|
return E.Left[A](err)
|
||||||
}
|
}
|
||||||
return ma()
|
return ma()
|
||||||
})
|
})
|
||||||
|
@@ -1,35 +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 reader
|
|
||||||
|
|
||||||
import (
|
|
||||||
R "github.com/IBM/fp-go/reader/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TraverseArray transforms an array
|
|
||||||
func TraverseArray[A, B any](f func(A) Reader[B]) func([]A) Reader[[]B] {
|
|
||||||
return R.TraverseArray[Reader[B], Reader[[]B], []A](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TraverseArrayWithIndex transforms an array
|
|
||||||
func TraverseArrayWithIndex[A, B any](f func(int, A) Reader[B]) func([]A) Reader[[]B] {
|
|
||||||
return R.TraverseArrayWithIndex[Reader[B], Reader[[]B], []A](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SequenceArray converts a homogeneous sequence of either into an either of sequence
|
|
||||||
func SequenceArray[A any](ma []Reader[A]) Reader[[]A] {
|
|
||||||
return R.SequenceArray[Reader[A], Reader[[]A]](ma)
|
|
||||||
}
|
|
@@ -1,53 +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 reader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
R "github.com/IBM/fp-go/reader/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// these functions curry a golang function with the context as the firsr parameter into a either reader with the context as the last parameter
|
|
||||||
// this goes back to the advice in https://pkg.go.dev/context to put the context as a first parameter as a convention
|
|
||||||
|
|
||||||
func Curry0[A any](f func(context.Context) A) Reader[A] {
|
|
||||||
return R.Curry0[Reader[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Curry1[T1, A any](f func(context.Context, T1) A) func(T1) Reader[A] {
|
|
||||||
return R.Curry1[Reader[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Curry2[T1, T2, A any](f func(context.Context, T1, T2) A) func(T1) func(T2) Reader[A] {
|
|
||||||
return R.Curry2[Reader[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Curry3[T1, T2, T3, A any](f func(context.Context, T1, T2, T3) A) func(T1) func(T2) func(T3) Reader[A] {
|
|
||||||
return R.Curry3[Reader[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uncurry1[T1, A any](f func(T1) Reader[A]) func(context.Context, T1) A {
|
|
||||||
return R.Uncurry1(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uncurry2[T1, T2, A any](f func(T1) func(T2) Reader[A]) func(context.Context, T1, T2) A {
|
|
||||||
return R.Uncurry2(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Uncurry3[T1, T2, T3, A any](f func(T1) func(T2) func(T3) Reader[A]) func(context.Context, T1, T2, T3) A {
|
|
||||||
return R.Uncurry3(f)
|
|
||||||
}
|
|
@@ -1,41 +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 reader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
R "github.com/IBM/fp-go/reader/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// these functions curry a golang function with the context as the firsr parameter into a either reader with the context as the last parameter
|
|
||||||
// this goes back to the advice in https://pkg.go.dev/context to put the context as a first parameter as a convention
|
|
||||||
|
|
||||||
func From0[A any](f func(context.Context) A) func() Reader[A] {
|
|
||||||
return R.From0[Reader[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func From1[T1, A any](f func(context.Context, T1) A) func(T1) Reader[A] {
|
|
||||||
return R.From1[Reader[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func From2[T1, T2, A any](f func(context.Context, T1, T2) A) func(T1, T2) Reader[A] {
|
|
||||||
return R.From2[Reader[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func From3[T1, T2, T3, A any](f func(context.Context, T1, T2, T3) A) func(T1, T2, T3) Reader[A] {
|
|
||||||
return R.From3[Reader[A]](f)
|
|
||||||
}
|
|
@@ -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 reader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
R "github.com/IBM/fp-go/reader/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
func MonadMap[A, B any](fa Reader[A], f func(A) B) Reader[B] {
|
|
||||||
return R.MonadMap[Reader[A], Reader[B]](fa, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Map[A, B any](f func(A) B) func(Reader[A]) Reader[B] {
|
|
||||||
return R.Map[Reader[A], Reader[B]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChain[A, B any](ma Reader[A], f func(A) Reader[B]) Reader[B] {
|
|
||||||
return R.MonadChain(ma, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Chain[A, B any](f func(A) Reader[B]) func(Reader[A]) Reader[B] {
|
|
||||||
return R.Chain[Reader[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Of[A any](a A) Reader[A] {
|
|
||||||
return R.Of[Reader[A]](a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadAp[A, B any](fab Reader[func(A) B], fa Reader[A]) Reader[B] {
|
|
||||||
return R.MonadAp[Reader[A], Reader[B]](fab, fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Ap[A, B any](fa Reader[A]) func(Reader[func(A) B]) Reader[B] {
|
|
||||||
return R.Ap[Reader[A], Reader[B], Reader[func(A) B]](fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Ask() Reader[context.Context] {
|
|
||||||
return R.Ask[Reader[context.Context]]()
|
|
||||||
}
|
|
||||||
|
|
||||||
func Asks[A any](r Reader[A]) Reader[A] {
|
|
||||||
return R.Asks(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadFlap[B, A any](fab Reader[func(A) B], a A) Reader[B] {
|
|
||||||
return R.MonadFlap[Reader[func(A) B], Reader[B]](fab, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Flap[B, A any](a A) func(Reader[func(A) B]) Reader[B] {
|
|
||||||
return R.Flap[Reader[func(A) B], Reader[B]](a)
|
|
||||||
}
|
|
@@ -1,75 +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 reader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GoFunction(ctx context.Context, data string) string {
|
|
||||||
return strings.ToUpper(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GoIntFunction(ctx context.Context, data string, number int) string {
|
|
||||||
return fmt.Sprintf("%s: %d", data, number)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReaderFrom(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
f := From1(GoFunction)
|
|
||||||
|
|
||||||
result := f("input")(ctx)
|
|
||||||
|
|
||||||
assert.Equal(t, result, "INPUT")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func MyFinalResult(left, right string) string {
|
|
||||||
return fmt.Sprintf("%s-%s", left, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadersFrom(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
f1 := From1(GoFunction)
|
|
||||||
f2 := From2(GoIntFunction)
|
|
||||||
|
|
||||||
result1 := f1("input")(ctx)
|
|
||||||
result2 := f2("input", 10)(ctx)
|
|
||||||
|
|
||||||
result3 := MyFinalResult(result1, result2)
|
|
||||||
|
|
||||||
h := F.Pipe1(
|
|
||||||
SequenceT2(f1("input"), f2("input", 10)),
|
|
||||||
Map(T.Tupled2(MyFinalResult)),
|
|
||||||
)
|
|
||||||
|
|
||||||
composedResult := h(ctx)
|
|
||||||
|
|
||||||
assert.Equal(t, result1, "INPUT")
|
|
||||||
assert.Equal(t, result2, "input: 10")
|
|
||||||
assert.Equal(t, result3, "INPUT-input: 10")
|
|
||||||
|
|
||||||
assert.Equal(t, composedResult, "INPUT-input: 10")
|
|
||||||
|
|
||||||
}
|
|
@@ -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 reader
|
|
||||||
|
|
||||||
import (
|
|
||||||
R "github.com/IBM/fp-go/reader/generic"
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SequenceT converts n inputs of higher kinded types into a higher kinded types of n strongly typed values, represented as a tuple
|
|
||||||
|
|
||||||
func SequenceT1[A any](a Reader[A]) Reader[T.Tuple1[A]] {
|
|
||||||
return R.SequenceT1[
|
|
||||||
Reader[A],
|
|
||||||
Reader[T.Tuple1[A]],
|
|
||||||
](a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SequenceT2[A, B any](a Reader[A], b Reader[B]) Reader[T.Tuple2[A, B]] {
|
|
||||||
return R.SequenceT2[
|
|
||||||
Reader[A],
|
|
||||||
Reader[B],
|
|
||||||
Reader[T.Tuple2[A, B]],
|
|
||||||
](a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SequenceT3[A, B, C any](a Reader[A], b Reader[B], c Reader[C]) Reader[T.Tuple3[A, B, C]] {
|
|
||||||
return R.SequenceT3[
|
|
||||||
Reader[A],
|
|
||||||
Reader[B],
|
|
||||||
Reader[C],
|
|
||||||
Reader[T.Tuple3[A, B, C]],
|
|
||||||
](a, b, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SequenceT4[A, B, C, D any](a Reader[A], b Reader[B], c Reader[C], d Reader[D]) Reader[T.Tuple4[A, B, C, D]] {
|
|
||||||
return R.SequenceT4[
|
|
||||||
Reader[A],
|
|
||||||
Reader[B],
|
|
||||||
Reader[C],
|
|
||||||
Reader[D],
|
|
||||||
Reader[T.Tuple4[A, B, C, D]],
|
|
||||||
](a, b, c, d)
|
|
||||||
}
|
|
@@ -34,8 +34,6 @@ var (
|
|||||||
|
|
||||||
func command(name string, args []string, in []byte) RE.ReaderEither[exec.CommandOutput] {
|
func command(name string, args []string, in []byte) RE.ReaderEither[exec.CommandOutput] {
|
||||||
return func(ctx context.Context) E.Either[error, exec.CommandOutput] {
|
return func(ctx context.Context) E.Either[error, exec.CommandOutput] {
|
||||||
return E.TryCatchError(func() (exec.CommandOutput, error) {
|
return E.TryCatchError(GE.Exec(ctx, name, args, in))
|
||||||
return GE.Exec(ctx, name, args, in)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ package readereither
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
R "github.com/IBM/fp-go/context/reader"
|
|
||||||
ET "github.com/IBM/fp-go/either"
|
ET "github.com/IBM/fp-go/either"
|
||||||
O "github.com/IBM/fp-go/option"
|
O "github.com/IBM/fp-go/option"
|
||||||
RE "github.com/IBM/fp-go/readereither/generic"
|
RE "github.com/IBM/fp-go/readereither/generic"
|
||||||
@@ -32,14 +31,6 @@ func FromEither[A any](e ET.Either[error, A]) ReaderEither[A] {
|
|||||||
return RE.FromEither[ReaderEither[A]](e)
|
return RE.FromEither[ReaderEither[A]](e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RightReader[A any](r R.Reader[A]) ReaderEither[A] {
|
|
||||||
return RE.RightReader[R.Reader[A], ReaderEither[A]](r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LeftReader[A any](l R.Reader[error]) ReaderEither[A] {
|
|
||||||
return RE.LeftReader[R.Reader[error], ReaderEither[A]](l)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Left[A any](l error) ReaderEither[A] {
|
func Left[A any](l error) ReaderEither[A] {
|
||||||
return RE.Left[ReaderEither[A]](l)
|
return RE.Left[ReaderEither[A]](l)
|
||||||
}
|
}
|
||||||
@@ -48,10 +39,6 @@ func Right[A any](r A) ReaderEither[A] {
|
|||||||
return RE.Right[ReaderEither[A]](r)
|
return RE.Right[ReaderEither[A]](r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FromReader[A any](r R.Reader[A]) ReaderEither[A] {
|
|
||||||
return RE.FromReader[R.Reader[A], ReaderEither[A]](r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadMap[A, B any](fa ReaderEither[A], f func(A) B) ReaderEither[B] {
|
func MonadMap[A, B any](fa ReaderEither[A], f func(A) B) ReaderEither[B] {
|
||||||
return RE.MonadMap[ReaderEither[A], ReaderEither[B]](fa, f)
|
return RE.MonadMap[ReaderEither[A], ReaderEither[B]](fa, f)
|
||||||
}
|
}
|
||||||
@@ -84,30 +71,14 @@ func FromPredicate[A any](pred func(A) bool, onFalse func(A) error) func(A) Read
|
|||||||
return RE.FromPredicate[ReaderEither[A]](pred, onFalse)
|
return RE.FromPredicate[ReaderEither[A]](pred, onFalse)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fold[A, B any](onLeft func(error) R.Reader[B], onRight func(A) R.Reader[B]) func(ReaderEither[A]) R.Reader[B] {
|
|
||||||
return RE.Fold[ReaderEither[A]](onLeft, onRight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetOrElse[A any](onLeft func(error) R.Reader[A]) func(ReaderEither[A]) R.Reader[A] {
|
|
||||||
return RE.GetOrElse[ReaderEither[A]](onLeft)
|
|
||||||
}
|
|
||||||
|
|
||||||
func OrElse[A any](onLeft func(error) ReaderEither[A]) func(ReaderEither[A]) ReaderEither[A] {
|
func OrElse[A any](onLeft func(error) ReaderEither[A]) func(ReaderEither[A]) ReaderEither[A] {
|
||||||
return RE.OrElse[ReaderEither[A]](onLeft)
|
return RE.OrElse[ReaderEither[A]](onLeft)
|
||||||
}
|
}
|
||||||
|
|
||||||
func OrLeft[A any](onLeft func(error) R.Reader[error]) func(ReaderEither[A]) ReaderEither[A] {
|
|
||||||
return RE.OrLeft[ReaderEither[A], ReaderEither[A]](onLeft)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Ask() ReaderEither[context.Context] {
|
func Ask() ReaderEither[context.Context] {
|
||||||
return RE.Ask[ReaderEither[context.Context]]()
|
return RE.Ask[ReaderEither[context.Context]]()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Asks[A any](r R.Reader[A]) ReaderEither[A] {
|
|
||||||
return RE.Asks[R.Reader[A], ReaderEither[A]](r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChainEitherK[A, B any](ma ReaderEither[A], f func(A) ET.Either[error, B]) ReaderEither[B] {
|
func MonadChainEitherK[A, B any](ma ReaderEither[A], f func(A) ET.Either[error, B]) ReaderEither[B] {
|
||||||
return RE.MonadChainEitherK[ReaderEither[A], ReaderEither[B]](ma, f)
|
return RE.MonadChainEitherK[ReaderEither[A], ReaderEither[B]](ma, 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 readerio
|
|
||||||
|
|
||||||
import (
|
|
||||||
IO "github.com/IBM/fp-go/io"
|
|
||||||
R "github.com/IBM/fp-go/readerio/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TraverseArray transforms an array
|
|
||||||
func TraverseArray[A, B any](f func(A) ReaderIO[B]) func([]A) ReaderIO[[]B] {
|
|
||||||
return R.TraverseArray[ReaderIO[B], ReaderIO[[]B], IO.IO[B], IO.IO[[]B], []A](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TraverseArrayWithIndex transforms an array
|
|
||||||
func TraverseArrayWithIndex[A, B any](f func(int, A) ReaderIO[B]) func([]A) ReaderIO[[]B] {
|
|
||||||
return R.TraverseArrayWithIndex[ReaderIO[B], ReaderIO[[]B], IO.IO[B], IO.IO[[]B], []A](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SequenceArray converts a homogeneous sequence of either into an either of sequence
|
|
||||||
func SequenceArray[A any](ma []ReaderIO[A]) ReaderIO[[]A] {
|
|
||||||
return R.SequenceArray[ReaderIO[A], ReaderIO[[]A]](ma)
|
|
||||||
}
|
|
@@ -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 readerio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
IO "github.com/IBM/fp-go/io"
|
|
||||||
R "github.com/IBM/fp-go/readerio/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// these functions curry a golang function with the context as the firsr parameter into a either reader with the context as the last parameter
|
|
||||||
// this goes back to the advice in https://pkg.go.dev/context to put the context as a first parameter as a convention
|
|
||||||
|
|
||||||
func From0[A any](f func(context.Context) IO.IO[A]) func() ReaderIO[A] {
|
|
||||||
return R.From0[ReaderIO[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func From1[T1, A any](f func(context.Context, T1) IO.IO[A]) func(T1) ReaderIO[A] {
|
|
||||||
return R.From1[ReaderIO[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func From2[T1, T2, A any](f func(context.Context, T1, T2) IO.IO[A]) func(T1, T2) ReaderIO[A] {
|
|
||||||
return R.From2[ReaderIO[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func From3[T1, T2, T3, A any](f func(context.Context, T1, T2, T3) IO.IO[A]) func(T1, T2, T3) ReaderIO[A] {
|
|
||||||
return R.From3[ReaderIO[A]](f)
|
|
||||||
}
|
|
@@ -1,102 +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 readerio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
IO "github.com/IBM/fp-go/io"
|
|
||||||
L "github.com/IBM/fp-go/lazy"
|
|
||||||
R "github.com/IBM/fp-go/readerio/generic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FromIO converts an [IO.IO] to a [ReaderIO]
|
|
||||||
func FromIO[A any](a IO.IO[A]) ReaderIO[A] {
|
|
||||||
return R.FromIO[ReaderIO[A]](a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadMap[A, B any](fa ReaderIO[A], f func(A) B) ReaderIO[B] {
|
|
||||||
return R.MonadMap[ReaderIO[A], ReaderIO[B]](fa, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Map[A, B any](f func(A) B) func(ReaderIO[A]) ReaderIO[B] {
|
|
||||||
return R.Map[ReaderIO[A], ReaderIO[B]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChain[A, B any](ma ReaderIO[A], f func(A) ReaderIO[B]) ReaderIO[B] {
|
|
||||||
return R.MonadChain(ma, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Chain[A, B any](f func(A) ReaderIO[B]) func(ReaderIO[A]) ReaderIO[B] {
|
|
||||||
return R.Chain[ReaderIO[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChainIOK[A, B any](fa ReaderIO[A], f func(A) IO.IO[B]) ReaderIO[B] {
|
|
||||||
return R.MonadChainIOK[ReaderIO[A], ReaderIO[B]](fa, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ChainIOK[A, B any](f func(A) IO.IO[B]) func(ReaderIO[A]) ReaderIO[B] {
|
|
||||||
return R.ChainIOK[ReaderIO[A], ReaderIO[B]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChainFirstIOK[A, B any](fa ReaderIO[A], f func(A) IO.IO[B]) ReaderIO[A] {
|
|
||||||
return R.MonadChainFirstIOK[ReaderIO[A], ReaderIO[B]](fa, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ChainFirstIOK[A, B any](f func(A) IO.IO[B]) func(ReaderIO[A]) ReaderIO[A] {
|
|
||||||
return R.ChainFirstIOK[ReaderIO[A], ReaderIO[B]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Of[A any](a A) ReaderIO[A] {
|
|
||||||
return R.Of[ReaderIO[A]](a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadAp[A, B any](fab ReaderIO[func(A) B], fa ReaderIO[A]) ReaderIO[B] {
|
|
||||||
return R.MonadAp[ReaderIO[A], ReaderIO[B]](fab, fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Ap[A, B any](fa ReaderIO[A]) func(ReaderIO[func(A) B]) ReaderIO[B] {
|
|
||||||
return R.Ap[ReaderIO[A], ReaderIO[B], ReaderIO[func(A) B]](fa)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Ask() ReaderIO[context.Context] {
|
|
||||||
return R.Ask[ReaderIO[context.Context]]()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
|
||||||
func Defer[A any](gen L.Lazy[ReaderIO[A]]) ReaderIO[A] {
|
|
||||||
return R.Defer[ReaderIO[A]](gen)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memoize computes the value of the provided [ReaderIO] monad lazily but exactly once
|
|
||||||
// The context used to compute the value is the context of the first call, so do not use this
|
|
||||||
// method if the value has a functional dependency on the content of the context
|
|
||||||
func Memoize[A any](rdr ReaderIO[A]) ReaderIO[A] {
|
|
||||||
return R.Memoize[ReaderIO[A]](rdr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flatten converts a nested [ReaderIO] into a [ReaderIO]
|
|
||||||
func Flatten[A any](mma ReaderIO[ReaderIO[A]]) ReaderIO[A] {
|
|
||||||
return R.Flatten[ReaderIO[A]](mma)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadFlap[B, A any](fab ReaderIO[func(A) B], a A) ReaderIO[B] {
|
|
||||||
return R.MonadFlap[ReaderIO[func(A) B], ReaderIO[B]](fab, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Flap[B, A any](a A) func(ReaderIO[func(A) B]) ReaderIO[B] {
|
|
||||||
return R.Flap[ReaderIO[func(A) B], ReaderIO[B]](a)
|
|
||||||
}
|
|
@@ -1,80 +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 readerio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
F "github.com/IBM/fp-go/function"
|
|
||||||
IO "github.com/IBM/fp-go/io"
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GoFunction(ctx context.Context, data string) IO.IO[string] {
|
|
||||||
return func() string {
|
|
||||||
return strings.ToUpper(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GoIntFunction(ctx context.Context, data string, number int) IO.IO[string] {
|
|
||||||
return func() string {
|
|
||||||
return fmt.Sprintf("%s: %d", data, number)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReaderFrom(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
f := From1(GoFunction)
|
|
||||||
|
|
||||||
result := f("input")(ctx)
|
|
||||||
|
|
||||||
assert.Equal(t, result(), "INPUT")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func MyFinalResult(left, right string) string {
|
|
||||||
return fmt.Sprintf("%s-%s", left, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadersFrom(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
f1 := From1(GoFunction)
|
|
||||||
f2 := From2(GoIntFunction)
|
|
||||||
|
|
||||||
result1 := f1("input")(ctx)
|
|
||||||
result2 := f2("input", 10)(ctx)
|
|
||||||
|
|
||||||
result3 := MyFinalResult(result1(), result2())
|
|
||||||
|
|
||||||
h := F.Pipe1(
|
|
||||||
SequenceT2(f1("input"), f2("input", 10)),
|
|
||||||
Map(T.Tupled2(MyFinalResult)),
|
|
||||||
)
|
|
||||||
|
|
||||||
composedResult := h(ctx)
|
|
||||||
|
|
||||||
assert.Equal(t, result1(), "INPUT")
|
|
||||||
assert.Equal(t, result2(), "input: 10")
|
|
||||||
assert.Equal(t, result3, "INPUT-input: 10")
|
|
||||||
|
|
||||||
assert.Equal(t, composedResult(), "INPUT-input: 10")
|
|
||||||
|
|
||||||
}
|
|
@@ -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 readerio
|
|
||||||
|
|
||||||
import (
|
|
||||||
R "github.com/IBM/fp-go/readerio/generic"
|
|
||||||
T "github.com/IBM/fp-go/tuple"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SequenceT converts n inputs of higher kinded types into a higher kinded types of n strongly typed values, represented as a tuple
|
|
||||||
|
|
||||||
func SequenceT1[A any](a ReaderIO[A]) ReaderIO[T.Tuple1[A]] {
|
|
||||||
return R.SequenceT1[
|
|
||||||
ReaderIO[A],
|
|
||||||
ReaderIO[T.Tuple1[A]],
|
|
||||||
](a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SequenceT2[A, B any](a ReaderIO[A], b ReaderIO[B]) ReaderIO[T.Tuple2[A, B]] {
|
|
||||||
return R.SequenceT2[
|
|
||||||
ReaderIO[A],
|
|
||||||
ReaderIO[B],
|
|
||||||
ReaderIO[T.Tuple2[A, B]],
|
|
||||||
](a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SequenceT3[A, B, C any](a ReaderIO[A], b ReaderIO[B], c ReaderIO[C]) ReaderIO[T.Tuple3[A, B, C]] {
|
|
||||||
return R.SequenceT3[
|
|
||||||
ReaderIO[A],
|
|
||||||
ReaderIO[B],
|
|
||||||
ReaderIO[C],
|
|
||||||
ReaderIO[T.Tuple3[A, B, C]],
|
|
||||||
](a, b, c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SequenceT4[A, B, C, D any](a ReaderIO[A], b ReaderIO[B], c ReaderIO[C], d ReaderIO[D]) ReaderIO[T.Tuple4[A, B, C, D]] {
|
|
||||||
return R.SequenceT4[
|
|
||||||
ReaderIO[A],
|
|
||||||
ReaderIO[B],
|
|
||||||
ReaderIO[C],
|
|
||||||
ReaderIO[D],
|
|
||||||
ReaderIO[T.Tuple4[A, B, C, D]],
|
|
||||||
](a, b, c, d)
|
|
||||||
}
|
|
37
context/readerioeither/bracket.go
Normal file
37
context/readerioeither/bracket.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// 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"
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||||
|
// whether the body action returns and error or not.
|
||||||
|
func Bracket[
|
||||||
|
A, B, ANY any](
|
||||||
|
|
||||||
|
acquire ReaderIOEither[A],
|
||||||
|
use func(A) ReaderIOEither[B],
|
||||||
|
release func(A, E.Either[error, B]) ReaderIOEither[ANY],
|
||||||
|
) ReaderIOEither[B] {
|
||||||
|
return G.Bracket[ReaderIOEither[A], ReaderIOEither[B], ReaderIOEither[ANY]](
|
||||||
|
acquire,
|
||||||
|
use,
|
||||||
|
release,
|
||||||
|
)
|
||||||
|
}
|
@@ -19,9 +19,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
RIO "github.com/IBM/fp-go/context/readerio"
|
|
||||||
R "github.com/IBM/fp-go/context/readerioeither"
|
R "github.com/IBM/fp-go/context/readerioeither"
|
||||||
"github.com/IBM/fp-go/errors"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
IO "github.com/IBM/fp-go/io"
|
IO "github.com/IBM/fp-go/io"
|
||||||
J "github.com/IBM/fp-go/json"
|
J "github.com/IBM/fp-go/json"
|
||||||
@@ -37,20 +35,17 @@ func getData(r RecordType) string {
|
|||||||
|
|
||||||
func ExampleReadFile() {
|
func ExampleReadFile() {
|
||||||
|
|
||||||
data := F.Pipe4(
|
data := F.Pipe3(
|
||||||
ReadFile("./data/file.json"),
|
ReadFile("./data/file.json"),
|
||||||
R.ChainEitherK(J.Unmarshal[RecordType]),
|
R.ChainEitherK(J.Unmarshal[RecordType]),
|
||||||
R.ChainFirstIOK(IO.Logf[RecordType]("Log: %v")),
|
R.ChainFirstIOK(IO.Logf[RecordType]("Log: %v")),
|
||||||
R.Map(getData),
|
R.Map(getData),
|
||||||
R.GetOrElse(F.Flow2(
|
|
||||||
errors.ToString,
|
|
||||||
RIO.Of[string],
|
|
||||||
)),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
result := data(context.Background())
|
result := data(context.Background())
|
||||||
|
|
||||||
fmt.Println(result())
|
fmt.Println(result())
|
||||||
|
|
||||||
// Output: Carsten
|
// Output:
|
||||||
|
// Right[<nil>, string](Carsten)
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@ package readerioeither
|
|||||||
|
|
||||||
// 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-09-12 13:44:14.1022311 +0200 CEST m=+0.017763401
|
// 2023-10-23 08:30:39.012572 +0200 CEST m=+0.008846101
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
53
context/readerioeither/generic/bracket.go
Normal file
53
context/readerioeither/generic/bracket.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
G "github.com/IBM/fp-go/internal/bracket"
|
||||||
|
I "github.com/IBM/fp-go/readerio/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||||
|
// whether the body action returns and error or not.
|
||||||
|
func Bracket[
|
||||||
|
GA ~func(context.Context) TA,
|
||||||
|
GB ~func(context.Context) TB,
|
||||||
|
GANY ~func(context.Context) TANY,
|
||||||
|
|
||||||
|
TA ~func() E.Either[error, A],
|
||||||
|
TB ~func() E.Either[error, B],
|
||||||
|
TANY ~func() E.Either[error, ANY],
|
||||||
|
|
||||||
|
A, B, ANY any](
|
||||||
|
|
||||||
|
acquire GA,
|
||||||
|
use func(A) GB,
|
||||||
|
release func(A, E.Either[error, B]) GANY,
|
||||||
|
) GB {
|
||||||
|
return G.Bracket[GA, GB, GANY, E.Either[error, B], A, B](
|
||||||
|
I.Of[GB, TB, context.Context, E.Either[error, B]],
|
||||||
|
MonadChain[GA, GB, TA, TB, A, B],
|
||||||
|
I.MonadChain[GB, GB, TB, TB, context.Context, E.Either[error, B], E.Either[error, B]],
|
||||||
|
MonadChain[GANY, GB, TANY, TB, ANY, B],
|
||||||
|
|
||||||
|
acquire,
|
||||||
|
use,
|
||||||
|
release,
|
||||||
|
)
|
||||||
|
}
|
@@ -2,7 +2,7 @@ package generic
|
|||||||
|
|
||||||
// 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-09-12 13:44:14.1036885 +0200 CEST m=+0.019220801
|
// 2023-10-23 08:30:39.012572 +0200 CEST m=+0.008846101
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@@ -432,10 +432,10 @@ func FromIOEither[
|
|||||||
|
|
||||||
func FromIO[
|
func FromIO[
|
||||||
GRA ~func(context.Context) GIOA,
|
GRA ~func(context.Context) GIOA,
|
||||||
GIOA ~func() E.Either[error, A],
|
|
||||||
|
|
||||||
GIOB ~func() A,
|
GIOB ~func() A,
|
||||||
|
|
||||||
|
GIOA ~func() E.Either[error, A],
|
||||||
|
|
||||||
A any](t GIOB) GRA {
|
A any](t GIOB) GRA {
|
||||||
return RIE.FromIO[GRA](t)
|
return RIE.FromIO[GRA](t)
|
||||||
}
|
}
|
||||||
@@ -571,7 +571,7 @@ func Timer[
|
|||||||
](delay time.Duration) GRA {
|
](delay time.Duration) GRA {
|
||||||
return F.Pipe2(
|
return F.Pipe2(
|
||||||
IO.Now[func() time.Time](),
|
IO.Now[func() time.Time](),
|
||||||
FromIO[GRA, GIOA, func() time.Time],
|
FromIO[GRA, func() time.Time],
|
||||||
Delay[GRA](delay),
|
Delay[GRA](delay),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
44
context/readerioeither/generic/sync.go
Normal file
44
context/readerioeither/generic/sync.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
IO "github.com/IBM/fp-go/io/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[
|
||||||
|
GRA ~func(context.Context) GIOA,
|
||||||
|
GIOA ~func() E.Either[error, A],
|
||||||
|
GRCANCEL ~func(context.Context) GIOCANCEL,
|
||||||
|
GIOCANCEL ~func() E.Either[error, context.CancelFunc],
|
||||||
|
A any](lock GRCANCEL) func(fa GRA) GRA {
|
||||||
|
|
||||||
|
type GRANY func(ctx context.Context) func() E.Either[error, any]
|
||||||
|
type IOANY func() any
|
||||||
|
|
||||||
|
return F.Flow2(
|
||||||
|
F.Constant1[context.CancelFunc, GRA],
|
||||||
|
WithResource[GRA, GRCANCEL, GRANY](lock, F.Flow2(
|
||||||
|
IO.FromImpure[IOANY, context.CancelFunc],
|
||||||
|
FromIO[GRANY, IOANY],
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
}
|
@@ -19,8 +19,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
R "github.com/IBM/fp-go/context/reader"
|
|
||||||
RIO "github.com/IBM/fp-go/context/readerio"
|
|
||||||
G "github.com/IBM/fp-go/context/readerioeither/generic"
|
G "github.com/IBM/fp-go/context/readerioeither/generic"
|
||||||
ET "github.com/IBM/fp-go/either"
|
ET "github.com/IBM/fp-go/either"
|
||||||
IO "github.com/IBM/fp-go/io"
|
IO "github.com/IBM/fp-go/io"
|
||||||
@@ -33,14 +31,6 @@ func FromEither[A any](e ET.Either[error, A]) ReaderIOEither[A] {
|
|||||||
return G.FromEither[ReaderIOEither[A]](e)
|
return G.FromEither[ReaderIOEither[A]](e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RightReader[A any](r R.Reader[A]) ReaderIOEither[A] {
|
|
||||||
return G.RightReader[ReaderIOEither[A]](r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LeftReader[A any](l R.Reader[error]) ReaderIOEither[A] {
|
|
||||||
return G.LeftReader[ReaderIOEither[A]](l)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Left[A any](l error) ReaderIOEither[A] {
|
func Left[A any](l error) ReaderIOEither[A] {
|
||||||
return G.Left[ReaderIOEither[A]](l)
|
return G.Left[ReaderIOEither[A]](l)
|
||||||
}
|
}
|
||||||
@@ -49,10 +39,6 @@ func Right[A any](r A) ReaderIOEither[A] {
|
|||||||
return G.Right[ReaderIOEither[A]](r)
|
return G.Right[ReaderIOEither[A]](r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FromReader[A any](r R.Reader[A]) ReaderIOEither[A] {
|
|
||||||
return G.FromReader[ReaderIOEither[A]](r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadMap[A, B any](fa ReaderIOEither[A], f func(A) B) ReaderIOEither[B] {
|
func MonadMap[A, B any](fa ReaderIOEither[A], f func(A) B) ReaderIOEither[B] {
|
||||||
return G.MonadMap[ReaderIOEither[A], ReaderIOEither[B]](fa, f)
|
return G.MonadMap[ReaderIOEither[A], ReaderIOEither[B]](fa, f)
|
||||||
}
|
}
|
||||||
@@ -103,30 +89,14 @@ func FromPredicate[A any](pred func(A) bool, onFalse func(A) error) func(A) Read
|
|||||||
return G.FromPredicate[ReaderIOEither[A]](pred, onFalse)
|
return G.FromPredicate[ReaderIOEither[A]](pred, onFalse)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fold[A, B any](onLeft func(error) RIO.ReaderIO[B], onRight func(A) RIO.ReaderIO[B]) func(ReaderIOEither[A]) RIO.ReaderIO[B] {
|
|
||||||
return G.Fold[RIO.ReaderIO[B], ReaderIOEither[A]](onLeft, onRight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetOrElse[A any](onLeft func(error) RIO.ReaderIO[A]) func(ReaderIOEither[A]) RIO.ReaderIO[A] {
|
|
||||||
return G.GetOrElse[RIO.ReaderIO[A], ReaderIOEither[A]](onLeft)
|
|
||||||
}
|
|
||||||
|
|
||||||
func OrElse[A any](onLeft func(error) ReaderIOEither[A]) func(ReaderIOEither[A]) ReaderIOEither[A] {
|
func OrElse[A any](onLeft func(error) ReaderIOEither[A]) func(ReaderIOEither[A]) ReaderIOEither[A] {
|
||||||
return G.OrElse[ReaderIOEither[A]](onLeft)
|
return G.OrElse[ReaderIOEither[A]](onLeft)
|
||||||
}
|
}
|
||||||
|
|
||||||
func OrLeft[A any](onLeft func(error) RIO.ReaderIO[error]) func(ReaderIOEither[A]) ReaderIOEither[A] {
|
|
||||||
return G.OrLeft[ReaderIOEither[A], RIO.ReaderIO[error]](onLeft)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Ask() ReaderIOEither[context.Context] {
|
func Ask() ReaderIOEither[context.Context] {
|
||||||
return G.Ask[ReaderIOEither[context.Context]]()
|
return G.Ask[ReaderIOEither[context.Context]]()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Asks[A any](r R.Reader[A]) ReaderIOEither[A] {
|
|
||||||
return G.Asks[ReaderIOEither[A]](r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChainEitherK[A, B any](ma ReaderIOEither[A], f func(A) ET.Either[error, B]) ReaderIOEither[B] {
|
func MonadChainEitherK[A, B any](ma ReaderIOEither[A], f func(A) ET.Either[error, B]) ReaderIOEither[B] {
|
||||||
return G.MonadChainEitherK[ReaderIOEither[A], ReaderIOEither[B]](ma, f)
|
return G.MonadChainEitherK[ReaderIOEither[A], ReaderIOEither[B]](ma, f)
|
||||||
}
|
}
|
||||||
@@ -164,14 +134,6 @@ func Never[A any]() ReaderIOEither[A] {
|
|||||||
return G.Never[ReaderIOEither[A]]()
|
return G.Never[ReaderIOEither[A]]()
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadChainReaderIOK[A, B any](ma ReaderIOEither[A], f func(A) RIO.ReaderIO[B]) ReaderIOEither[B] {
|
|
||||||
return G.MonadChainReaderIOK[ReaderIOEither[B], ReaderIOEither[A]](ma, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ChainReaderIOK[A, B any](f func(A) RIO.ReaderIO[B]) func(ma ReaderIOEither[A]) ReaderIOEither[B] {
|
|
||||||
return G.ChainReaderIOK[ReaderIOEither[B], ReaderIOEither[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadChainIOK[A, B any](ma ReaderIOEither[A], f func(A) IO.IO[B]) ReaderIOEither[B] {
|
func MonadChainIOK[A, B any](ma ReaderIOEither[A], f func(A) IO.IO[B]) ReaderIOEither[B] {
|
||||||
return G.MonadChainIOK[ReaderIOEither[B], ReaderIOEither[A]](ma, f)
|
return G.MonadChainIOK[ReaderIOEither[B], ReaderIOEither[A]](ma, f)
|
||||||
}
|
}
|
||||||
@@ -235,22 +197,6 @@ func Flatten[
|
|||||||
return G.Flatten[ReaderIOEither[ReaderIOEither[A]]](rdr)
|
return G.Flatten[ReaderIOEither[ReaderIOEither[A]]](rdr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonadFromReaderIO[A any](a A, f func(A) RIO.ReaderIO[A]) ReaderIOEither[A] {
|
|
||||||
return G.MonadFromReaderIO[ReaderIOEither[A]](a, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FromReaderIO[A any](f func(A) RIO.ReaderIO[A]) func(A) ReaderIOEither[A] {
|
|
||||||
return G.FromReaderIO[ReaderIOEither[A]](f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RightReaderIO[A any](ma RIO.ReaderIO[A]) ReaderIOEither[A] {
|
|
||||||
return G.RightReaderIO[ReaderIOEither[A]](ma)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LeftReaderIO[A any](ma RIO.ReaderIO[error]) ReaderIOEither[A] {
|
|
||||||
return G.LeftReaderIO[ReaderIOEither[A]](ma)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MonadFlap[B, A any](fab ReaderIOEither[func(A) B], a A) ReaderIOEither[B] {
|
func MonadFlap[B, A any](fab ReaderIOEither[func(A) B], a A) ReaderIOEither[B] {
|
||||||
return G.MonadFlap[ReaderIOEither[func(A) B], ReaderIOEither[B]](fab, a)
|
return G.MonadFlap[ReaderIOEither[func(A) B], ReaderIOEither[B]](fab, a)
|
||||||
}
|
}
|
||||||
|
@@ -13,14 +13,15 @@
|
|||||||
// 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 reader implements a specialization of the Reader monad assuming a golang context as the context of the monad
|
package readerioeither
|
||||||
package reader
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
R "github.com/IBM/fp-go/reader"
|
G "github.com/IBM/fp-go/context/readerioeither/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reader is a specialization of the Reader monad assuming a golang context as the context of the monad
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
type Reader[A any] R.Reader[context.Context, A]
|
func WithLock[A any](lock ReaderIOEither[context.CancelFunc]) func(fa ReaderIOEither[A]) ReaderIOEither[A] {
|
||||||
|
return G.WithLock[ReaderIOEither[A]](lock)
|
||||||
|
}
|
@@ -46,12 +46,12 @@ func (s Either[E, A]) Format(f fmt.State, c rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLeft tests if the either is a left value. Rather use [Fold] if you need to access the values. Inverse is [IsRight].
|
// IsLeft tests if the [Either] is a left value. Rather use [Fold] if you need to access the values. Inverse is [IsRight].
|
||||||
func IsLeft[E, A any](val Either[E, A]) bool {
|
func IsLeft[E, A any](val Either[E, A]) bool {
|
||||||
return val.isLeft
|
return val.isLeft
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLeft tests if the either is a right value. Rather use [Fold] if you need to access the values. Inverse is [IsLeft].
|
// IsLeft tests if the [Either] is a right value. Rather use [Fold] if you need to access the values. Inverse is [IsLeft].
|
||||||
func IsRight[E, A any](val Either[E, A]) bool {
|
func IsRight[E, A any](val Either[E, A]) bool {
|
||||||
return !val.isLeft
|
return !val.isLeft
|
||||||
}
|
}
|
||||||
|
@@ -120,16 +120,15 @@ func Flatten[E, A any](mma Either[E, Either[E, A]]) Either[E, A] {
|
|||||||
return MonadChain(mma, F.Identity[Either[E, A]])
|
return MonadChain(mma, F.Identity[Either[E, A]])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TryCatch[FA ~func() (A, error), FE func(error) E, E, A any](f FA, onThrow FE) Either[E, A] {
|
func TryCatch[FE func(error) E, E, A any](val A, err error, onThrow FE) Either[E, A] {
|
||||||
val, err := f()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return F.Pipe2(err, onThrow, Left[A, E])
|
return F.Pipe2(err, onThrow, Left[A, E])
|
||||||
}
|
}
|
||||||
return F.Pipe1(val, Right[E, A])
|
return F.Pipe1(val, Right[E, A])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TryCatchError[F ~func() (A, error), A any](f F) Either[error, A] {
|
func TryCatchError[A any](val A, err error) Either[error, A] {
|
||||||
return TryCatch(f, E.IdentityError)
|
return TryCatch(val, err, E.IdentityError)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sequence2[E, T1, T2, R any](f func(T1, T2) Either[E, R]) func(Either[E, T1], Either[E, T2]) Either[E, R] {
|
func Sequence2[E, T1, T2, R any](f func(T1, T2) Either[E, R]) func(Either[E, T1], Either[E, T2]) Either[E, R] {
|
||||||
@@ -154,9 +153,7 @@ func ToOption[E, A any](ma Either[E, A]) O.Option[A] {
|
|||||||
|
|
||||||
func FromError[A any](f func(a A) error) func(A) Either[error, A] {
|
func FromError[A any](f func(a A) error) func(A) Either[error, A] {
|
||||||
return func(a A) Either[error, A] {
|
return func(a A) Either[error, A] {
|
||||||
return TryCatchError(func() (A, error) {
|
return TryCatchError(a, f(a))
|
||||||
return a, f(a)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,7 +32,5 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func command(name string, args []string, in []byte) E.Either[error, exec.CommandOutput] {
|
func command(name string, args []string, in []byte) E.Either[error, exec.CommandOutput] {
|
||||||
return E.TryCatchError(func() (exec.CommandOutput, error) {
|
return E.TryCatchError(GE.Exec(context.Background(), name, args, in))
|
||||||
return GE.Exec(context.Background(), name, args, in)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@@ -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-09-12 13:44:15.6356542 +0200 CEST m=+0.009418901
|
// 2023-10-23 08:30:40.410373 +0200 CEST m=+0.010337601
|
||||||
|
|
||||||
package either
|
package either
|
||||||
|
|
||||||
@@ -13,9 +13,7 @@ import (
|
|||||||
// The inverse function is [Uneitherize0]
|
// The inverse function is [Uneitherize0]
|
||||||
func Eitherize0[F ~func() (R, error), R any](f F) func() Either[error, R] {
|
func Eitherize0[F ~func() (R, error), R any](f F) func() Either[error, R] {
|
||||||
return func() Either[error, R] {
|
return func() Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f())
|
||||||
return f()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,9 +29,7 @@ func Uneitherize0[F ~func() Either[error, R], R any](f F) func() (R, error) {
|
|||||||
// The inverse function is [Uneitherize1]
|
// The inverse function is [Uneitherize1]
|
||||||
func Eitherize1[F ~func(T0) (R, error), T0, R any](f F) func(T0) Either[error, R] {
|
func Eitherize1[F ~func(T0) (R, error), T0, R any](f F) func(T0) Either[error, R] {
|
||||||
return func(t0 T0) Either[error, R] {
|
return func(t0 T0) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0))
|
||||||
return f(t0)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,9 +72,7 @@ func TraverseTuple1[F1 ~func(A1) Either[E, T1], E, A1, T1 any](f1 F1) func(T.Tup
|
|||||||
// The inverse function is [Uneitherize2]
|
// The inverse function is [Uneitherize2]
|
||||||
func Eitherize2[F ~func(T0, T1) (R, error), T0, T1, R any](f F) func(T0, T1) Either[error, R] {
|
func Eitherize2[F ~func(T0, T1) (R, error), T0, T1, R any](f F) func(T0, T1) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1) Either[error, R] {
|
return func(t0 T0, t1 T1) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1))
|
||||||
return f(t0, t1)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,9 +120,7 @@ func TraverseTuple2[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], E, A
|
|||||||
// The inverse function is [Uneitherize3]
|
// The inverse function is [Uneitherize3]
|
||||||
func Eitherize3[F ~func(T0, T1, T2) (R, error), T0, T1, T2, R any](f F) func(T0, T1, T2) Either[error, R] {
|
func Eitherize3[F ~func(T0, T1, T2) (R, error), T0, T1, T2, R any](f F) func(T0, T1, T2) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1, t2 T2) Either[error, R] {
|
return func(t0 T0, t1 T1, t2 T2) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1, t2))
|
||||||
return f(t0, t1, t2)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,9 +173,7 @@ func TraverseTuple3[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~
|
|||||||
// The inverse function is [Uneitherize4]
|
// The inverse function is [Uneitherize4]
|
||||||
func Eitherize4[F ~func(T0, T1, T2, T3) (R, error), T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) Either[error, R] {
|
func Eitherize4[F ~func(T0, T1, T2, T3) (R, error), T0, T1, T2, T3, R any](f F) func(T0, T1, T2, T3) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3) Either[error, R] {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1, t2, t3))
|
||||||
return f(t0, t1, t2, t3)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,9 +231,7 @@ func TraverseTuple4[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~
|
|||||||
// The inverse function is [Uneitherize5]
|
// The inverse function is [Uneitherize5]
|
||||||
func Eitherize5[F ~func(T0, T1, T2, T3, T4) (R, error), T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) Either[error, R] {
|
func Eitherize5[F ~func(T0, T1, T2, T3, T4) (R, error), T0, T1, T2, T3, T4, R any](f F) func(T0, T1, T2, T3, T4) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) Either[error, R] {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1, t2, t3, t4))
|
||||||
return f(t0, t1, t2, t3, t4)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,9 +294,7 @@ func TraverseTuple5[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~
|
|||||||
// The inverse function is [Uneitherize6]
|
// The inverse function is [Uneitherize6]
|
||||||
func Eitherize6[F ~func(T0, T1, T2, T3, T4, T5) (R, error), T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) Either[error, R] {
|
func Eitherize6[F ~func(T0, T1, T2, T3, T4, T5) (R, error), T0, T1, T2, T3, T4, T5, R any](f F) func(T0, T1, T2, T3, T4, T5) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) Either[error, R] {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1, t2, t3, t4, t5))
|
||||||
return f(t0, t1, t2, t3, t4, t5)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,9 +362,7 @@ func TraverseTuple6[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~
|
|||||||
// The inverse function is [Uneitherize7]
|
// The inverse function is [Uneitherize7]
|
||||||
func Eitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) (R, error), T0, T1, T2, T3, T4, T5, T6, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) Either[error, R] {
|
func Eitherize7[F ~func(T0, T1, T2, T3, T4, T5, T6) (R, error), T0, T1, T2, T3, T4, T5, T6, R any](f F) func(T0, T1, T2, T3, T4, T5, T6) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) Either[error, R] {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6))
|
||||||
return f(t0, t1, t2, t3, t4, t5, t6)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,9 +435,7 @@ func TraverseTuple7[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~
|
|||||||
// The inverse function is [Uneitherize8]
|
// The inverse function is [Uneitherize8]
|
||||||
func Eitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) Either[error, R] {
|
func Eitherize8[F ~func(T0, T1, T2, T3, T4, T5, T6, T7) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) Either[error, R] {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6, t7))
|
||||||
return f(t0, t1, t2, t3, t4, t5, t6, t7)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,9 +513,7 @@ func TraverseTuple8[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~
|
|||||||
// The inverse function is [Uneitherize9]
|
// The inverse function is [Uneitherize9]
|
||||||
func Eitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Either[error, R] {
|
func Eitherize9[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) Either[error, R] {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8))
|
||||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,9 +596,7 @@ func TraverseTuple9[F1 ~func(A1) Either[E, T1], F2 ~func(A2) Either[E, T2], F3 ~
|
|||||||
// The inverse function is [Uneitherize10]
|
// The inverse function is [Uneitherize10]
|
||||||
func Eitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Either[error, R] {
|
func Eitherize10[F ~func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) Either[error, R] {
|
||||||
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) Either[error, R] {
|
return func(t0 T0, t1 T1, t2 T2, t3 T3, t4 T4, t5 T5, t6 T6, t7 T7, t8 T8, t9 T9) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9))
|
||||||
return f(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,17 +35,13 @@ var (
|
|||||||
func bodyRequest(method string) func(string) func([]byte) E.Either[error, *http.Request] {
|
func bodyRequest(method string) func(string) func([]byte) E.Either[error, *http.Request] {
|
||||||
return func(url string) func([]byte) E.Either[error, *http.Request] {
|
return func(url string) func([]byte) E.Either[error, *http.Request] {
|
||||||
return func(body []byte) E.Either[error, *http.Request] {
|
return func(body []byte) E.Either[error, *http.Request] {
|
||||||
return E.TryCatchError(func() (*http.Request, error) {
|
return E.TryCatchError(http.NewRequest(method, url, bytes.NewReader(body)))
|
||||||
return http.NewRequest(method, url, bytes.NewReader(body))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func noBodyRequest(method string) func(string) E.Either[error, *http.Request] {
|
func noBodyRequest(method string) func(string) E.Either[error, *http.Request] {
|
||||||
return func(url string) E.Either[error, *http.Request] {
|
return func(url string) E.Either[error, *http.Request] {
|
||||||
return E.TryCatchError(func() (*http.Request, error) {
|
return E.TryCatchError(http.NewRequest(method, url, nil))
|
||||||
return http.NewRequest(method, url, nil)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,20 +25,14 @@ import (
|
|||||||
|
|
||||||
func TestWithResource(t *testing.T) {
|
func TestWithResource(t *testing.T) {
|
||||||
onCreate := func() Either[error, *os.File] {
|
onCreate := func() Either[error, *os.File] {
|
||||||
return TryCatchError(func() (*os.File, error) {
|
return TryCatchError(os.CreateTemp("", "*"))
|
||||||
return os.CreateTemp("", "*")
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
onDelete := F.Flow2(
|
onDelete := F.Flow2(
|
||||||
func(f *os.File) Either[error, string] {
|
func(f *os.File) Either[error, string] {
|
||||||
return TryCatchError(func() (string, error) {
|
return TryCatchError(f.Name(), f.Close())
|
||||||
return f.Name(), f.Close()
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
Chain(func(name string) Either[error, any] {
|
Chain(func(name string) Either[error, any] {
|
||||||
return TryCatchError(func() (any, error) {
|
return TryCatchError(any(name), os.Remove(name))
|
||||||
return name, os.Remove(name)
|
|
||||||
})
|
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -17,80 +17,60 @@ package either
|
|||||||
|
|
||||||
func Variadic0[V, R any](f func([]V) (R, error)) func(...V) Either[error, R] {
|
func Variadic0[V, R any](f func([]V) (R, error)) func(...V) Either[error, R] {
|
||||||
return func(v ...V) Either[error, R] {
|
return func(v ...V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(v))
|
||||||
return f(v)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Variadic1[T1, V, R any](f func(T1, []V) (R, error)) func(T1, ...V) Either[error, R] {
|
func Variadic1[T1, V, R any](f func(T1, []V) (R, error)) func(T1, ...V) Either[error, R] {
|
||||||
return func(t1 T1, v ...V) Either[error, R] {
|
return func(t1 T1, v ...V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t1, v))
|
||||||
return f(t1, v)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Variadic2[T1, T2, V, R any](f func(T1, T2, []V) (R, error)) func(T1, T2, ...V) Either[error, R] {
|
func Variadic2[T1, T2, V, R any](f func(T1, T2, []V) (R, error)) func(T1, T2, ...V) Either[error, R] {
|
||||||
return func(t1 T1, t2 T2, v ...V) Either[error, R] {
|
return func(t1 T1, t2 T2, v ...V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t1, t2, v))
|
||||||
return f(t1, t2, v)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Variadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, []V) (R, error)) func(T1, T2, T3, ...V) Either[error, R] {
|
func Variadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, []V) (R, error)) func(T1, T2, T3, ...V) Either[error, R] {
|
||||||
return func(t1 T1, t2 T2, t3 T3, v ...V) Either[error, R] {
|
return func(t1 T1, t2 T2, t3 T3, v ...V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t1, t2, t3, v))
|
||||||
return f(t1, t2, t3, v)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Variadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, []V) (R, error)) func(T1, T2, T3, T4, ...V) Either[error, R] {
|
func Variadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, []V) (R, error)) func(T1, T2, T3, T4, ...V) Either[error, R] {
|
||||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, v ...V) Either[error, R] {
|
return func(t1 T1, t2 T2, t3 T3, t4 T4, v ...V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t1, t2, t3, t4, v))
|
||||||
return f(t1, t2, t3, t4, v)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unvariadic0[V, R any](f func(...V) (R, error)) func([]V) Either[error, R] {
|
func Unvariadic0[V, R any](f func(...V) (R, error)) func([]V) Either[error, R] {
|
||||||
return func(v []V) Either[error, R] {
|
return func(v []V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(v...))
|
||||||
return f(v...)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unvariadic1[T1, V, R any](f func(T1, ...V) (R, error)) func(T1, []V) Either[error, R] {
|
func Unvariadic1[T1, V, R any](f func(T1, ...V) (R, error)) func(T1, []V) Either[error, R] {
|
||||||
return func(t1 T1, v []V) Either[error, R] {
|
return func(t1 T1, v []V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t1, v...))
|
||||||
return f(t1, v...)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unvariadic2[T1, T2, V, R any](f func(T1, T2, ...V) (R, error)) func(T1, T2, []V) Either[error, R] {
|
func Unvariadic2[T1, T2, V, R any](f func(T1, T2, ...V) (R, error)) func(T1, T2, []V) Either[error, R] {
|
||||||
return func(t1 T1, t2 T2, v []V) Either[error, R] {
|
return func(t1 T1, t2 T2, v []V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t1, t2, v...))
|
||||||
return f(t1, t2, v...)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unvariadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, ...V) (R, error)) func(T1, T2, T3, []V) Either[error, R] {
|
func Unvariadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, ...V) (R, error)) func(T1, T2, T3, []V) Either[error, R] {
|
||||||
return func(t1 T1, t2 T2, t3 T3, v []V) Either[error, R] {
|
return func(t1 T1, t2 T2, t3 T3, v []V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t1, t2, t3, v...))
|
||||||
return f(t1, t2, t3, v...)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unvariadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, ...V) (R, error)) func(T1, T2, T3, T4, []V) Either[error, R] {
|
func Unvariadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, ...V) (R, error)) func(T1, T2, T3, T4, []V) Either[error, R] {
|
||||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, v []V) Either[error, R] {
|
return func(t1 T1, t2 T2, t3 T3, t4 T4, v []V) Either[error, R] {
|
||||||
return TryCatchError(func() (R, error) {
|
return TryCatchError(f(t1, t2, t3, t4, v...))
|
||||||
return f(t1, t2, t3, t4, v...)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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-09-12 13:44:23.4226437 +0200 CEST m=+0.011841001
|
// 2023-10-23 08:30:44.6474482 +0200 CEST m=+0.150851901
|
||||||
|
|
||||||
package function
|
package function
|
||||||
|
|
||||||
|
@@ -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-09-12 13:44:17.0002767 +0200 CEST m=+0.008233101
|
// 2023-10-23 08:30:41.7972101 +0200 CEST m=+0.008029101
|
||||||
|
|
||||||
package function
|
package function
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||||
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
|
||||||
|
4
go.sum
4
go.sum
@@ -1,5 +1,5 @@
|
|||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
@@ -68,10 +68,8 @@ const (
|
|||||||
|
|
||||||
// ParseMediaType parses a media type into a tuple
|
// ParseMediaType parses a media type into a tuple
|
||||||
func ParseMediaType(mediaType string) E.Either[error, ParsedMediaType] {
|
func ParseMediaType(mediaType string) E.Either[error, ParsedMediaType] {
|
||||||
return E.TryCatchError(func() (ParsedMediaType, error) {
|
m, p, err := mime.ParseMediaType(mediaType)
|
||||||
m, p, err := mime.ParseMediaType(mediaType)
|
return E.TryCatchError(T.MakeTuple2(m, p), err)
|
||||||
return T.MakeTuple2(m, p), err
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHeader(resp *H.Response) H.Header {
|
func GetHeader(resp *H.Response) H.Header {
|
||||||
|
@@ -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-09-12 13:44:24.9409324 +0200 CEST m=+0.008573601
|
// 2023-10-23 08:30:50.5492271 +0200 CEST m=+0.023274501
|
||||||
|
|
||||||
package identity
|
package identity
|
||||||
|
|
||||||
|
@@ -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-09-12 13:44:26.2499883 +0200 CEST m=+0.007601301
|
// 2023-10-23 08:30:54.1909432 +0200 CEST m=+0.014252201
|
||||||
|
|
||||||
package apply
|
package apply
|
||||||
|
|
||||||
|
@@ -51,6 +51,24 @@ func ReduceWithIndex[GA ~[]A, A, B any](fa GA, f func(int, B, A) B, initial B) B
|
|||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReduceRight[GA ~[]A, A, B any](fa GA, f func(A, B) B, initial B) B {
|
||||||
|
current := initial
|
||||||
|
count := len(fa)
|
||||||
|
for i := count - 1; i >= 0; i-- {
|
||||||
|
current = f(fa[i], current)
|
||||||
|
}
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReduceRightWithIndex[GA ~[]A, A, B any](fa GA, f func(int, A, B) B, initial B) B {
|
||||||
|
current := initial
|
||||||
|
count := len(fa)
|
||||||
|
for i := count - 1; i >= 0; i-- {
|
||||||
|
current = f(i, fa[i], current)
|
||||||
|
}
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
func Append[GA ~[]A, A any](as GA, a A) GA {
|
func Append[GA ~[]A, A any](as GA, a A) GA {
|
||||||
return append(as, a)
|
return append(as, a)
|
||||||
}
|
}
|
||||||
|
@@ -46,9 +46,7 @@ func MakeReader(ctx context.Context, rdr io.Reader) io.Reader {
|
|||||||
|
|
||||||
// ReadAll reads the content of a reader and allows it to be canceled
|
// ReadAll reads the content of a reader and allows it to be canceled
|
||||||
func ReadAll(ctx context.Context, rdr io.Reader) E.Either[error, []byte] {
|
func ReadAll(ctx context.Context, rdr io.Reader) E.Either[error, []byte] {
|
||||||
return E.TryCatchError(func() ([]byte, error) {
|
var buffer bytes.Buffer
|
||||||
var buffer bytes.Buffer
|
_, err := io.Copy(&buffer, MakeReader(ctx, rdr))
|
||||||
_, err := io.Copy(&buffer, MakeReader(ctx, rdr))
|
return E.TryCatchError(buffer.Bytes(), err)
|
||||||
return buffer.Bytes(), err
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
30
io/bracket.go
Normal file
30
io/bracket.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||||
|
// whether the body action returns and error or not.
|
||||||
|
func Bracket[A, B, ANY any](
|
||||||
|
acquire IO[A],
|
||||||
|
use func(A) IO[B],
|
||||||
|
release func(A, B) IO[ANY],
|
||||||
|
) IO[B] {
|
||||||
|
return G.Bracket(acquire, use, release)
|
||||||
|
}
|
@@ -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-09-12 13:44:27.9813739 +0200 CEST m=+0.011088001
|
// 2023-10-23 08:30:56.7105551 +0200 CEST m=+0.011255201
|
||||||
|
|
||||||
package io
|
package io
|
||||||
|
|
||||||
|
44
io/generic/bracket.go
Normal file
44
io/generic/bracket.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
// 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 (
|
||||||
|
G "github.com/IBM/fp-go/internal/bracket"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||||
|
// whether the body action returns and error or not.
|
||||||
|
func Bracket[
|
||||||
|
GA ~func() A,
|
||||||
|
GB ~func() B,
|
||||||
|
GANY ~func() ANY,
|
||||||
|
A, B, ANY any](
|
||||||
|
|
||||||
|
acquire GA,
|
||||||
|
use func(A) GB,
|
||||||
|
release func(A, B) GANY,
|
||||||
|
) GB {
|
||||||
|
return G.Bracket[GA, GB, GANY, B, A, B](
|
||||||
|
Of[GB, B],
|
||||||
|
MonadChain[GA, GB, A, B],
|
||||||
|
MonadChain[GB, GB, B, B],
|
||||||
|
MonadChain[GANY, GB, ANY, B],
|
||||||
|
|
||||||
|
acquire,
|
||||||
|
use,
|
||||||
|
release,
|
||||||
|
)
|
||||||
|
}
|
@@ -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-09-12 13:44:27.9813739 +0200 CEST m=+0.011088001
|
// 2023-10-23 08:30:56.7105551 +0200 CEST m=+0.011255201
|
||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
30
io/generic/sync.go
Normal file
30
io/generic/sync.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[GA ~func() A, A any](lock func() context.CancelFunc) func(fa GA) GA {
|
||||||
|
return func(fa GA) GA {
|
||||||
|
return func() A {
|
||||||
|
defer lock()()
|
||||||
|
return fa()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
io/sync.go
Normal file
27
io/sync.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// 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 (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
G "github.com/IBM/fp-go/io/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided [IO] operation in the scope of a lock
|
||||||
|
func WithLock[A any](lock IO[context.CancelFunc]) func(fa IO[A]) IO[A] {
|
||||||
|
return G.WithLock[IO[A]](lock)
|
||||||
|
}
|
@@ -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-09-12 13:44:29.4935658 +0200 CEST m=+0.015377401
|
// 2023-10-23 08:30:58.6457744 +0200 CEST m=+0.080336501
|
||||||
|
|
||||||
package ioeither
|
package ioeither
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ package generic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
ET "github.com/IBM/fp-go/either"
|
ET "github.com/IBM/fp-go/either"
|
||||||
G "github.com/IBM/fp-go/internal/file"
|
G "github.com/IBM/fp-go/internal/bracket"
|
||||||
I "github.com/IBM/fp-go/io/generic"
|
I "github.com/IBM/fp-go/io/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -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-09-12 13:44:29.4935658 +0200 CEST m=+0.015377401
|
// 2023-10-23 08:30:58.6556525 +0200 CEST m=+0.090214601
|
||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@@ -19,7 +19,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
ET "github.com/IBM/fp-go/either"
|
ET "github.com/IBM/fp-go/either"
|
||||||
"github.com/IBM/fp-go/errors"
|
|
||||||
F "github.com/IBM/fp-go/function"
|
F "github.com/IBM/fp-go/function"
|
||||||
C "github.com/IBM/fp-go/internal/chain"
|
C "github.com/IBM/fp-go/internal/chain"
|
||||||
"github.com/IBM/fp-go/internal/eithert"
|
"github.com/IBM/fp-go/internal/eithert"
|
||||||
@@ -184,12 +183,15 @@ func Flatten[GA ~func() ET.Either[E, A], GAA ~func() ET.Either[E, GA], E, A any]
|
|||||||
|
|
||||||
func TryCatch[GA ~func() ET.Either[E, A], E, A any](f func() (A, error), onThrow func(error) E) GA {
|
func TryCatch[GA ~func() ET.Either[E, A], E, A any](f func() (A, error), onThrow func(error) E) GA {
|
||||||
return MakeIO(func() ET.Either[E, A] {
|
return MakeIO(func() ET.Either[E, A] {
|
||||||
return ET.TryCatch(f, onThrow)
|
a, err := f()
|
||||||
|
return ET.TryCatch(a, err, onThrow)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TryCatchError[GA ~func() ET.Either[error, A], A any](f func() (A, error)) GA {
|
func TryCatchError[GA ~func() ET.Either[error, A], A any](f func() (A, error)) GA {
|
||||||
return TryCatch[GA](f, errors.IdentityError)
|
return MakeIO(func() ET.Either[error, A] {
|
||||||
|
return ET.TryCatchError(f())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Memoize computes the value of the provided IO monad lazily but exactly once
|
// Memoize computes the value of the provided IO monad lazily but exactly once
|
||||||
|
28
ioeither/generic/sync.go
Normal file
28
ioeither/generic/sync.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// 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"
|
||||||
|
G "github.com/IBM/fp-go/io/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[GA ~func() ET.Either[E, A], E, A any](lock func() context.CancelFunc) func(fa GA) GA {
|
||||||
|
return G.WithLock[GA](lock)
|
||||||
|
}
|
@@ -63,7 +63,7 @@ func TestRetryHttp(t *testing.T) {
|
|||||||
check := E.Fold(
|
check := E.Fold(
|
||||||
F.Flow2(
|
F.Flow2(
|
||||||
errors.As[*net.DNSError](),
|
errors.As[*net.DNSError](),
|
||||||
O.Fold(F.Constant(false), F.Constant1[*net.DNSError](true)),
|
O.IsSome[*net.DNSError],
|
||||||
),
|
),
|
||||||
F.Constant1[*PostItem](false),
|
F.Constant1[*PostItem](false),
|
||||||
)
|
)
|
||||||
|
@@ -125,10 +125,29 @@ func MonadAp[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEithe
|
|||||||
return G.MonadAp[IOEither[E, B]](mab, ma)
|
return G.MonadAp[IOEither[E, B]](mab, ma)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ap is an alias of [ApPar]
|
||||||
func Ap[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
func Ap[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
||||||
return G.Ap[IOEither[E, B], IOEither[E, func(A) B]](ma)
|
return G.Ap[IOEither[E, B], IOEither[E, func(A) B]](ma)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MonadApPar[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEither[E, B] {
|
||||||
|
return G.MonadApPar[IOEither[E, B]](mab, ma)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApPar applies function and value in parallel
|
||||||
|
func ApPar[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
||||||
|
return G.ApPar[IOEither[E, B], IOEither[E, func(A) B]](ma)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MonadApSeq[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEither[E, B] {
|
||||||
|
return G.MonadApSeq[IOEither[E, B]](mab, ma)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApSeq applies function and value sequentially
|
||||||
|
func ApSeq[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
|
||||||
|
return G.ApSeq[IOEither[E, B], IOEither[E, func(A) B]](ma)
|
||||||
|
}
|
||||||
|
|
||||||
func Flatten[E, A any](mma IOEither[E, IOEither[E, A]]) IOEither[E, A] {
|
func Flatten[E, A any](mma IOEither[E, IOEither[E, A]]) IOEither[E, A] {
|
||||||
return G.Flatten(mma)
|
return G.Flatten(mma)
|
||||||
}
|
}
|
||||||
|
28
ioeither/sync.go
Normal file
28
ioeither/sync.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// 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 (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
IO "github.com/IBM/fp-go/io"
|
||||||
|
G "github.com/IBM/fp-go/ioeither/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[E, A any](lock IO.IO[context.CancelFunc]) func(fa IOEither[E, A]) IOEither[E, A] {
|
||||||
|
return G.WithLock[IOEither[E, A]](lock)
|
||||||
|
}
|
31
iooption/bracket.go
Normal file
31
iooption/bracket.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) 2023 IBM Corp.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package iooption
|
||||||
|
|
||||||
|
import (
|
||||||
|
G "github.com/IBM/fp-go/iooption/generic"
|
||||||
|
O "github.com/IBM/fp-go/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||||
|
// whether the body action returns and error or not.
|
||||||
|
func Bracket[E, A, B, ANY any](
|
||||||
|
acquire IOOption[A],
|
||||||
|
use func(A) IOOption[B],
|
||||||
|
release func(A, O.Option[B]) IOOption[ANY],
|
||||||
|
) IOOption[B] {
|
||||||
|
return G.Bracket(acquire, use, release)
|
||||||
|
}
|
@@ -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-09-12 13:44:32.1514823 +0200 CEST m=+0.098931001
|
// 2023-10-23 08:31:01.9227118 +0200 CEST m=+0.009977901
|
||||||
|
|
||||||
package iooption
|
package iooption
|
||||||
|
|
||||||
|
46
iooption/generic/bracket.go
Normal file
46
iooption/generic/bracket.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// 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 (
|
||||||
|
G "github.com/IBM/fp-go/internal/bracket"
|
||||||
|
I "github.com/IBM/fp-go/io/generic"
|
||||||
|
O "github.com/IBM/fp-go/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||||
|
// whether the body action returns and error or not.
|
||||||
|
func Bracket[
|
||||||
|
GA ~func() O.Option[A],
|
||||||
|
GB ~func() O.Option[B],
|
||||||
|
GANY ~func() O.Option[ANY],
|
||||||
|
A, B, ANY any](
|
||||||
|
|
||||||
|
acquire GA,
|
||||||
|
use func(A) GB,
|
||||||
|
release func(A, O.Option[B]) GANY,
|
||||||
|
) GB {
|
||||||
|
return G.Bracket[GA, GB, GANY, O.Option[B], A, B](
|
||||||
|
I.Of[GB, O.Option[B]],
|
||||||
|
MonadChain[GA, GB, A, B],
|
||||||
|
I.MonadChain[GB, GB, O.Option[B], O.Option[B]],
|
||||||
|
MonadChain[GANY, GB, ANY, B],
|
||||||
|
|
||||||
|
acquire,
|
||||||
|
use,
|
||||||
|
release,
|
||||||
|
)
|
||||||
|
}
|
@@ -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-09-12 13:44:32.1546277 +0200 CEST m=+0.102076401
|
// 2023-10-23 08:31:01.9227118 +0200 CEST m=+0.009977901
|
||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
28
iooption/generic/sync.go
Normal file
28
iooption/generic/sync.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
G "github.com/IBM/fp-go/io/generic"
|
||||||
|
O "github.com/IBM/fp-go/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[GA ~func() O.Option[A], A any](lock func() context.CancelFunc) func(fa GA) GA {
|
||||||
|
return G.WithLock[GA](lock)
|
||||||
|
}
|
28
iooption/sync.go
Normal file
28
iooption/sync.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// 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 (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
IO "github.com/IBM/fp-go/io"
|
||||||
|
G "github.com/IBM/fp-go/iooption/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[E, A any](lock IO.IO[context.CancelFunc]) func(fa IOOption[A]) IOOption[A] {
|
||||||
|
return G.WithLock[IOOption[A]](lock)
|
||||||
|
}
|
26
iterator/stateless/any.go
Normal file
26
iterator/stateless/any.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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 stateless
|
||||||
|
|
||||||
|
import (
|
||||||
|
G "github.com/IBM/fp-go/iterator/stateless/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Any returns `true` if any element of the iterable is `true`. If the iterable is empty, return `false`
|
||||||
|
// Similar to the [https://docs.python.org/3/library/functions.html#any] function
|
||||||
|
func Any[U any](pred func(U) bool) func(ma Iterator[U]) bool {
|
||||||
|
return G.Any[Iterator[U]](pred)
|
||||||
|
}
|
38
iterator/stateless/any_test.go
Normal file
38
iterator/stateless/any_test.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// 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 stateless
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAny(t *testing.T) {
|
||||||
|
|
||||||
|
anyBool := Any(F.Identity[bool])
|
||||||
|
|
||||||
|
i1 := FromArray(A.From(false, true, false))
|
||||||
|
assert.True(t, anyBool(i1))
|
||||||
|
|
||||||
|
i2 := FromArray(A.From(false, false, false))
|
||||||
|
assert.False(t, anyBool(i2))
|
||||||
|
|
||||||
|
i3 := Empty[bool]()
|
||||||
|
assert.False(t, anyBool(i3))
|
||||||
|
}
|
55
iterator/stateless/example_test.go
Normal file
55
iterator/stateless/example_test.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// 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 stateless
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
A "github.com/IBM/fp-go/array"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
O "github.com/IBM/fp-go/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example_any() {
|
||||||
|
// `Any` function that simply returns the boolean identity
|
||||||
|
anyBool := Any(F.Identity[bool])
|
||||||
|
|
||||||
|
fmt.Println(anyBool(FromArray(A.From(true, false, false))))
|
||||||
|
fmt.Println(anyBool(FromArray(A.From(false, false, false))))
|
||||||
|
fmt.Println(anyBool(Empty[bool]()))
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_next() {
|
||||||
|
|
||||||
|
seq := MakeBy(F.Identity[int])
|
||||||
|
|
||||||
|
first := seq()
|
||||||
|
|
||||||
|
value := F.Pipe1(
|
||||||
|
first,
|
||||||
|
O.Map(Current[int]),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Println(value)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// Some[int](0)
|
||||||
|
}
|
31
iterator/stateless/generic/any.go
Normal file
31
iterator/stateless/generic/any.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) 2023 IBM Corp.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package generic
|
||||||
|
|
||||||
|
import (
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
O "github.com/IBM/fp-go/option"
|
||||||
|
T "github.com/IBM/fp-go/tuple"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Any returns `true` if any element of the iterable is `true`. If the iterable is empty, return `false`
|
||||||
|
func Any[GU ~func() O.Option[T.Tuple2[GU, U]], FCT ~func(U) bool, U any](pred FCT) func(ma GU) bool {
|
||||||
|
return F.Flow3(
|
||||||
|
Filter[GU](pred),
|
||||||
|
First[GU],
|
||||||
|
O.IsSome[U],
|
||||||
|
)
|
||||||
|
}
|
@@ -41,7 +41,7 @@ func DropWhile[GU ~func() O.Option[T.Tuple2[GU, U]], U any](pred func(U) bool) f
|
|||||||
return F.Pipe2(
|
return F.Pipe2(
|
||||||
t,
|
t,
|
||||||
fromPred,
|
fromPred,
|
||||||
O.Fold(recurse(t.F1), O.Of[T.Tuple2[GU, U]]),
|
O.Fold(recurse(Next(t)), O.Of[T.Tuple2[GU, U]]),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -26,6 +26,16 @@ import (
|
|||||||
T "github.com/IBM/fp-go/tuple"
|
T "github.com/IBM/fp-go/tuple"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Next returns the iterator for the next element in an iterator `T.Tuple2`
|
||||||
|
func Next[GU ~func() O.Option[T.Tuple2[GU, U]], U any](m T.Tuple2[GU, U]) GU {
|
||||||
|
return T.First(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current returns the current element in an iterator `T.Tuple2`
|
||||||
|
func Current[GU ~func() O.Option[T.Tuple2[GU, U]], U any](m T.Tuple2[GU, U]) U {
|
||||||
|
return T.Second(m)
|
||||||
|
}
|
||||||
|
|
||||||
// From constructs an array from a set of variadic arguments
|
// From constructs an array from a set of variadic arguments
|
||||||
func From[GU ~func() O.Option[T.Tuple2[GU, U]], U any](data ...U) GU {
|
func From[GU ~func() O.Option[T.Tuple2[GU, U]], U any](data ...U) GU {
|
||||||
return FromArray[GU](data)
|
return FromArray[GU](data)
|
||||||
@@ -56,8 +66,8 @@ func reduce[GU ~func() O.Option[T.Tuple2[GU, U]], U, V any](as GU, f func(V, U)
|
|||||||
current := initial
|
current := initial
|
||||||
for ok {
|
for ok {
|
||||||
// next (with bad side effect)
|
// next (with bad side effect)
|
||||||
current = f(current, next.F2)
|
current = f(current, Current(next))
|
||||||
next, ok = O.Unwrap(next.F1())
|
next, ok = O.Unwrap(Next(next)())
|
||||||
}
|
}
|
||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
@@ -199,8 +209,8 @@ func FilterMap[GV ~func() O.Option[T.Tuple2[GV, V]], GU ~func() O.Option[T.Tuple
|
|||||||
m = O.Fold(
|
m = O.Fold(
|
||||||
Empty[GV](),
|
Empty[GV](),
|
||||||
func(t T.Tuple2[GU, U]) O.Option[T.Tuple2[GV, V]] {
|
func(t T.Tuple2[GU, U]) O.Option[T.Tuple2[GV, V]] {
|
||||||
r := recurse(t.F1)
|
r := recurse(Next(t))
|
||||||
return O.MonadFold(f(t.F2), r, F.Flow2(
|
return O.MonadFold(f(Current(t)), r, F.Flow2(
|
||||||
F.Bind1st(T.MakeTuple2[GV, V], r),
|
F.Bind1st(T.MakeTuple2[GV, V], r),
|
||||||
O.Some[T.Tuple2[GV, V]],
|
O.Some[T.Tuple2[GV, V]],
|
||||||
))
|
))
|
||||||
|
@@ -26,6 +26,16 @@ import (
|
|||||||
// Iterator represents a stateless, pure way to iterate over a sequence
|
// Iterator represents a stateless, pure way to iterate over a sequence
|
||||||
type Iterator[U any] L.Lazy[O.Option[T.Tuple2[Iterator[U], U]]]
|
type Iterator[U any] L.Lazy[O.Option[T.Tuple2[Iterator[U], U]]]
|
||||||
|
|
||||||
|
// Next returns the [Iterator] for the next element in an iterator `T.Tuple2`
|
||||||
|
func Next[U any](m T.Tuple2[Iterator[U], U]) Iterator[U] {
|
||||||
|
return G.Next(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current returns the current element in an [Iterator] `T.Tuple2`
|
||||||
|
func Current[U any](m T.Tuple2[Iterator[U], U]) U {
|
||||||
|
return G.Current(m)
|
||||||
|
}
|
||||||
|
|
||||||
// Empty returns the empty iterator
|
// Empty returns the empty iterator
|
||||||
func Empty[U any]() Iterator[U] {
|
func Empty[U any]() Iterator[U] {
|
||||||
return G.Empty[Iterator[U]]()
|
return G.Empty[Iterator[U]]()
|
||||||
|
12
json/json.go
12
json/json.go
@@ -23,16 +23,12 @@ import (
|
|||||||
|
|
||||||
// Unmarshal parses a JSON data structure from bytes
|
// Unmarshal parses a JSON data structure from bytes
|
||||||
func Unmarshal[A any](data []byte) E.Either[error, A] {
|
func Unmarshal[A any](data []byte) E.Either[error, A] {
|
||||||
return E.TryCatchError(func() (A, error) {
|
var result A
|
||||||
var result A
|
err := json.Unmarshal(data, &result)
|
||||||
err := json.Unmarshal(data, &result)
|
return E.TryCatchError(result, err)
|
||||||
return result, err
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal converts a data structure to json
|
// Marshal converts a data structure to json
|
||||||
func Marshal[A any](a A) E.Either[error, []byte] {
|
func Marshal[A any](a A) E.Either[error, []byte] {
|
||||||
return E.TryCatchError(func() ([]byte, error) {
|
return E.TryCatchError(json.Marshal(a))
|
||||||
return json.Marshal(a)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ func MakeMagma[A any](c func(A, A) A) Magma[A] {
|
|||||||
|
|
||||||
func Reverse[A any](m Magma[A]) Magma[A] {
|
func Reverse[A any](m Magma[A]) Magma[A] {
|
||||||
return MakeMagma(func(x A, y A) A {
|
return MakeMagma(func(x A, y A) A {
|
||||||
return m.Concat(y, y)
|
return m.Concat(y, x)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ import (
|
|||||||
G "github.com/IBM/fp-go/optics/traversal/generic"
|
G "github.com/IBM/fp-go/optics/traversal/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FromArray returns a traversal from an array for the identity monad
|
// FromArray returns a traversal from an array for the identity [Monoid]
|
||||||
func FromArray[E, A any](m M.Monoid[E]) G.Traversal[[]A, A, C.Const[E, []A], C.Const[E, A]] {
|
func FromArray[E, A any](m M.Monoid[E]) G.Traversal[[]A, A, C.Const[E, []A], C.Const[E, A]] {
|
||||||
return AR.FromArray[[]A, E, A](m)
|
return AR.FromArray[[]A, E, A](m)
|
||||||
}
|
}
|
||||||
|
@@ -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-09-12 13:44:34.2077257 +0200 CEST m=+0.023541001
|
// 2023-10-23 08:31:07.8687134 +0200 CEST m=+0.012222901
|
||||||
|
|
||||||
package option
|
package option
|
||||||
|
|
||||||
|
@@ -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-09-12 13:44:36.1655251 +0200 CEST m=+0.010000501
|
// 2023-10-23 08:31:13.0131834 +0200 CEST m=+0.010996501
|
||||||
|
|
||||||
package reader
|
package reader
|
||||||
|
|
||||||
|
@@ -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-09-12 13:44:36.166526 +0200 CEST m=+0.011001401
|
// 2023-10-23 08:31:13.0131834 +0200 CEST m=+0.010996501
|
||||||
package generic
|
package generic
|
||||||
|
|
||||||
// From0 converts a function with 1 parameters returning a [R] into a function with 0 parameters returning a [GRA]
|
// From0 converts a function with 1 parameters returning a [R] into a function with 0 parameters returning a [GRA]
|
||||||
|
@@ -25,58 +25,58 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testError = fmt.Errorf("error")
|
errFoo = fmt.Errorf("error")
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSequenceT1(t *testing.T) {
|
func TestSequenceT1(t *testing.T) {
|
||||||
|
|
||||||
t1 := Of[MyContext, error]("s1")
|
t1 := Of[MyContext, error]("s1")
|
||||||
e1 := Left[MyContext, string](testError)
|
e1 := Left[MyContext, string](errFoo)
|
||||||
|
|
||||||
res1 := SequenceT1(t1)
|
res1 := SequenceT1(t1)
|
||||||
assert.Equal(t, E.Of[error](T.MakeTuple1("s1")), res1(defaultContext))
|
assert.Equal(t, E.Of[error](T.MakeTuple1("s1")), res1(defaultContext))
|
||||||
|
|
||||||
res2 := SequenceT1(e1)
|
res2 := SequenceT1(e1)
|
||||||
assert.Equal(t, E.Left[T.Tuple1[string]](testError), res2(defaultContext))
|
assert.Equal(t, E.Left[T.Tuple1[string]](errFoo), res2(defaultContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSequenceT2(t *testing.T) {
|
func TestSequenceT2(t *testing.T) {
|
||||||
|
|
||||||
t1 := Of[MyContext, error]("s1")
|
t1 := Of[MyContext, error]("s1")
|
||||||
e1 := Left[MyContext, string](testError)
|
e1 := Left[MyContext, string](errFoo)
|
||||||
t2 := Of[MyContext, error](2)
|
t2 := Of[MyContext, error](2)
|
||||||
e2 := Left[MyContext, int](testError)
|
e2 := Left[MyContext, int](errFoo)
|
||||||
|
|
||||||
res1 := SequenceT2(t1, t2)
|
res1 := SequenceT2(t1, t2)
|
||||||
assert.Equal(t, E.Of[error](T.MakeTuple2("s1", 2)), res1(defaultContext))
|
assert.Equal(t, E.Of[error](T.MakeTuple2("s1", 2)), res1(defaultContext))
|
||||||
|
|
||||||
res2 := SequenceT2(e1, t2)
|
res2 := SequenceT2(e1, t2)
|
||||||
assert.Equal(t, E.Left[T.Tuple2[string, int]](testError), res2(defaultContext))
|
assert.Equal(t, E.Left[T.Tuple2[string, int]](errFoo), res2(defaultContext))
|
||||||
|
|
||||||
res3 := SequenceT2(t1, e2)
|
res3 := SequenceT2(t1, e2)
|
||||||
assert.Equal(t, E.Left[T.Tuple2[string, int]](testError), res3(defaultContext))
|
assert.Equal(t, E.Left[T.Tuple2[string, int]](errFoo), res3(defaultContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSequenceT3(t *testing.T) {
|
func TestSequenceT3(t *testing.T) {
|
||||||
|
|
||||||
t1 := Of[MyContext, error]("s1")
|
t1 := Of[MyContext, error]("s1")
|
||||||
e1 := Left[MyContext, string](testError)
|
e1 := Left[MyContext, string](errFoo)
|
||||||
t2 := Of[MyContext, error](2)
|
t2 := Of[MyContext, error](2)
|
||||||
e2 := Left[MyContext, int](testError)
|
e2 := Left[MyContext, int](errFoo)
|
||||||
t3 := Of[MyContext, error](true)
|
t3 := Of[MyContext, error](true)
|
||||||
e3 := Left[MyContext, bool](testError)
|
e3 := Left[MyContext, bool](errFoo)
|
||||||
|
|
||||||
res1 := SequenceT3(t1, t2, t3)
|
res1 := SequenceT3(t1, t2, t3)
|
||||||
assert.Equal(t, E.Of[error](T.MakeTuple3("s1", 2, true)), res1(defaultContext))
|
assert.Equal(t, E.Of[error](T.MakeTuple3("s1", 2, true)), res1(defaultContext))
|
||||||
|
|
||||||
res2 := SequenceT3(e1, t2, t3)
|
res2 := SequenceT3(e1, t2, t3)
|
||||||
assert.Equal(t, E.Left[T.Tuple3[string, int, bool]](testError), res2(defaultContext))
|
assert.Equal(t, E.Left[T.Tuple3[string, int, bool]](errFoo), res2(defaultContext))
|
||||||
|
|
||||||
res3 := SequenceT3(t1, e2, t3)
|
res3 := SequenceT3(t1, e2, t3)
|
||||||
assert.Equal(t, E.Left[T.Tuple3[string, int, bool]](testError), res3(defaultContext))
|
assert.Equal(t, E.Left[T.Tuple3[string, int, bool]](errFoo), res3(defaultContext))
|
||||||
|
|
||||||
res4 := SequenceT3(t1, t2, e3)
|
res4 := SequenceT3(t1, t2, e3)
|
||||||
assert.Equal(t, E.Left[T.Tuple3[string, int, bool]](testError), res4(defaultContext))
|
assert.Equal(t, E.Left[T.Tuple3[string, int, bool]](errFoo), res4(defaultContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSequenceT4(t *testing.T) {
|
func TestSequenceT4(t *testing.T) {
|
||||||
|
34
readerio/generic/sync.go
Normal file
34
readerio/generic/sync.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
G "github.com/IBM/fp-go/io/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[GEA ~func(R) GIOA, GIOA ~func() A, R, A any](lock func() context.CancelFunc) func(fa GEA) GEA {
|
||||||
|
l := G.WithLock[GIOA](lock)
|
||||||
|
return func(fa GEA) GEA {
|
||||||
|
return F.Flow2(
|
||||||
|
fa,
|
||||||
|
l,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@@ -13,14 +13,15 @@
|
|||||||
// 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 readerio implements a specialization of the ReaderIO monad assuming a golang context as the context of the monad
|
|
||||||
package readerio
|
package readerio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
R "github.com/IBM/fp-go/readerio"
|
G "github.com/IBM/fp-go/readerio/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReaderIO is a specialization of the ReaderIO monad assuming a golang context as the context of the monad
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
type ReaderIO[A any] R.ReaderIO[context.Context, A]
|
func WithLock[R, A any](lock func() context.CancelFunc) func(fa ReaderIO[R, A]) ReaderIO[R, A] {
|
||||||
|
return G.WithLock[ReaderIO[R, A]](lock)
|
||||||
|
}
|
@@ -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-09-12 13:44:37.5566477 +0200 CEST m=+0.009011201
|
// 2023-10-23 08:31:16.2414489 +0200 CEST m=+0.013052301
|
||||||
|
|
||||||
package readerioeither
|
package readerioeither
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ package generic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
ET "github.com/IBM/fp-go/either"
|
ET "github.com/IBM/fp-go/either"
|
||||||
G "github.com/IBM/fp-go/internal/file"
|
G "github.com/IBM/fp-go/internal/bracket"
|
||||||
I "github.com/IBM/fp-go/readerio/generic"
|
I "github.com/IBM/fp-go/readerio/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -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-09-12 13:44:37.5566477 +0200 CEST m=+0.009011201
|
// 2023-10-23 08:31:16.241979 +0200 CEST m=+0.013582401
|
||||||
package generic
|
package generic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
28
readerioeither/generic/sync.go
Normal file
28
readerioeither/generic/sync.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// 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"
|
||||||
|
G "github.com/IBM/fp-go/readerio/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](lock func() context.CancelFunc) func(fa GEA) GEA {
|
||||||
|
return G.WithLock[GEA](lock)
|
||||||
|
}
|
27
readerioeither/sync.go
Normal file
27
readerioeither/sync.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
G "github.com/IBM/fp-go/readerioeither/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithLock executes the provided IO operation in the scope of a lock
|
||||||
|
func WithLock[R, E, A any](lock func() context.CancelFunc) func(fa ReaderIOEither[R, E, A]) ReaderIOEither[R, E, A] {
|
||||||
|
return G.WithLock[ReaderIOEither[R, E, A]](lock)
|
||||||
|
}
|
@@ -6,6 +6,15 @@
|
|||||||
],
|
],
|
||||||
"rangeStrategy": "bump",
|
"rangeStrategy": "bump",
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"matchManagers": [
|
||||||
|
"gomod"
|
||||||
|
],
|
||||||
|
"matchDepTypes": [
|
||||||
|
"golang"
|
||||||
|
],
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": [
|
"matchUpdateTypes": [
|
||||||
"major",
|
"major",
|
||||||
|
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
This folder is meant to contain examples that illustrate how to use the library. I recommend the following reading to get an idea of the underlying concepts. These articles talk about [fp-ts](https://github.com/gcanti/fp-ts) but the concepts are very similar, only syntax differs.
|
This folder is meant to contain examples that illustrate how to use the library. I recommend the following reading to get an idea of the underlying concepts. These articles talk about [fp-ts](https://github.com/gcanti/fp-ts) but the concepts are very similar, only syntax differs.
|
||||||
|
|
||||||
|
# Video Introduction
|
||||||
|
|
||||||
|
[](https://www.youtube.com/watch?v=Jif3jL6DRdw "introduction to fp-go")
|
||||||
|
|
||||||
### References
|
### References
|
||||||
|
|
||||||
- [Ryan's Blog](https://rlee.dev/practical-guide-to-fp-ts-part-1) - practical introduction into FP concepts
|
- [Ryan's Blog](https://rlee.dev/practical-guide-to-fp-ts-part-1) - practical introduction into FP concepts
|
||||||
|
@@ -107,6 +107,7 @@ func TestHeterogeneousHttpRequests(t *testing.T) {
|
|||||||
// BenchmarkHeterogeneousHttpRequests shows how to execute multiple HTTP requests in parallel when
|
// BenchmarkHeterogeneousHttpRequests shows how to execute multiple HTTP requests in parallel when
|
||||||
// the response structure of these requests is different. We use [R.TraverseTuple2] to account for the different types
|
// the response structure of these requests is different. We use [R.TraverseTuple2] to account for the different types
|
||||||
func BenchmarkHeterogeneousHttpRequests(b *testing.B) {
|
func BenchmarkHeterogeneousHttpRequests(b *testing.B) {
|
||||||
|
for n := 0; n < b.N; n++ {
|
||||||
heterogeneousHttpRequests()(context.Background())
|
heterogeneousHttpRequests()(context.Background())()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -105,7 +105,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// checkActive :: User -> Either error User
|
// checkActive :: User -> Either error User
|
||||||
checkActive = E.FromPredicate(Chapter08User.isActive, F.Constant1[Chapter08User](fmt.Errorf("Your account is not active")))
|
checkActive = E.FromPredicate(Chapter08User.isActive, F.Constant1[Chapter08User](fmt.Errorf("your account is not active")))
|
||||||
|
|
||||||
// validateUser :: (User -> Either String ()) -> User -> Either String User
|
// validateUser :: (User -> Either String ()) -> User -> Either String User
|
||||||
validateUser = F.Curry2(func(validate func(Chapter08User) E.Either[error, any], user Chapter08User) E.Either[error, Chapter08User] {
|
validateUser = F.Curry2(func(validate func(Chapter08User) E.Either[error, any], user Chapter08User) E.Either[error, Chapter08User] {
|
||||||
@@ -235,7 +235,7 @@ func Example_solution08C() {
|
|||||||
fmt.Println(eitherWelcome(theresa08))
|
fmt.Println(eitherWelcome(theresa08))
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// Left[*errors.errorString, string](Your account is not active)
|
// Left[*errors.errorString, string](your account is not active)
|
||||||
// Right[<nil>, string](Welcome Theresa)
|
// Right[<nil>, string](Welcome Theresa)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user