mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-25 22:21:49 +02:00
fix: introduce IOResult
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
benchErr = errors.New("benchmark error")
|
||||
errBench = errors.New("benchmark error")
|
||||
benchResult Either[error, int]
|
||||
benchBool bool
|
||||
benchInt int
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
func BenchmarkLeft(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
benchResult = Left[int](benchErr)
|
||||
benchResult = Left[int](errBench)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func BenchmarkOf(b *testing.B) {
|
||||
|
||||
// Benchmark predicates
|
||||
func BenchmarkIsLeft(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -84,7 +84,7 @@ func BenchmarkMonadFold_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkMonadFold_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
onLeft := func(e error) int { return 0 }
|
||||
onRight := func(a int) int { return a * 2 }
|
||||
b.ResetTimer()
|
||||
@@ -108,7 +108,7 @@ func BenchmarkFold_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkFold_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
folder := Fold(
|
||||
func(e error) int { return 0 },
|
||||
func(a int) int { return a * 2 },
|
||||
@@ -131,7 +131,7 @@ func BenchmarkUnwrap_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkUnwrap_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -149,7 +149,7 @@ func BenchmarkUnwrapError_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkUnwrapError_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -169,7 +169,7 @@ func BenchmarkMonadMap_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkMonadMap_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
mapper := func(a int) int { return a * 2 }
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -189,7 +189,7 @@ func BenchmarkMap_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkMap_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
mapper := Map[error](func(a int) int { return a * 2 })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -209,7 +209,7 @@ func BenchmarkMapLeft_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkMapLeft_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
mapper := MapLeft[int](func(e error) string { return e.Error() })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -232,7 +232,7 @@ func BenchmarkBiMap_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkBiMap_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
mapper := BiMap(
|
||||
func(e error) string { return e.Error() },
|
||||
func(a int) string { return "value" },
|
||||
@@ -256,7 +256,7 @@ func BenchmarkMonadChain_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkMonadChain_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
chainer := func(a int) Either[error, int] { return Right[error](a * 2) }
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -276,7 +276,7 @@ func BenchmarkChain_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkChain_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
chainer := Chain[error](func(a int) Either[error, int] { return Right[error](a * 2) })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -287,7 +287,7 @@ func BenchmarkChain_Left(b *testing.B) {
|
||||
|
||||
func BenchmarkChainFirst_Right(b *testing.B) {
|
||||
right := Right[error](42)
|
||||
chainer := ChainFirst[error](func(a int) Either[error, string] { return Right[error]("logged") })
|
||||
chainer := ChainFirst(func(a int) Either[error, string] { return Right[error]("logged") })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -296,7 +296,7 @@ func BenchmarkChainFirst_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkChainFirst_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
chainer := ChainFirst[error](func(a int) Either[error, string] { return Right[error]("logged") })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -315,7 +315,7 @@ func BenchmarkFlatten_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkFlatten_Left(b *testing.B) {
|
||||
nested := Left[Either[error, int]](benchErr)
|
||||
nested := Left[Either[error, int]](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -336,7 +336,7 @@ func BenchmarkMonadAp_RightRight(b *testing.B) {
|
||||
|
||||
func BenchmarkMonadAp_RightLeft(b *testing.B) {
|
||||
fab := Right[error](func(a int) int { return a * 2 })
|
||||
fa := Left[int](benchErr)
|
||||
fa := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -345,7 +345,7 @@ func BenchmarkMonadAp_RightLeft(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkMonadAp_LeftRight(b *testing.B) {
|
||||
fab := Left[func(int) int](benchErr)
|
||||
fab := Left[func(int) int](errBench)
|
||||
fa := Right[error](42)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -368,7 +368,7 @@ func BenchmarkAp_RightRight(b *testing.B) {
|
||||
// Benchmark alternative operations
|
||||
func BenchmarkAlt_RightRight(b *testing.B) {
|
||||
right := Right[error](42)
|
||||
alternative := Alt[error](func() Either[error, int] { return Right[error](99) })
|
||||
alternative := Alt(func() Either[error, int] { return Right[error](99) })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -377,7 +377,7 @@ func BenchmarkAlt_RightRight(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkAlt_LeftRight(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
alternative := Alt[error](func() Either[error, int] { return Right[error](99) })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -397,8 +397,8 @@ func BenchmarkOrElse_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkOrElse_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
recover := OrElse[error](func(e error) Either[error, int] { return Right[error](0) })
|
||||
left := Left[int](errBench)
|
||||
recover := OrElse(func(e error) Either[error, int] { return Right[error](0) })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -419,7 +419,7 @@ func BenchmarkTryCatch_Error(b *testing.B) {
|
||||
onThrow := func(err error) error { return err }
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
benchResult = TryCatch(0, benchErr, onThrow)
|
||||
benchResult = TryCatch(0, errBench, onThrow)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ func BenchmarkTryCatchError_Success(b *testing.B) {
|
||||
func BenchmarkTryCatchError_Error(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
benchResult = TryCatchError(0, benchErr)
|
||||
benchResult = TryCatchError(0, errBench)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,7 +447,7 @@ func BenchmarkSwap_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkSwap_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -466,7 +466,7 @@ func BenchmarkGetOrElse_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkGetOrElse_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
getter := GetOrElse[error](func(e error) int { return 0 })
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
@@ -489,7 +489,7 @@ func BenchmarkPipeline_Map_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkPipeline_Map_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -513,7 +513,7 @@ func BenchmarkPipeline_Chain_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkPipeline_Chain_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -539,7 +539,7 @@ func BenchmarkPipeline_Complex_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkPipeline_Complex_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -565,7 +565,7 @@ func BenchmarkMonadSequence2_RightRight(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkMonadSequence2_LeftRight(b *testing.B) {
|
||||
e1 := Left[int](benchErr)
|
||||
e1 := Left[int](errBench)
|
||||
e2 := Right[error](20)
|
||||
f := func(a, b int) Either[error, int] { return Right[error](a + b) }
|
||||
b.ResetTimer()
|
||||
@@ -641,7 +641,7 @@ func BenchmarkString_Right(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkString_Left(b *testing.B) {
|
||||
left := Left[int](benchErr)
|
||||
left := Left[int](errBench)
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
@@ -59,7 +59,7 @@ func TestUneitherize1(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "positive", result)
|
||||
|
||||
result, err = uneitherized(-1)
|
||||
_, err = uneitherized(-1)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ import (
|
||||
)
|
||||
|
||||
// MkdirAll create a sequence of directories, see [os.MkdirAll]
|
||||
func MkdirAll(path string, perm os.FileMode) ioeither.IOEither[error, string] {
|
||||
func MkdirAll(path string, perm os.FileMode) IOEither[error, string] {
|
||||
return ioeither.TryCatchError(func() (string, error) {
|
||||
return path, os.MkdirAll(path, perm)
|
||||
})
|
||||
}
|
||||
|
||||
// Mkdir create a directory, see [os.Mkdir]
|
||||
func Mkdir(path string, perm os.FileMode) ioeither.IOEither[error, string] {
|
||||
func Mkdir(path string, perm os.FileMode) IOEither[error, string] {
|
||||
return ioeither.TryCatchError(func() (string, error) {
|
||||
return path, os.Mkdir(path, perm)
|
||||
})
|
||||
|
||||
@@ -32,8 +32,8 @@ var (
|
||||
)
|
||||
|
||||
// WriteFile writes a data blob to a file
|
||||
func WriteFile(dstName string, perm os.FileMode) func([]byte) ioeither.IOEither[error, []byte] {
|
||||
return func(data []byte) ioeither.IOEither[error, []byte] {
|
||||
func WriteFile(dstName string, perm os.FileMode) Kleisli[error, []byte, []byte] {
|
||||
return func(data []byte) IOEither[error, []byte] {
|
||||
return ioeither.TryCatchError(func() ([]byte, error) {
|
||||
return data, os.WriteFile(dstName, data, perm)
|
||||
})
|
||||
@@ -41,14 +41,14 @@ func WriteFile(dstName string, perm os.FileMode) func([]byte) ioeither.IOEither[
|
||||
}
|
||||
|
||||
// Remove removes a file by name
|
||||
func Remove(name string) ioeither.IOEither[error, string] {
|
||||
func Remove(name string) IOEither[error, string] {
|
||||
return ioeither.TryCatchError(func() (string, error) {
|
||||
return name, os.Remove(name)
|
||||
})
|
||||
}
|
||||
|
||||
// Close closes an object
|
||||
func Close[C io.Closer](c C) ioeither.IOEither[error, any] {
|
||||
func Close[C io.Closer](c C) IOEither[error, any] {
|
||||
return ioeither.TryCatchError(func() (any, error) {
|
||||
return c, c.Close()
|
||||
})
|
||||
|
||||
@@ -29,7 +29,7 @@ var (
|
||||
)
|
||||
|
||||
// ReadAll uses a generator function to create a stream, reads it and closes it
|
||||
func ReadAll[R io.ReadCloser](acquire ioeither.IOEither[error, R]) ioeither.IOEither[error, []byte] {
|
||||
func ReadAll[R io.ReadCloser](acquire IOEither[error, R]) IOEither[error, []byte] {
|
||||
return F.Pipe1(
|
||||
F.Flow2(
|
||||
FL.ToReader[R],
|
||||
|
||||
@@ -39,6 +39,6 @@ var (
|
||||
)
|
||||
|
||||
// WithTempFile creates a temporary file, then invokes a callback to create a resource based on the file, then close and remove the temp file
|
||||
func WithTempFile[A any](f func(*os.File) ioeither.IOEither[error, A]) ioeither.IOEither[error, A] {
|
||||
func WithTempFile[A any](f Kleisli[error, *os.File, A]) IOEither[error, A] {
|
||||
return ioeither.WithResource[A](onCreateTempFile, onReleaseTempFile)(f)
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestWithTempFile(t *testing.T) {
|
||||
|
||||
func TestWithTempFileOnClosedFile(t *testing.T) {
|
||||
|
||||
res := WithTempFile(func(f *os.File) ioeither.IOEither[error, []byte] {
|
||||
res := WithTempFile(func(f *os.File) IOEither[error, []byte] {
|
||||
return F.Pipe2(
|
||||
f,
|
||||
onWriteAll[*os.File]([]byte("Carsten")),
|
||||
|
||||
11
v2/ioeither/file/types.go
Normal file
11
v2/ioeither/file/types.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
)
|
||||
|
||||
type (
|
||||
IOEither[E, T any] = ioeither.IOEither[E, T]
|
||||
Kleisli[E, A, B any] = ioeither.Kleisli[E, A, B]
|
||||
Operator[E, A, B any] = ioeither.Operator[E, A, B]
|
||||
)
|
||||
@@ -21,8 +21,8 @@ import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
)
|
||||
|
||||
func onWriteAll[W io.Writer](data []byte) func(w W) ioeither.IOEither[error, []byte] {
|
||||
return func(w W) ioeither.IOEither[error, []byte] {
|
||||
func onWriteAll[W io.Writer](data []byte) Kleisli[error, W, []byte] {
|
||||
return func(w W) IOEither[error, []byte] {
|
||||
return ioeither.TryCatchError(func() ([]byte, error) {
|
||||
_, err := w.Write(data)
|
||||
return data, err
|
||||
@@ -31,9 +31,9 @@ func onWriteAll[W io.Writer](data []byte) func(w W) ioeither.IOEither[error, []b
|
||||
}
|
||||
|
||||
// WriteAll uses a generator function to create a stream, writes data to it and closes it
|
||||
func WriteAll[W io.WriteCloser](data []byte) func(acquire ioeither.IOEither[error, W]) ioeither.IOEither[error, []byte] {
|
||||
func WriteAll[W io.WriteCloser](data []byte) Operator[error, W, []byte] {
|
||||
onWrite := onWriteAll[W](data)
|
||||
return func(onCreate ioeither.IOEither[error, W]) ioeither.IOEither[error, []byte] {
|
||||
return func(onCreate IOEither[error, W]) IOEither[error, []byte] {
|
||||
return ioeither.WithResource[[]byte](
|
||||
onCreate,
|
||||
Close[W])(
|
||||
@@ -43,7 +43,7 @@ func WriteAll[W io.WriteCloser](data []byte) func(acquire ioeither.IOEither[erro
|
||||
}
|
||||
|
||||
// Write uses a generator function to create a stream, writes data to it and closes it
|
||||
func Write[R any, W io.WriteCloser](acquire ioeither.IOEither[error, W]) func(use func(W) ioeither.IOEither[error, R]) ioeither.IOEither[error, R] {
|
||||
func Write[R any, W io.WriteCloser](acquire IOEither[error, W]) Kleisli[error, Kleisli[error, W, R], R] {
|
||||
return ioeither.WithResource[R](
|
||||
acquire,
|
||||
Close[W])
|
||||
|
||||
2687
v2/ioeither/gen.go
2687
v2/ioeither/gen.go
File diff suppressed because it is too large
Load Diff
@@ -230,7 +230,7 @@ func Memoize[E, A any](ma IOEither[E, A]) IOEither[E, A] {
|
||||
return io.Memoize(ma)
|
||||
}
|
||||
|
||||
func MonadMapLeft[E1, E2, A any](fa IOEither[E1, A], f func(E1) E2) IOEither[E2, A] {
|
||||
func MonadMapLeft[A, E1, E2 any](fa IOEither[E1, A], f func(E1) E2) IOEither[E2, A] {
|
||||
return eithert.MonadMapLeft(
|
||||
io.MonadMap[Either[E1, A], Either[E2, A]],
|
||||
fa,
|
||||
|
||||
@@ -24,7 +24,7 @@ type (
|
||||
)
|
||||
|
||||
// AltSemigroup is a [Semigroup] that tries the first item and then the second one using an alternative
|
||||
func AltSemigroup[E, A any]() semigroup.Semigroup[IOEither[E, A]] {
|
||||
func AltSemigroup[E, A any]() Semigroup[E, A] {
|
||||
return semigroup.AltSemigroup(
|
||||
MonadAlt[E, A],
|
||||
)
|
||||
|
||||
48
v2/ioresult/ap.go
Normal file
48
v2/ioresult/ap.go
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
)
|
||||
|
||||
// MonadApFirst combines two effectful actions, keeping only the result of the first.
|
||||
//
|
||||
//go:inline
|
||||
func MonadApFirst[A, B any](first IOResult[A], second IOResult[B]) IOResult[A] {
|
||||
return ioeither.MonadApFirst(first, second)
|
||||
}
|
||||
|
||||
// ApFirst combines two effectful actions, keeping only the result of the first.
|
||||
//
|
||||
//go:inline
|
||||
func ApFirst[A, B any](second IOResult[B]) Operator[A, A] {
|
||||
return ioeither.ApFirst[A](second)
|
||||
}
|
||||
|
||||
// MonadApSecond combines two effectful actions, keeping only the result of the second.
|
||||
//
|
||||
//go:inline
|
||||
func MonadApSecond[A, B any](first IOResult[A], second IOResult[B]) IOResult[B] {
|
||||
return ioeither.MonadApSecond(first, second)
|
||||
}
|
||||
|
||||
// ApSecond combines two effectful actions, keeping only the result of the second.
|
||||
//
|
||||
//go:inline
|
||||
func ApSecond[A, B any](second IOResult[B]) Operator[A, B] {
|
||||
return ioeither.ApSecond[A](second)
|
||||
}
|
||||
296
v2/ioresult/bind.go
Normal file
296
v2/ioresult/bind.go
Normal file
@@ -0,0 +1,296 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
L "github.com/IBM/fp-go/v2/optics/lens"
|
||||
)
|
||||
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Posts []Post
|
||||
// }
|
||||
// result := ioeither.Do[error](State{})
|
||||
//
|
||||
//go:inline
|
||||
func Do[S any](
|
||||
empty S,
|
||||
) IOResult[S] {
|
||||
return ioeither.Do[error](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Posts []Post
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// ioeither.Do[error](State{}),
|
||||
// ioeither.Bind(
|
||||
// func(user User) func(State) State {
|
||||
// return func(s State) State { s.User = user; return s }
|
||||
// },
|
||||
// func(s State) ioeither.IOResult[error, User] {
|
||||
// return ioeither.TryCatch(func() (User, error) {
|
||||
// return fetchUser()
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// ioeither.Bind(
|
||||
// func(posts []Post) func(State) State {
|
||||
// return func(s State) State { s.Posts = posts; return s }
|
||||
// },
|
||||
// func(s State) ioeither.IOResult[error, []Post] {
|
||||
// // This can access s.User from the previous step
|
||||
// return ioeither.TryCatch(func() ([]Post, error) {
|
||||
// return fetchPostsForUser(s.User.ID)
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
//
|
||||
//go:inline
|
||||
func Bind[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f Kleisli[S1, T],
|
||||
) Operator[S1, S2] {
|
||||
return ioeither.Bind(setter, f)
|
||||
}
|
||||
|
||||
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
//
|
||||
//go:inline
|
||||
func Let[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) T,
|
||||
) Operator[S1, S2] {
|
||||
return ioeither.Let[error](setter, f)
|
||||
}
|
||||
|
||||
// LetTo attaches the a value to a context [S1] to produce a context [S2]
|
||||
//
|
||||
//go:inline
|
||||
func LetTo[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
b T,
|
||||
) Operator[S1, S2] {
|
||||
return ioeither.LetTo[error](setter, b)
|
||||
}
|
||||
|
||||
// BindTo initializes a new state [S1] from a value [T]
|
||||
//
|
||||
//go:inline
|
||||
func BindTo[S1, T any](
|
||||
setter func(T) S1,
|
||||
) Operator[T, S1] {
|
||||
return ioeither.BindTo[error](setter)
|
||||
}
|
||||
|
||||
// ApS attaches a value to a context [S1] to produce a context [S2] by considering
|
||||
// the context and the value concurrently (using Applicative rather than Monad).
|
||||
// This allows independent computations to be combined without one depending on the result of the other.
|
||||
//
|
||||
// Unlike Bind, which sequences operations, ApS can be used when operations are independent
|
||||
// and can conceptually run in parallel.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Posts []Post
|
||||
// }
|
||||
//
|
||||
// // These operations are independent and can be combined with ApS
|
||||
// getUser := ioeither.Right[error](User{ID: 1, Name: "Alice"})
|
||||
// getPosts := ioeither.Right[error]([]Post{{ID: 1, Title: "Hello"}})
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// ioeither.Do[error](State{}),
|
||||
// ioeither.ApS(
|
||||
// func(user User) func(State) State {
|
||||
// return func(s State) State { s.User = user; return s }
|
||||
// },
|
||||
// getUser,
|
||||
// ),
|
||||
// ioeither.ApS(
|
||||
// func(posts []Post) func(State) State {
|
||||
// return func(s State) State { s.Posts = posts; return s }
|
||||
// },
|
||||
// getPosts,
|
||||
// ),
|
||||
// )
|
||||
//
|
||||
//go:inline
|
||||
func ApS[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
fa IOResult[T],
|
||||
) Operator[S1, S2] {
|
||||
return ioeither.ApS(setter, fa)
|
||||
}
|
||||
|
||||
// ApSL attaches a value to a context using a lens-based setter.
|
||||
// This is a convenience function that combines ApS with a lens, allowing you to use
|
||||
// optics to update nested structures in a more composable way.
|
||||
//
|
||||
// The lens parameter provides both the getter and setter for a field within the structure S.
|
||||
// This eliminates the need to manually write setter functions.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type Config struct {
|
||||
// Host string
|
||||
// Port int
|
||||
// }
|
||||
//
|
||||
// portLens := lens.MakeLens(
|
||||
// func(c Config) int { return c.Port },
|
||||
// func(c Config, p int) Config { c.Port = p; return c },
|
||||
// )
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// ioeither.Of[error](Config{Host: "localhost"}),
|
||||
// ioeither.ApSL(portLens, ioeither.Of[error](8080)),
|
||||
// )
|
||||
//
|
||||
//go:inline
|
||||
func ApSL[S, T any](
|
||||
lens L.Lens[S, T],
|
||||
fa IOResult[T],
|
||||
) Operator[S, S] {
|
||||
return ioeither.ApSL(lens, fa)
|
||||
}
|
||||
|
||||
// BindL attaches the result of a computation to a context using a lens-based setter.
|
||||
// This is a convenience function that combines Bind with a lens, allowing you to use
|
||||
// optics to update nested structures based on their current values.
|
||||
//
|
||||
// The lens parameter provides both the getter and setter for a field within the structure S.
|
||||
// The computation function f receives the current value of the focused field and returns
|
||||
// an IOResult that produces the new value.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type Counter struct {
|
||||
// Value int
|
||||
// }
|
||||
//
|
||||
// valueLens := lens.MakeLens(
|
||||
// func(c Counter) int { return c.Value },
|
||||
// func(c Counter, v int) Counter { c.Value = v; return c },
|
||||
// )
|
||||
//
|
||||
// increment := func(v int) ioeither.IOResult[error, int] {
|
||||
// return ioeither.TryCatch(func() (int, error) {
|
||||
// if v >= 100 {
|
||||
// return 0, errors.New("overflow")
|
||||
// }
|
||||
// return v + 1, nil
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe1(
|
||||
// ioeither.Of[error](Counter{Value: 42}),
|
||||
// ioeither.BindL(valueLens, increment),
|
||||
// )
|
||||
//
|
||||
//go:inline
|
||||
func BindL[S, T any](
|
||||
lens L.Lens[S, T],
|
||||
f Kleisli[T, T],
|
||||
) Operator[S, S] {
|
||||
return ioeither.BindL(lens, f)
|
||||
}
|
||||
|
||||
// LetL attaches the result of a pure computation to a context using a lens-based setter.
|
||||
// This is a convenience function that combines Let with a lens, allowing you to use
|
||||
// optics to update nested structures with pure transformations.
|
||||
//
|
||||
// The lens parameter provides both the getter and setter for a field within the structure S.
|
||||
// The transformation function f receives the current value of the focused field and returns
|
||||
// the new value directly (not wrapped in IOResult).
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type Counter struct {
|
||||
// Value int
|
||||
// }
|
||||
//
|
||||
// valueLens := lens.MakeLens(
|
||||
// func(c Counter) int { return c.Value },
|
||||
// func(c Counter, v int) Counter { c.Value = v; return c },
|
||||
// )
|
||||
//
|
||||
// double := func(v int) int { return v * 2 }
|
||||
//
|
||||
// result := F.Pipe1(
|
||||
// ioeither.Of[error](Counter{Value: 21}),
|
||||
// ioeither.LetL(valueLens, double),
|
||||
// )
|
||||
//
|
||||
//go:inline
|
||||
func LetL[S, T any](
|
||||
lens L.Lens[S, T],
|
||||
f Endomorphism[T],
|
||||
) Operator[S, S] {
|
||||
return ioeither.LetL[error](lens, f)
|
||||
}
|
||||
|
||||
// LetToL attaches a constant value to a context using a lens-based setter.
|
||||
// This is a convenience function that combines LetTo with a lens, allowing you to use
|
||||
// optics to set nested fields to specific values.
|
||||
//
|
||||
// The lens parameter provides the setter for a field within the structure S.
|
||||
// Unlike LetL which transforms the current valuLetToL simply replaces it with
|
||||
// the provided constant value b.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type Config struct {
|
||||
// Debug bool
|
||||
// Timeout int
|
||||
// }
|
||||
//
|
||||
// debugLens := lens.MakeLens(
|
||||
// func(c Config) bool { return c.Debug },
|
||||
// func(c Config, d bool) Config { c.Debug = d; return c },
|
||||
// )
|
||||
//
|
||||
// result := F.Pipe1(
|
||||
// ioeither.Of[error](Config{Debug: truTimeout: 30}),
|
||||
// ioeither.LetToL(debugLens, false),
|
||||
// )
|
||||
//
|
||||
//go:inline
|
||||
func LetToL[S, T any](
|
||||
lens L.Lens[S, T],
|
||||
b T,
|
||||
) Operator[S, S] {
|
||||
return ioeither.LetToL[error](lens, b)
|
||||
}
|
||||
57
v2/ioresult/bind_test.go
Normal file
57
v2/ioresult/bind_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/IBM/fp-go/v2/internal/utils"
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func getLastName(s utils.Initial) IOResult[string] {
|
||||
return Of("Doe")
|
||||
}
|
||||
|
||||
func getGivenName(s utils.WithLastName) IOResult[string] {
|
||||
return Of("John")
|
||||
}
|
||||
|
||||
func TestBind(t *testing.T) {
|
||||
|
||||
res := F.Pipe3(
|
||||
Do(utils.Empty),
|
||||
Bind(utils.SetLastName, getLastName),
|
||||
Bind(utils.SetGivenName, getGivenName),
|
||||
Map(utils.GetFullName),
|
||||
)
|
||||
|
||||
assert.Equal(t, res(), result.Of("John Doe"))
|
||||
}
|
||||
|
||||
func TestApS(t *testing.T) {
|
||||
|
||||
res := F.Pipe3(
|
||||
Do(utils.Empty),
|
||||
ApS(utils.SetLastName, Of("Doe")),
|
||||
ApS(utils.SetGivenName, Of("John")),
|
||||
Map(utils.GetFullName),
|
||||
)
|
||||
|
||||
assert.Equal(t, res(), result.Of("John Doe"))
|
||||
}
|
||||
32
v2/ioresult/bracket.go
Normal file
32
v2/ioresult/bracket.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
)
|
||||
|
||||
// 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.
|
||||
//
|
||||
//go:inline
|
||||
func Bracket[A, B, ANY any](
|
||||
acquire IOResult[A],
|
||||
use Kleisli[A, B],
|
||||
release func(A, Result[B]) IOResult[ANY],
|
||||
) IOResult[B] {
|
||||
return ioeither.Bracket(acquire, use, release)
|
||||
}
|
||||
18
v2/ioresult/doc.go
Normal file
18
v2/ioresult/doc.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
//go:generate go run .. ioeither --count 10 --filename gen.go
|
||||
36
v2/ioresult/eq.go
Normal file
36
v2/ioresult/eq.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
EQ "github.com/IBM/fp-go/v2/eq"
|
||||
"github.com/IBM/fp-go/v2/io"
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
)
|
||||
|
||||
// Eq implements the equals predicate for values contained in the IOResult monad
|
||||
//
|
||||
//go:inline
|
||||
func Eq[A any](eq EQ.Eq[Result[A]]) EQ.Eq[IOResult[A]] {
|
||||
return io.Eq(eq)
|
||||
}
|
||||
|
||||
// FromStrictEquals constructs an [EQ.Eq] from the canonical comparison function
|
||||
//
|
||||
//go:inline
|
||||
func FromStrictEquals[A comparable]() EQ.Eq[IOResult[A]] {
|
||||
return Eq(result.FromStrictEquals[A]())
|
||||
}
|
||||
49
v2/ioresult/eq_test.go
Normal file
49
v2/ioresult/eq_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEq(t *testing.T) {
|
||||
|
||||
a := errors.New("a")
|
||||
b := errors.New("b")
|
||||
|
||||
r1 := Of(1)
|
||||
r2 := Of(1)
|
||||
r3 := Of(2)
|
||||
|
||||
e1 := Left[int](a)
|
||||
e2 := Left[int](a)
|
||||
e3 := Left[int](b)
|
||||
|
||||
eq := FromStrictEquals[int]()
|
||||
|
||||
assert.True(t, eq.Equals(r1, r1))
|
||||
assert.True(t, eq.Equals(r1, r2))
|
||||
assert.False(t, eq.Equals(r1, r3))
|
||||
assert.False(t, eq.Equals(r1, e1))
|
||||
|
||||
assert.True(t, eq.Equals(e1, e1))
|
||||
assert.True(t, eq.Equals(e1, e2))
|
||||
assert.False(t, eq.Equals(e1, e3))
|
||||
assert.False(t, eq.Equals(e2, r2))
|
||||
}
|
||||
57
v2/ioresult/examples_create_test.go
Normal file
57
v2/ioresult/examples_create_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
)
|
||||
|
||||
func ExampleIOEither_creation() {
|
||||
// Build an IOEither
|
||||
leftValue := Left[string](fmt.Errorf("some error"))
|
||||
rightValue := Right("value")
|
||||
|
||||
// Convert from Either
|
||||
eitherValue := result.Of(42)
|
||||
ioFromEither := FromEither(eitherValue)
|
||||
|
||||
// some predicate
|
||||
isEven := func(num int) (int, error) {
|
||||
if num%2 == 0 {
|
||||
return num, nil
|
||||
}
|
||||
return 0, fmt.Errorf("%d is an odd number", num)
|
||||
}
|
||||
fromEven := Eitherize1(isEven)
|
||||
leftFromPred := fromEven(3)
|
||||
rightFromPred := fromEven(4)
|
||||
|
||||
fmt.Println(leftValue())
|
||||
fmt.Println(rightValue())
|
||||
fmt.Println(ioFromEither())
|
||||
fmt.Println(leftFromPred())
|
||||
fmt.Println(rightFromPred())
|
||||
|
||||
// Output:
|
||||
// Left[*errors.errorString](some error)
|
||||
// Right[string](value)
|
||||
// Right[int](42)
|
||||
// Left[*errors.errorString](3 is an odd number)
|
||||
// Right[int](4)
|
||||
|
||||
}
|
||||
57
v2/ioresult/examples_do_test.go
Normal file
57
v2/ioresult/examples_do_test.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/IBM/fp-go/v2/io"
|
||||
T "github.com/IBM/fp-go/v2/tuple"
|
||||
)
|
||||
|
||||
func ExampleIOEither_do() {
|
||||
foo := Of("foo")
|
||||
bar := Of(1)
|
||||
|
||||
// quux consumes the state of three bindings and returns an [IO] instead of an [IOEither]
|
||||
quux := func(t T.Tuple3[string, int, string]) IO[any] {
|
||||
return io.FromImpure(func() {
|
||||
log.Printf("t1: %s, t2: %d, t3: %s", t.F1, t.F2, t.F3)
|
||||
})
|
||||
}
|
||||
|
||||
transform := func(t T.Tuple3[string, int, string]) int {
|
||||
return len(t.F1) + t.F2 + len(t.F3)
|
||||
}
|
||||
|
||||
b := F.Pipe5(
|
||||
foo,
|
||||
BindTo(T.Of[string]),
|
||||
ApS(T.Push1[string, int], bar),
|
||||
Bind(T.Push2[string, int, string], func(t T.Tuple2[string, int]) IOResult[string] {
|
||||
return Of(fmt.Sprintf("%s%d", t.F1, t.F2))
|
||||
}),
|
||||
ChainFirstIOK(quux),
|
||||
Map(transform),
|
||||
)
|
||||
|
||||
fmt.Println(b())
|
||||
|
||||
// Output:
|
||||
// Right[int](8)
|
||||
}
|
||||
45
v2/ioresult/examples_extract_test.go
Normal file
45
v2/ioresult/examples_extract_test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/IBM/fp-go/v2/io"
|
||||
)
|
||||
|
||||
func ExampleIOEither_extraction() {
|
||||
// IOEither
|
||||
someIOEither := Right(42)
|
||||
eitherValue := someIOEither() // E.Right(42)
|
||||
value := E.GetOrElse(F.Constant1[error](0))(eitherValue) // 42
|
||||
|
||||
// Or more directly
|
||||
infaillibleIO := GetOrElse(F.Constant1[error](io.Of(0)))(someIOEither) // => io.Right(42)
|
||||
valueFromIO := infaillibleIO() // => 42
|
||||
|
||||
fmt.Println(eitherValue)
|
||||
fmt.Println(value)
|
||||
fmt.Println(valueFromIO)
|
||||
|
||||
// Output:
|
||||
// Right[int](42)
|
||||
// 42
|
||||
// 42
|
||||
|
||||
}
|
||||
25
v2/ioresult/exec/exec.go
Normal file
25
v2/ioresult/exec/exec.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 exec
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
// Command executes a command
|
||||
Command = exec.Command
|
||||
)
|
||||
43
v2/ioresult/exec/exec_test.go
Normal file
43
v2/ioresult/exec/exec_test.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 exec
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
RA "github.com/IBM/fp-go/v2/array"
|
||||
B "github.com/IBM/fp-go/v2/bytes"
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
"github.com/IBM/fp-go/v2/exec"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOpenSSL(t *testing.T) {
|
||||
// execute the openSSL binary
|
||||
version := F.Pipe1(
|
||||
Command("openssl")(RA.From("version"))(B.Monoid.Empty()),
|
||||
ioeither.Map[error](F.Flow3(
|
||||
exec.StdOut,
|
||||
B.ToString,
|
||||
strings.TrimSpace,
|
||||
)),
|
||||
)
|
||||
|
||||
assert.True(t, E.IsRight(version()))
|
||||
}
|
||||
36
v2/ioresult/file/dir.go
Normal file
36
v2/ioresult/file/dir.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/IBM/fp-go/v2/ioeither/file"
|
||||
)
|
||||
|
||||
// MkdirAll create a sequence of directories, see [os.MkdirAll]
|
||||
//
|
||||
//go:inline
|
||||
func MkdirAll(path string, perm os.FileMode) IOResult[string] {
|
||||
return file.MkdirAll(path, perm)
|
||||
}
|
||||
|
||||
// Mkdir create a directory, see [os.Mkdir]
|
||||
//
|
||||
//go:inline
|
||||
func Mkdir(path string, perm os.FileMode) IOResult[string] {
|
||||
return file.Mkdir(path, perm)
|
||||
}
|
||||
53
v2/ioresult/file/file.go
Normal file
53
v2/ioresult/file/file.go
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/IBM/fp-go/v2/ioeither/file"
|
||||
)
|
||||
|
||||
var (
|
||||
// Open opens a file for reading
|
||||
Open = file.Open
|
||||
// Create opens a file for writing
|
||||
Create = file.Create
|
||||
// ReadFile reads the context of a file
|
||||
ReadFile = file.ReadFile
|
||||
)
|
||||
|
||||
// WriteFile writes a data blob to a file
|
||||
//
|
||||
//go:inline
|
||||
func WriteFile(dstName string, perm os.FileMode) Kleisli[[]byte, []byte] {
|
||||
return file.WriteFile(dstName, perm)
|
||||
}
|
||||
|
||||
// Remove removes a file by name
|
||||
//
|
||||
//go:inline
|
||||
func Remove(name string) IOResult[string] {
|
||||
return file.Remove(name)
|
||||
}
|
||||
|
||||
// Close closes an object
|
||||
//
|
||||
//go:inline
|
||||
func Close[C io.Closer](c C) IOResult[any] {
|
||||
return file.Close(c)
|
||||
}
|
||||
29
v2/ioresult/file/readall.go
Normal file
29
v2/ioresult/file/readall.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/IBM/fp-go/v2/ioeither/file"
|
||||
)
|
||||
|
||||
// ReadAll uses a generator function to create a stream, reads it and closes it
|
||||
//
|
||||
//go:inline
|
||||
func ReadAll[R io.ReadCloser](acquire IOResult[R]) IOResult[[]byte] {
|
||||
return file.ReadAll(acquire)
|
||||
}
|
||||
34
v2/ioresult/file/tempfile.go
Normal file
34
v2/ioresult/file/tempfile.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/IBM/fp-go/v2/ioeither/file"
|
||||
)
|
||||
|
||||
var (
|
||||
// CreateTemp created a temp file with proper parametrization
|
||||
CreateTemp = file.CreateTemp
|
||||
)
|
||||
|
||||
// WithTempFile creates a temporary filthen invokes a callback to create a resource based on the filthen close and remove the temp file
|
||||
//
|
||||
//go:inline
|
||||
func WithTempFile[A any](f Kleisli[*os.File, A]) IOResult[A] {
|
||||
return file.WithTempFile(f)
|
||||
}
|
||||
9
v2/ioresult/file/types.go
Normal file
9
v2/ioresult/file/types.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package file
|
||||
|
||||
import "github.com/IBM/fp-go/v2/ioresult"
|
||||
|
||||
type (
|
||||
IOResult[T any] = ioresult.IOResult[T]
|
||||
Kleisli[A, B any] = ioresult.Kleisli[A, B]
|
||||
Operator[A, B any] = ioresult.Operator[A, B]
|
||||
)
|
||||
36
v2/ioresult/file/write.go
Normal file
36
v2/ioresult/file/write.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package file
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/IBM/fp-go/v2/ioeither/file"
|
||||
)
|
||||
|
||||
// WriteAll uses a generator function to create a stream, writes data to it and closes it
|
||||
//
|
||||
//go:inline
|
||||
func WriteAll[W io.WriteCloser](data []byte) Operator[W, []byte] {
|
||||
return file.WriteAll[W](data)
|
||||
}
|
||||
|
||||
// Write uses a generator function to create a stream, writes data to it and closes it
|
||||
//
|
||||
//go:inline
|
||||
func Write[R any, W io.WriteCloser](acquire IOResult[W]) Kleisli[Kleisli[W, R], R] {
|
||||
return file.Write[R](acquire)
|
||||
}
|
||||
989
v2/ioresult/gen.go
Normal file
989
v2/ioresult/gen.go
Normal file
@@ -0,0 +1,989 @@
|
||||
// Code generated by go generate; DO NOT EDIT.
|
||||
// This file was generated by robots at
|
||||
// 2025-03-09 23:53:07.5974468 +0100 CET m=+0.008920801
|
||||
|
||||
package ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
"github.com/IBM/fp-go/v2/tuple"
|
||||
)
|
||||
|
||||
// Eitherize0 converts a function with 1 parameters returning a tuple into a function with 0 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize0[F ~func() (R, error), R any](f F) func() IOResult[R] {
|
||||
return ioeither.Eitherize0(f)
|
||||
}
|
||||
|
||||
// Uneitherize0 converts a function with 1 parameters returning a tuple into a function with 0 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize0[F ~func() IOResult[R], R any](f F) func() (R, error) {
|
||||
return ioeither.Uneitherize0(f)
|
||||
}
|
||||
|
||||
// Eitherize1 converts a function with 2 parameters returning a tuple into a function with 1 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize1[F ~func(T1) (R, error), T1, R any](f F) func(T1) IOResult[R] {
|
||||
return ioeither.Eitherize1(f)
|
||||
}
|
||||
|
||||
// Uneitherize1 converts a function with 2 parameters returning a tuple into a function with 1 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize1[F ~func(T1) IOResult[R], T1, R any](f F) func(T1) (R, error) {
|
||||
return ioeither.Uneitherize1(f)
|
||||
}
|
||||
|
||||
// SequenceT1 converts 1 [IOResult[T]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT1[T1 any](
|
||||
t1 IOResult[T1],
|
||||
) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.SequenceParT1(t1)
|
||||
}
|
||||
|
||||
// SequenceSeqT1 converts 1 [IOResult[T]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT1[T1 any](
|
||||
t1 IOResult[T1],
|
||||
) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.SequenceSeqT1(t1)
|
||||
}
|
||||
|
||||
// SequenceParT1 converts 1 [IOResult[T]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT1[T1 any](
|
||||
t1 IOResult[T1],
|
||||
) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.SequenceParT1(t1)
|
||||
}
|
||||
|
||||
// SequenceTuple1 converts a [tuple.Tuple1[IOResult[T]]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple1[T1 any](t tuple.Tuple1[IOResult[T1]]) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.SequenceTuple1(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple1 converts a [tuple.Tuple1[IOResult[T]]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple1[T1 any](t tuple.Tuple1[IOResult[T1]]) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.SequenceSeqTuple1(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple1 converts a [tuple.Tuple1[IOResult[T]]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple1[T1 any](t tuple.Tuple1[IOResult[T1]]) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.SequenceParTuple1(t)
|
||||
}
|
||||
|
||||
// TraverseTuple1 converts a [tuple.Tuple1[A1]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple1[F1 ~func(A1) IOResult[T1], T1, A1 any](f1 F1) func(tuple.Tuple1[A1]) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.TraverseTuple1(f1)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple1 converts a [tuple.Tuple1[A1]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple1[F1 ~func(A1) IOResult[T1], T1, A1 any](f1 F1) func(tuple.Tuple1[A1]) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.TraverseSeqTuple1(f1)
|
||||
}
|
||||
|
||||
// TraverseParTuple1 converts a [tuple.Tuple1[A1]] into a [IOResult[tuple.Tuple1[T1]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple1[F1 ~func(A1) IOResult[T1], T1, A1 any](f1 F1) func(tuple.Tuple1[A1]) IOResult[tuple.Tuple1[T1]] {
|
||||
return ioeither.TraverseParTuple1(f1)
|
||||
}
|
||||
|
||||
// Eitherize2 converts a function with 3 parameters returning a tuple into a function with 2 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize2[F ~func(T1, T2) (R, error), T1, T2, R any](f F) func(T1, T2) IOResult[R] {
|
||||
return ioeither.Eitherize2(f)
|
||||
}
|
||||
|
||||
// Uneitherize2 converts a function with 3 parameters returning a tuple into a function with 2 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize2[F ~func(T1, T2) IOResult[R], T1, T2, R any](f F) func(T1, T2) (R, error) {
|
||||
return ioeither.Uneitherize2(f)
|
||||
}
|
||||
|
||||
// SequenceT2 converts 2 [IOResult[T]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT2[T1, T2 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.SequenceT2(t1, t2)
|
||||
}
|
||||
|
||||
// SequenceSeqT2 converts 2 [IOResult[T]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT2[T1, T2 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.SequenceSeqT2(t1, t2)
|
||||
}
|
||||
|
||||
// SequenceParT2 converts 2 [IOResult[T]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT2[T1, T2 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.SequenceParT2(t1, t2)
|
||||
}
|
||||
|
||||
// SequenceTuple2 converts a [tuple.Tuple2[IOResult[T]]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple2[T1, T2 any](t tuple.Tuple2[IOResult[T1], IOResult[T2]]) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.SequenceTuple2(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple2 converts a [tuple.Tuple2[IOResult[T]]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple2[T1, T2 any](t tuple.Tuple2[IOResult[T1], IOResult[T2]]) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.SequenceSeqTuple2(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple2 converts a [tuple.Tuple2[IOResult[T]]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple2[T1, T2 any](t tuple.Tuple2[IOResult[T1], IOResult[T2]]) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.SequenceParTuple2(t)
|
||||
}
|
||||
|
||||
// TraverseTuple2 converts a [tuple.Tuple2[A1, A2]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple2[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], T1, T2, A1, A2 any](f1 F1, f2 F2) func(tuple.Tuple2[A1, A2]) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.TraverseTuple2(f1, f2)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple2 converts a [tuple.Tuple2[A1, A2]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple2[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], T1, T2, A1, A2 any](f1 F1, f2 F2) func(tuple.Tuple2[A1, A2]) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.TraverseSeqTuple2(f1, f2)
|
||||
}
|
||||
|
||||
// TraverseParTuple2 converts a [tuple.Tuple2[A1, A2]] into a [IOResult[tuple.Tuple2[T1, T2]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple2[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], T1, T2, A1, A2 any](f1 F1, f2 F2) func(tuple.Tuple2[A1, A2]) IOResult[tuple.Tuple2[T1, T2]] {
|
||||
return ioeither.TraverseParTuple2(f1, f2)
|
||||
}
|
||||
|
||||
// Eitherize3 converts a function with 4 parameters returning a tuple into a function with 3 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize3[F ~func(T1, T2, T3) (R, error), T1, T2, T3, R any](f F) func(T1, T2, T3) IOResult[R] {
|
||||
return ioeither.Eitherize3(f)
|
||||
}
|
||||
|
||||
// Uneitherize3 converts a function with 4 parameters returning a tuple into a function with 3 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize3[F ~func(T1, T2, T3) IOResult[R], T1, T2, T3, R any](f F) func(T1, T2, T3) (R, error) {
|
||||
return ioeither.Uneitherize3(f)
|
||||
}
|
||||
|
||||
// SequenceT3 converts 3 [IOResult[T]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT3[T1, T2, T3 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.SequenceT3(t1, t2, t3)
|
||||
}
|
||||
|
||||
// SequenceSeqT3 converts 3 [IOResult[T]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT3[T1, T2, T3 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.SequenceSeqT3(t1, t2, t3)
|
||||
}
|
||||
|
||||
// SequenceParT3 converts 3 [IOResult[T]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT3[T1, T2, T3 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.SequenceParT3(t1, t2, t3)
|
||||
}
|
||||
|
||||
// SequenceTuple3 converts a [tuple.Tuple3[IOResult[T]]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple3[T1, T2, T3 any](t tuple.Tuple3[IOResult[T1], IOResult[T2], IOResult[T3]]) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.SequenceTuple3(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple3 converts a [tuple.Tuple3[IOResult[T]]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple3[T1, T2, T3 any](t tuple.Tuple3[IOResult[T1], IOResult[T2], IOResult[T3]]) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.SequenceSeqTuple3(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple3 converts a [tuple.Tuple3[IOResult[T]]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple3[T1, T2, T3 any](t tuple.Tuple3[IOResult[T1], IOResult[T2], IOResult[T3]]) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.SequenceParTuple3(t)
|
||||
}
|
||||
|
||||
// TraverseTuple3 converts a [tuple.Tuple3[A1, A2, A3]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple3[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], T1, T2, T3, A1, A2, A3 any](f1 F1, f2 F2, f3 F3) func(tuple.Tuple3[A1, A2, A3]) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.TraverseTuple3(f1, f2, f3)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple3 converts a [tuple.Tuple3[A1, A2, A3]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple3[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], T1, T2, T3, A1, A2, A3 any](f1 F1, f2 F2, f3 F3) func(tuple.Tuple3[A1, A2, A3]) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.TraverseSeqTuple3(f1, f2, f3)
|
||||
}
|
||||
|
||||
// TraverseParTuple3 converts a [tuple.Tuple3[A1, A2, A3]] into a [IOResult[tuple.Tuple3[T1, T2, T3]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple3[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], T1, T2, T3, A1, A2, A3 any](f1 F1, f2 F2, f3 F3) func(tuple.Tuple3[A1, A2, A3]) IOResult[tuple.Tuple3[T1, T2, T3]] {
|
||||
return ioeither.TraverseParTuple3(f1, f2, f3)
|
||||
}
|
||||
|
||||
// Eitherize4 converts a function with 5 parameters returning a tuple into a function with 4 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize4[F ~func(T1, T2, T3, T4) (R, error), T1, T2, T3, T4, R any](f F) func(T1, T2, T3, T4) IOResult[R] {
|
||||
return ioeither.Eitherize4(f)
|
||||
}
|
||||
|
||||
// Uneitherize4 converts a function with 5 parameters returning a tuple into a function with 4 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize4[F ~func(T1, T2, T3, T4) IOResult[R], T1, T2, T3, T4, R any](f F) func(T1, T2, T3, T4) (R, error) {
|
||||
return ioeither.Uneitherize4(f)
|
||||
}
|
||||
|
||||
// SequenceT4 converts 4 [IOResult[T]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT4[T1, T2, T3, T4 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.SequenceT4(t1, t2, t3, t4)
|
||||
}
|
||||
|
||||
// SequenceSeqT4 converts 4 [IOResult[T]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT4[T1, T2, T3, T4 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.SequenceSeqT4(t1, t2, t3, t4)
|
||||
}
|
||||
|
||||
// SequenceParT4 converts 4 [IOResult[T]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT4[T1, T2, T3, T4 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.SequenceParT4(t1, t2, t3, t4)
|
||||
}
|
||||
|
||||
// SequenceTuple4 converts a [tuple.Tuple4[IOResult[T]]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple4[T1, T2, T3, T4 any](t tuple.Tuple4[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4]]) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.SequenceTuple4(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple4 converts a [tuple.Tuple4[IOResult[T]]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple4[T1, T2, T3, T4 any](t tuple.Tuple4[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4]]) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.SequenceSeqTuple4(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple4 converts a [tuple.Tuple4[IOResult[T]]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple4[T1, T2, T3, T4 any](t tuple.Tuple4[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4]]) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.SequenceParTuple4(t)
|
||||
}
|
||||
|
||||
// TraverseTuple4 converts a [tuple.Tuple4[A1, A2, A3, A4]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple4[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], T1, T2, T3, T4, A1, A2, A3, A4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(tuple.Tuple4[A1, A2, A3, A4]) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.TraverseTuple4(f1, f2, f3, f4)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple4 converts a [tuple.Tuple4[A1, A2, A3, A4]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple4[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], T1, T2, T3, T4, A1, A2, A3, A4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(tuple.Tuple4[A1, A2, A3, A4]) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.TraverseSeqTuple4(f1, f2, f3, f4)
|
||||
}
|
||||
|
||||
// TraverseParTuple4 converts a [tuple.Tuple4[A1, A2, A3, A4]] into a [IOResult[tuple.Tuple4[T1, T2, T3, T4]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple4[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], T1, T2, T3, T4, A1, A2, A3, A4 any](f1 F1, f2 F2, f3 F3, f4 F4) func(tuple.Tuple4[A1, A2, A3, A4]) IOResult[tuple.Tuple4[T1, T2, T3, T4]] {
|
||||
return ioeither.TraverseParTuple4(f1, f2, f3, f4)
|
||||
}
|
||||
|
||||
// Eitherize5 converts a function with 6 parameters returning a tuple into a function with 5 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize5[F ~func(T1, T2, T3, T4, T5) (R, error), T1, T2, T3, T4, T5, R any](f F) func(T1, T2, T3, T4, T5) IOResult[R] {
|
||||
return ioeither.Eitherize5(f)
|
||||
}
|
||||
|
||||
// Uneitherize5 converts a function with 6 parameters returning a tuple into a function with 5 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize5[F ~func(T1, T2, T3, T4, T5) IOResult[R], T1, T2, T3, T4, T5, R any](f F) func(T1, T2, T3, T4, T5) (R, error) {
|
||||
return ioeither.Uneitherize5(f)
|
||||
}
|
||||
|
||||
// SequenceT5 converts 5 [IOResult[T]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT5[T1, T2, T3, T4, T5 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.SequenceT5(t1, t2, t3, t4, t5)
|
||||
}
|
||||
|
||||
// SequenceSeqT5 converts 5 [IOResult[T]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT5[T1, T2, T3, T4, T5 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.SequenceSeqT5(t1, t2, t3, t4, t5)
|
||||
}
|
||||
|
||||
// SequenceParT5 converts 5 [IOResult[T]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT5[T1, T2, T3, T4, T5 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.SequenceParT5(t1, t2, t3, t4, t5)
|
||||
}
|
||||
|
||||
// SequenceTuple5 converts a [tuple.Tuple5[IOResult[T]]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple5[T1, T2, T3, T4, T5 any](t tuple.Tuple5[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5]]) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.SequenceTuple5(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple5 converts a [tuple.Tuple5[IOResult[T]]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple5[T1, T2, T3, T4, T5 any](t tuple.Tuple5[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5]]) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.SequenceSeqTuple5(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple5 converts a [tuple.Tuple5[IOResult[T]]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple5[T1, T2, T3, T4, T5 any](t tuple.Tuple5[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5]]) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.SequenceParTuple5(t)
|
||||
}
|
||||
|
||||
// TraverseTuple5 converts a [tuple.Tuple5[A1, A2, A3, A4, A5]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple5[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], T1, T2, T3, T4, T5, A1, A2, A3, A4, A5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(tuple.Tuple5[A1, A2, A3, A4, A5]) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.TraverseTuple5(f1, f2, f3, f4, f5)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple5 converts a [tuple.Tuple5[A1, A2, A3, A4, A5]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple5[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], T1, T2, T3, T4, T5, A1, A2, A3, A4, A5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(tuple.Tuple5[A1, A2, A3, A4, A5]) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.TraverseSeqTuple5(f1, f2, f3, f4, f5)
|
||||
}
|
||||
|
||||
// TraverseParTuple5 converts a [tuple.Tuple5[A1, A2, A3, A4, A5]] into a [IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple5[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], T1, T2, T3, T4, T5, A1, A2, A3, A4, A5 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5) func(tuple.Tuple5[A1, A2, A3, A4, A5]) IOResult[tuple.Tuple5[T1, T2, T3, T4, T5]] {
|
||||
return ioeither.TraverseParTuple5(f1, f2, f3, f4, f5)
|
||||
}
|
||||
|
||||
// Eitherize6 converts a function with 7 parameters returning a tuple into a function with 6 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize6[F ~func(T1, T2, T3, T4, T5, T6) (R, error), T1, T2, T3, T4, T5, T6, R any](f F) func(T1, T2, T3, T4, T5, T6) IOResult[R] {
|
||||
return ioeither.Eitherize6(f)
|
||||
}
|
||||
|
||||
// Uneitherize6 converts a function with 7 parameters returning a tuple into a function with 6 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize6[F ~func(T1, T2, T3, T4, T5, T6) IOResult[R], T1, T2, T3, T4, T5, T6, R any](f F) func(T1, T2, T3, T4, T5, T6) (R, error) {
|
||||
return ioeither.Uneitherize6(f)
|
||||
}
|
||||
|
||||
// SequenceT6 converts 6 [IOResult[T]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT6[T1, T2, T3, T4, T5, T6 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.SequenceT6(t1, t2, t3, t4, t5, t6)
|
||||
}
|
||||
|
||||
// SequenceSeqT6 converts 6 [IOResult[T]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT6[T1, T2, T3, T4, T5, T6 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.SequenceSeqT6(t1, t2, t3, t4, t5, t6)
|
||||
}
|
||||
|
||||
// SequenceParT6 converts 6 [IOResult[T]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT6[T1, T2, T3, T4, T5, T6 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.SequenceParT6(t1, t2, t3, t4, t5, t6)
|
||||
}
|
||||
|
||||
// SequenceTuple6 converts a [tuple.Tuple6[IOResult[T]]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple6[T1, T2, T3, T4, T5, T6 any](t tuple.Tuple6[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6]]) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.SequenceTuple6(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple6 converts a [tuple.Tuple6[IOResult[T]]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple6[T1, T2, T3, T4, T5, T6 any](t tuple.Tuple6[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6]]) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.SequenceSeqTuple6(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple6 converts a [tuple.Tuple6[IOResult[T]]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple6[T1, T2, T3, T4, T5, T6 any](t tuple.Tuple6[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6]]) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.SequenceParTuple6(t)
|
||||
}
|
||||
|
||||
// TraverseTuple6 converts a [tuple.Tuple6[A1, A2, A3, A4, A5, A6]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple6[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], T1, T2, T3, T4, T5, T6, A1, A2, A3, A4, A5, A6 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(tuple.Tuple6[A1, A2, A3, A4, A5, A6]) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.TraverseTuple6(f1, f2, f3, f4, f5, f6)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple6 converts a [tuple.Tuple6[A1, A2, A3, A4, A5, A6]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple6[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], T1, T2, T3, T4, T5, T6, A1, A2, A3, A4, A5, A6 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(tuple.Tuple6[A1, A2, A3, A4, A5, A6]) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.TraverseSeqTuple6(f1, f2, f3, f4, f5, f6)
|
||||
}
|
||||
|
||||
// TraverseParTuple6 converts a [tuple.Tuple6[A1, A2, A3, A4, A5, A6]] into a [IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple6[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], T1, T2, T3, T4, T5, T6, A1, A2, A3, A4, A5, A6 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6) func(tuple.Tuple6[A1, A2, A3, A4, A5, A6]) IOResult[tuple.Tuple6[T1, T2, T3, T4, T5, T6]] {
|
||||
return ioeither.TraverseParTuple6(f1, f2, f3, f4, f5, f6)
|
||||
}
|
||||
|
||||
// Eitherize7 converts a function with 8 parameters returning a tuple into a function with 7 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize7[F ~func(T1, T2, T3, T4, T5, T6, T7) (R, error), T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T1, T2, T3, T4, T5, T6, T7) IOResult[R] {
|
||||
return ioeither.Eitherize7(f)
|
||||
}
|
||||
|
||||
// Uneitherize7 converts a function with 8 parameters returning a tuple into a function with 7 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize7[F ~func(T1, T2, T3, T4, T5, T6, T7) IOResult[R], T1, T2, T3, T4, T5, T6, T7, R any](f F) func(T1, T2, T3, T4, T5, T6, T7) (R, error) {
|
||||
return ioeither.Uneitherize7(f)
|
||||
}
|
||||
|
||||
// SequenceT7 converts 7 [IOResult[T]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT7[T1, T2, T3, T4, T5, T6, T7 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.SequenceT7(t1, t2, t3, t4, t5, t6, t7)
|
||||
}
|
||||
|
||||
// SequenceSeqT7 converts 7 [IOResult[T]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT7[T1, T2, T3, T4, T5, T6, T7 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.SequenceSeqT7(t1, t2, t3, t4, t5, t6, t7)
|
||||
}
|
||||
|
||||
// SequenceParT7 converts 7 [IOResult[T]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT7[T1, T2, T3, T4, T5, T6, T7 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.SequenceParT7(t1, t2, t3, t4, t5, t6, t7)
|
||||
}
|
||||
|
||||
// SequenceTuple7 converts a [tuple.Tuple7[IOResult[T]]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple7[T1, T2, T3, T4, T5, T6, T7 any](t tuple.Tuple7[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7]]) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.SequenceTuple7(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple7 converts a [tuple.Tuple7[IOResult[T]]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple7[T1, T2, T3, T4, T5, T6, T7 any](t tuple.Tuple7[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7]]) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.SequenceSeqTuple7(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple7 converts a [tuple.Tuple7[IOResult[T]]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple7[T1, T2, T3, T4, T5, T6, T7 any](t tuple.Tuple7[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7]]) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.SequenceParTuple7(t)
|
||||
}
|
||||
|
||||
// TraverseTuple7 converts a [tuple.Tuple7[A1, A2, A3, A4, A5, A6, A7]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple7[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], T1, T2, T3, T4, T5, T6, T7, A1, A2, A3, A4, A5, A6, A7 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(tuple.Tuple7[A1, A2, A3, A4, A5, A6, A7]) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.TraverseTuple7(f1, f2, f3, f4, f5, f6, f7)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple7 converts a [tuple.Tuple7[A1, A2, A3, A4, A5, A6, A7]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple7[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], T1, T2, T3, T4, T5, T6, T7, A1, A2, A3, A4, A5, A6, A7 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(tuple.Tuple7[A1, A2, A3, A4, A5, A6, A7]) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.TraverseSeqTuple7(f1, f2, f3, f4, f5, f6, f7)
|
||||
}
|
||||
|
||||
// TraverseParTuple7 converts a [tuple.Tuple7[A1, A2, A3, A4, A5, A6, A7]] into a [IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple7[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], T1, T2, T3, T4, T5, T6, T7, A1, A2, A3, A4, A5, A6, A7 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7) func(tuple.Tuple7[A1, A2, A3, A4, A5, A6, A7]) IOResult[tuple.Tuple7[T1, T2, T3, T4, T5, T6, T7]] {
|
||||
return ioeither.TraverseParTuple7(f1, f2, f3, f4, f5, f6, f7)
|
||||
}
|
||||
|
||||
// Eitherize8 converts a function with 9 parameters returning a tuple into a function with 8 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize8[F ~func(T1, T2, T3, T4, T5, T6, T7, T8) (R, error), T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8) IOResult[R] {
|
||||
return ioeither.Eitherize8(f)
|
||||
}
|
||||
|
||||
// Uneitherize8 converts a function with 9 parameters returning a tuple into a function with 8 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize8[F ~func(T1, T2, T3, T4, T5, T6, T7, T8) IOResult[R], T1, T2, T3, T4, T5, T6, T7, T8, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8) (R, error) {
|
||||
return ioeither.Uneitherize8(f)
|
||||
}
|
||||
|
||||
// SequenceT8 converts 8 [IOResult[T]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT8[T1, T2, T3, T4, T5, T6, T7, T8 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.SequenceT8(t1, t2, t3, t4, t5, t6, t7, t8)
|
||||
}
|
||||
|
||||
// SequenceSeqT8 converts 8 [IOResult[T]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT8[T1, T2, T3, T4, T5, T6, T7, T8 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.SequenceSeqT8(t1, t2, t3, t4, t5, t6, t7, t8)
|
||||
}
|
||||
|
||||
// SequenceParT8 converts 8 [IOResult[T]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT8[T1, T2, T3, T4, T5, T6, T7, T8 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.SequenceParT8(t1, t2, t3, t4, t5, t6, t7, t8)
|
||||
}
|
||||
|
||||
// SequenceTuple8 converts a [tuple.Tuple8[IOResult[T]]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple8[T1, T2, T3, T4, T5, T6, T7, T8 any](t tuple.Tuple8[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8]]) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.SequenceTuple8(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple8 converts a [tuple.Tuple8[IOResult[T]]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple8[T1, T2, T3, T4, T5, T6, T7, T8 any](t tuple.Tuple8[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8]]) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.SequenceSeqTuple8(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple8 converts a [tuple.Tuple8[IOResult[T]]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple8[T1, T2, T3, T4, T5, T6, T7, T8 any](t tuple.Tuple8[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8]]) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.SequenceParTuple8(t)
|
||||
}
|
||||
|
||||
// TraverseTuple8 converts a [tuple.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple8[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], T1, T2, T3, T4, T5, T6, T7, T8, A1, A2, A3, A4, A5, A6, A7, A8 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(tuple.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.TraverseTuple8(f1, f2, f3, f4, f5, f6, f7, f8)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple8 converts a [tuple.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple8[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], T1, T2, T3, T4, T5, T6, T7, T8, A1, A2, A3, A4, A5, A6, A7, A8 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(tuple.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.TraverseSeqTuple8(f1, f2, f3, f4, f5, f6, f7, f8)
|
||||
}
|
||||
|
||||
// TraverseParTuple8 converts a [tuple.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] into a [IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple8[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], T1, T2, T3, T4, T5, T6, T7, T8, A1, A2, A3, A4, A5, A6, A7, A8 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8) func(tuple.Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]) IOResult[tuple.Tuple8[T1, T2, T3, T4, T5, T6, T7, T8]] {
|
||||
return ioeither.TraverseParTuple8(f1, f2, f3, f4, f5, f6, f7, f8)
|
||||
}
|
||||
|
||||
// Eitherize9 converts a function with 10 parameters returning a tuple into a function with 9 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize9[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error), T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9) IOResult[R] {
|
||||
return ioeither.Eitherize9(f)
|
||||
}
|
||||
|
||||
// Uneitherize9 converts a function with 10 parameters returning a tuple into a function with 9 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize9[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9) IOResult[R], T1, T2, T3, T4, T5, T6, T7, T8, T9, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9) (R, error) {
|
||||
return ioeither.Uneitherize9(f)
|
||||
}
|
||||
|
||||
// SequenceT9 converts 9 [IOResult[T]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
t9 IOResult[T9],
|
||||
) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.SequenceT9(t1, t2, t3, t4, t5, t6, t7, t8, t9)
|
||||
}
|
||||
|
||||
// SequenceSeqT9 converts 9 [IOResult[T]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
t9 IOResult[T9],
|
||||
) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.SequenceSeqT9(t1, t2, t3, t4, t5, t6, t7, t8, t9)
|
||||
}
|
||||
|
||||
// SequenceParT9 converts 9 [IOResult[T]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
t9 IOResult[T9],
|
||||
) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.SequenceParT9(t1, t2, t3, t4, t5, t6, t7, t8, t9)
|
||||
}
|
||||
|
||||
// SequenceTuple9 converts a [tuple.Tuple9[IOResult[T]]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t tuple.Tuple9[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8], IOResult[T9]]) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.SequenceTuple9(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple9 converts a [tuple.Tuple9[IOResult[T]]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t tuple.Tuple9[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8], IOResult[T9]]) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.SequenceSeqTuple9(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple9 converts a [tuple.Tuple9[IOResult[T]]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9 any](t tuple.Tuple9[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8], IOResult[T9]]) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.SequenceParTuple9(t)
|
||||
}
|
||||
|
||||
// TraverseTuple9 converts a [tuple.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple9[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], F9 ~func(A9) IOResult[T9], T1, T2, T3, T4, T5, T6, T7, T8, T9, A1, A2, A3, A4, A5, A6, A7, A8, A9 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) func(tuple.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.TraverseTuple9(f1, f2, f3, f4, f5, f6, f7, f8, f9)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple9 converts a [tuple.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple9[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], F9 ~func(A9) IOResult[T9], T1, T2, T3, T4, T5, T6, T7, T8, T9, A1, A2, A3, A4, A5, A6, A7, A8, A9 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) func(tuple.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.TraverseSeqTuple9(f1, f2, f3, f4, f5, f6, f7, f8, f9)
|
||||
}
|
||||
|
||||
// TraverseParTuple9 converts a [tuple.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] into a [IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple9[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], F9 ~func(A9) IOResult[T9], T1, T2, T3, T4, T5, T6, T7, T8, T9, A1, A2, A3, A4, A5, A6, A7, A8, A9 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9) func(tuple.Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]) IOResult[tuple.Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9]] {
|
||||
return ioeither.TraverseParTuple9(f1, f2, f3, f4, f5, f6, f7, f8, f9)
|
||||
}
|
||||
|
||||
// Eitherize10 converts a function with 11 parameters returning a tuple into a function with 10 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Eitherize10[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) (R, error), T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) IOResult[R] {
|
||||
return ioeither.Eitherize10(f)
|
||||
}
|
||||
|
||||
// Uneitherize10 converts a function with 11 parameters returning a tuple into a function with 10 parameters returning a [IOResult[R]]
|
||||
//
|
||||
//go:inline
|
||||
func Uneitherize10[F ~func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) IOResult[R], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R any](f F) func(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) (R, error) {
|
||||
return ioeither.Uneitherize10(f)
|
||||
}
|
||||
|
||||
// SequenceT10 converts 10 [IOResult[T]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceT10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
t9 IOResult[T9],
|
||||
t10 IOResult[T10],
|
||||
) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.SequenceT10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)
|
||||
}
|
||||
|
||||
// SequenceSeqT10 converts 10 [IOResult[T]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqT10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
t9 IOResult[T9],
|
||||
t10 IOResult[T10],
|
||||
) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.SequenceSeqT10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)
|
||||
}
|
||||
|
||||
// SequenceParT10 converts 10 [IOResult[T]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParT10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](
|
||||
t1 IOResult[T1],
|
||||
t2 IOResult[T2],
|
||||
t3 IOResult[T3],
|
||||
t4 IOResult[T4],
|
||||
t5 IOResult[T5],
|
||||
t6 IOResult[T6],
|
||||
t7 IOResult[T7],
|
||||
t8 IOResult[T8],
|
||||
t9 IOResult[T9],
|
||||
t10 IOResult[T10],
|
||||
) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.SequenceParT10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)
|
||||
}
|
||||
|
||||
// SequenceTuple10 converts a [tuple.Tuple10[IOResult[T]]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t tuple.Tuple10[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8], IOResult[T9], IOResult[T10]]) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.SequenceTuple10(t)
|
||||
}
|
||||
|
||||
// SequenceSeqTuple10 converts a [tuple.Tuple10[IOResult[T]]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceSeqTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t tuple.Tuple10[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8], IOResult[T9], IOResult[T10]]) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.SequenceSeqTuple10(t)
|
||||
}
|
||||
|
||||
// SequenceParTuple10 converts a [tuple.Tuple10[IOResult[T]]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func SequenceParTuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 any](t tuple.Tuple10[IOResult[T1], IOResult[T2], IOResult[T3], IOResult[T4], IOResult[T5], IOResult[T6], IOResult[T7], IOResult[T8], IOResult[T9], IOResult[T10]]) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.SequenceParTuple10(t)
|
||||
}
|
||||
|
||||
// TraverseTuple10 converts a [tuple.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseTuple10[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], F9 ~func(A9) IOResult[T9], F10 ~func(A10) IOResult[T10], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) func(tuple.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.TraverseTuple10(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)
|
||||
}
|
||||
|
||||
// TraverseSeqTuple10 converts a [tuple.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseSeqTuple10[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], F9 ~func(A9) IOResult[T9], F10 ~func(A10) IOResult[T10], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) func(tuple.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.TraverseSeqTuple10(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)
|
||||
}
|
||||
|
||||
// TraverseParTuple10 converts a [tuple.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]] into a [IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]]]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseParTuple10[F1 ~func(A1) IOResult[T1], F2 ~func(A2) IOResult[T2], F3 ~func(A3) IOResult[T3], F4 ~func(A4) IOResult[T4], F5 ~func(A5) IOResult[T5], F6 ~func(A6) IOResult[T6], F7 ~func(A7) IOResult[T7], F8 ~func(A8) IOResult[T8], F9 ~func(A9) IOResult[T9], F10 ~func(A10) IOResult[T10], T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 any](f1 F1, f2 F2, f3 F3, f4 F4, f5 F5, f6 F6, f7 F7, f8 F8, f9 F9, f10 F10) func(tuple.Tuple10[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10]) IOResult[tuple.Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]] {
|
||||
return ioeither.TraverseParTuple10(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)
|
||||
}
|
||||
27
v2/ioresult/http/builder/builder.go
Normal file
27
v2/ioresult/http/builder/builder.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package builder
|
||||
|
||||
import (
|
||||
R "github.com/IBM/fp-go/v2/http/builder"
|
||||
IOEHB "github.com/IBM/fp-go/v2/ioeither/http/builder"
|
||||
IORH "github.com/IBM/fp-go/v2/ioresult/http"
|
||||
)
|
||||
|
||||
//go:inline
|
||||
func Requester(builder *R.Builder) IORH.Requester {
|
||||
return IOEHB.Requester(builder)
|
||||
}
|
||||
58
v2/ioresult/http/builder/builder_test.go
Normal file
58
v2/ioresult/http/builder/builder_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package builder
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
R "github.com/IBM/fp-go/v2/http/builder"
|
||||
"github.com/IBM/fp-go/v2/io"
|
||||
"github.com/IBM/fp-go/v2/ioresult"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBuilderWithQuery(t *testing.T) {
|
||||
// add some query
|
||||
withLimit := R.WithQueryArg("limit")("10")
|
||||
withURL := R.WithURL("http://www.example.org?a=b")
|
||||
|
||||
b := F.Pipe2(
|
||||
R.Default,
|
||||
withLimit,
|
||||
withURL,
|
||||
)
|
||||
|
||||
req := F.Pipe3(
|
||||
b,
|
||||
Requester,
|
||||
ioresult.Map(func(r *http.Request) *url.URL {
|
||||
return r.URL
|
||||
}),
|
||||
ioresult.ChainFirstIOK(func(u *url.URL) io.IO[any] {
|
||||
return io.FromImpure(func() {
|
||||
q := u.Query()
|
||||
assert.Equal(t, "10", q.Get("limit"))
|
||||
assert.Equal(t, "b", q.Get("a"))
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
assert.True(t, E.IsRight(req()))
|
||||
}
|
||||
24
v2/ioresult/http/builder/types.go
Normal file
24
v2/ioresult/http/builder/types.go
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package builder
|
||||
|
||||
import "github.com/IBM/fp-go/v2/ioresult"
|
||||
|
||||
type (
|
||||
IOResult[T any] = ioresult.IOResult[T]
|
||||
Kleisli[A, B any] = ioresult.Kleisli[A, B]
|
||||
Operator[A, B any] = ioresult.Operator[A, B]
|
||||
)
|
||||
28
v2/ioresult/http/di/di.go
Normal file
28
v2/ioresult/http/di/di.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package di
|
||||
|
||||
import (
|
||||
IOEHDI "github.com/IBM/fp-go/v2/ioeither/http/di"
|
||||
)
|
||||
|
||||
var (
|
||||
// InjHttpClient is the [DI.InjectionToken] for the [http.DefaultClient]
|
||||
InjHttpClient = IOEHDI.InjHttpClient
|
||||
|
||||
// InjClient is the [DI.InjectionToken] for the default [IOEH.Client]
|
||||
InjClient = IOEHDI.InjClient
|
||||
)
|
||||
78
v2/ioresult/http/request.go
Normal file
78
v2/ioresult/http/request.go
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
H "github.com/IBM/fp-go/v2/http"
|
||||
IOEH "github.com/IBM/fp-go/v2/ioeither/http"
|
||||
)
|
||||
|
||||
type (
|
||||
// Requester is a reader that constructs a request
|
||||
Requester = IOEH.Requester
|
||||
|
||||
Client = IOEH.Client
|
||||
)
|
||||
|
||||
var (
|
||||
// MakeRequest is an eitherized version of [http.NewRequest]
|
||||
MakeRequest = IOEH.MakeRequest
|
||||
|
||||
// specialize
|
||||
MakeGetRequest = IOEH.MakeGetRequest
|
||||
)
|
||||
|
||||
// MakeBodyRequest creates a request that carries a body
|
||||
//
|
||||
//go:inline
|
||||
func MakeBodyRequest(method string, body IOResult[[]byte]) Kleisli[string, *http.Request] {
|
||||
return IOEH.MakeBodyRequest(method, body)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MakeClient(httpClient *http.Client) Client {
|
||||
return IOEH.MakeClient(httpClient)
|
||||
}
|
||||
|
||||
// ReadFullResponse sends a request, reads the response as a byte array and represents the result as a tuple
|
||||
//
|
||||
//go:inline
|
||||
func ReadFullResponse(client Client) Kleisli[Requester, H.FullResponse] {
|
||||
return IOEH.ReadFullResponse(client)
|
||||
}
|
||||
|
||||
// ReadAll sends a request and reads the response as bytes
|
||||
//
|
||||
//go:inline
|
||||
func ReadAll(client Client) Kleisli[Requester, []byte] {
|
||||
return IOEH.ReadAll(client)
|
||||
}
|
||||
|
||||
// ReadText sends a request, reads the response and represents the response as a text string
|
||||
//
|
||||
//go:inline
|
||||
func ReadText(client Client) Kleisli[Requester, string] {
|
||||
return IOEH.ReadText(client)
|
||||
}
|
||||
|
||||
// ReadJSON sends a request, reads the response and parses the response as JSON
|
||||
//
|
||||
//go:inline
|
||||
func ReadJSON[A any](client Client) Kleisli[Requester, A] {
|
||||
return IOEH.ReadJSON[A](client)
|
||||
}
|
||||
71
v2/ioresult/http/retry_test.go
Normal file
71
v2/ioresult/http/retry_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 http
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
AR "github.com/IBM/fp-go/v2/array"
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
"github.com/IBM/fp-go/v2/errors"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
O "github.com/IBM/fp-go/v2/option"
|
||||
R "github.com/IBM/fp-go/v2/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var expLogBackoff = R.ExponentialBackoff(250 * time.Millisecond)
|
||||
|
||||
// our retry policy with a 1s cap
|
||||
var testLogPolicy = R.CapDelay(
|
||||
2*time.Second,
|
||||
R.Monoid.Concat(expLogBackoff, R.LimitRetries(20)),
|
||||
)
|
||||
|
||||
type PostItem struct {
|
||||
UserID uint `json:"userId"`
|
||||
Id uint `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
func TestRetryHttp(t *testing.T) {
|
||||
// URLs to try, the first URLs have an invalid hostname
|
||||
urls := AR.From("https://jsonplaceholder1.typicode.com/posts/1", "https://jsonplaceholder2.typicode.com/posts/1", "https://jsonplaceholder3.typicode.com/posts/1", "https://jsonplaceholder4.typicode.com/posts/1", "https://jsonplaceholder.typicode.com/posts/1")
|
||||
client := MakeClient(&http.Client{})
|
||||
|
||||
action := func(status R.RetryStatus) IOResult[*PostItem] {
|
||||
return F.Pipe1(
|
||||
MakeGetRequest(urls[status.IterNumber]),
|
||||
ReadJSON[*PostItem](client),
|
||||
)
|
||||
}
|
||||
|
||||
check := E.Fold(
|
||||
F.Flow2(
|
||||
errors.As[*net.DNSError](),
|
||||
O.IsSome[*net.DNSError],
|
||||
),
|
||||
F.Constant1[*PostItem](false),
|
||||
)
|
||||
|
||||
item := ioeither.Retrying(testLogPolicy, action, check)()
|
||||
assert.True(t, E.IsRight(item))
|
||||
}
|
||||
9
v2/ioresult/http/types.go
Normal file
9
v2/ioresult/http/types.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package http
|
||||
|
||||
import "github.com/IBM/fp-go/v2/ioresult"
|
||||
|
||||
type (
|
||||
IOResult[T any] = ioresult.IOResult[T]
|
||||
Kleisli[A, B any] = ioresult.Kleisli[A, B]
|
||||
Operator[A, B any] = ioresult.Operator[A, B]
|
||||
)
|
||||
385
v2/ioresult/ioeither.go
Normal file
385
v2/ioresult/ioeither.go
Normal file
@@ -0,0 +1,385 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
IOO "github.com/IBM/fp-go/v2/iooption"
|
||||
O "github.com/IBM/fp-go/v2/option"
|
||||
)
|
||||
|
||||
//go:inline
|
||||
func Left[A any](l error) IOResult[A] {
|
||||
return ioeither.Left[A](l)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func Right[A any](r A) IOResult[A] {
|
||||
return ioeither.Right[error](r)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func Of[A any](r A) IOResult[A] {
|
||||
return ioeither.Of[error](r)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadOf[A any](r A) IOResult[A] {
|
||||
return ioeither.MonadOf[error](r)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func LeftIO[A any](ml IO[error]) IOResult[A] {
|
||||
return ioeither.LeftIO[A](ml)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func RightIO[A any](mr IO[A]) IOResult[A] {
|
||||
return ioeither.RightIO[error](mr)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func FromEither[A any](e Result[A]) IOResult[A] {
|
||||
return ioeither.FromEither(e)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func FromResult[A any](e Result[A]) IOResult[A] {
|
||||
return ioeither.FromEither(e)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func FromOption[A any](onNone func() error) func(o O.Option[A]) IOResult[A] {
|
||||
return ioeither.FromOption[A](onNone)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func FromIOOption[A any](onNone func() error) func(o IOO.IOOption[A]) IOResult[A] {
|
||||
return ioeither.FromIOOption[A](onNone)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func ChainOptionK[A, B any](onNone func() error) func(func(A) O.Option[B]) Operator[A, B] {
|
||||
return ioeither.ChainOptionK[A, B](onNone)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadChainIOK[A, B any](ma IOResult[A], f func(A) IO[B]) IOResult[B] {
|
||||
return ioeither.MonadChainIOK(ma, f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func ChainIOK[A, B any](f func(A) IO[B]) Operator[A, B] {
|
||||
return ioeither.ChainIOK[error](f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func ChainLazyK[A, B any](f func(A) Lazy[B]) Operator[A, B] {
|
||||
return ioeither.ChainLazyK[error](f)
|
||||
}
|
||||
|
||||
// FromIO creates an [IOResult] from an [IO] instancinvoking [IO] for each invocation of [IOResult]
|
||||
//
|
||||
//go:inline
|
||||
func FromIO[A any](mr IO[A]) IOResult[A] {
|
||||
return ioeither.FromIO[error](mr)
|
||||
}
|
||||
|
||||
// FromLazy creates an [IOResult] from a [Lazy] instancinvoking [Lazy] for each invocation of [IOResult]
|
||||
//
|
||||
//go:inline
|
||||
func FromLazy[A any](mr Lazy[A]) IOResult[A] {
|
||||
return ioeither.FromLazy[error](mr)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadMap[A, B any](fa IOResult[A], f func(A) B) IOResult[B] {
|
||||
return ioeither.MonadMap(fa, f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func Map[A, B any](f func(A) B) Operator[A, B] {
|
||||
return ioeither.Map[error](f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadMapTo[A, B any](fa IOResult[A], b B) IOResult[B] {
|
||||
return ioeither.MonadMapTo(fa, b)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MapTo[A, B any](b B) Operator[A, B] {
|
||||
return ioeither.MapTo[error, A](b)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadChain[A, B any](fa IOResult[A], f Kleisli[A, B]) IOResult[B] {
|
||||
return ioeither.MonadChain(fa, f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func Chain[A, B any](f Kleisli[A, B]) Operator[A, B] {
|
||||
return ioeither.Chain(f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadChainEitherK[A, B any](ma IOResult[A], f func(A) Result[B]) IOResult[B] {
|
||||
return ioeither.MonadChainEitherK(ma, f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadChainResultK[A, B any](ma IOResult[A], f func(A) Result[B]) IOResult[B] {
|
||||
return ioeither.MonadChainEitherK(ma, f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func ChainEitherK[A, B any](f func(A) Result[B]) Operator[A, B] {
|
||||
return ioeither.ChainEitherK(f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func ChainResultK[A, B any](f func(A) Result[B]) Operator[A, B] {
|
||||
return ioeither.ChainEitherK(f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadAp[B, A any](mab IOResult[func(A) B], ma IOResult[A]) IOResult[B] {
|
||||
return ioeither.MonadAp(mab, ma)
|
||||
}
|
||||
|
||||
// Ap is an alias of [ApPar]
|
||||
//
|
||||
//go:inline
|
||||
func Ap[B, A any](ma IOResult[A]) Operator[func(A) B, B] {
|
||||
return ioeither.Ap[B](ma)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadApPar[B, A any](mab IOResult[func(A) B], ma IOResult[A]) IOResult[B] {
|
||||
return ioeither.MonadApPar(mab, ma)
|
||||
}
|
||||
|
||||
// ApPar applies function and value in parallel
|
||||
//
|
||||
//go:inline
|
||||
func ApPar[B, A any](ma IOResult[A]) Operator[func(A) B, B] {
|
||||
return ioeither.ApPar[B](ma)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadApSeq[B, A any](mab IOResult[func(A) B], ma IOResult[A]) IOResult[B] {
|
||||
return ioeither.MonadApSeq(mab, ma)
|
||||
}
|
||||
|
||||
// ApSeq applies function and value sequentially
|
||||
//
|
||||
//go:inline
|
||||
func ApSeq[B, A any](ma IOResult[A]) func(IOResult[func(A) B]) IOResult[B] {
|
||||
return ioeither.ApSeq[B](ma)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func Flatten[A any](mma IOResult[IOResult[A]]) IOResult[A] {
|
||||
return ioeither.Flatten(mma)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func TryCatch[A any](f func() (A, error), onThrow Endomorphism[error]) IOResult[A] {
|
||||
return ioeither.TryCatch(f, onThrow)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func TryCatchError[A any](f func() (A, error)) IOResult[A] {
|
||||
return ioeither.TryCatchError(f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func Memoize[A any](ma IOResult[A]) IOResult[A] {
|
||||
return ioeither.Memoize(ma)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadMapLeft[A, E any](fa IOResult[A], f func(error) E) ioeither.IOEither[E, A] {
|
||||
return ioeither.MonadMapLeft(fa, f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MapLeft[A, E any](f func(error) E) func(IOResult[A]) ioeither.IOEither[E, A] {
|
||||
return ioeither.MapLeft[A](f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadBiMap[E, A, B any](fa IOResult[A], f func(error) E, g func(A) B) ioeither.IOEither[E, B] {
|
||||
return ioeither.MonadBiMap(fa, f, g)
|
||||
}
|
||||
|
||||
// BiMap maps a pair of functions over the two type arguments of the bifunctor.
|
||||
//
|
||||
//go:inline
|
||||
func BiMap[E, A, B any](f func(error) E, g func(A) B) func(IOResult[A]) ioeither.IOEither[E, B] {
|
||||
return ioeither.BiMap(f, g)
|
||||
}
|
||||
|
||||
// Fold converts an IOResult into an IO
|
||||
//
|
||||
//go:inline
|
||||
func Fold[A, B any](onLeft func(error) IO[B], onRight func(A) IO[B]) func(IOResult[A]) IO[B] {
|
||||
return ioeither.Fold(onLeft, onRight)
|
||||
}
|
||||
|
||||
// GetOrElse extracts the value or maps the error
|
||||
//
|
||||
//go:inline
|
||||
func GetOrElse[A any](onLeft func(error) IO[A]) func(IOResult[A]) IO[A] {
|
||||
return ioeither.GetOrElse(onLeft)
|
||||
}
|
||||
|
||||
// MonadChainTo composes to the second monad ignoring the return value of the first
|
||||
//
|
||||
//go:inline
|
||||
func MonadChainTo[A, B any](fa IOResult[A], fb IOResult[B]) IOResult[B] {
|
||||
return ioeither.MonadChainTo(fa, fb)
|
||||
}
|
||||
|
||||
// ChainTo composes to the second [IOResult] monad ignoring the return value of the first
|
||||
//
|
||||
//go:inline
|
||||
func ChainTo[A, B any](fb IOResult[B]) Operator[A, B] {
|
||||
return ioeither.ChainTo[A](fb)
|
||||
}
|
||||
|
||||
// MonadChainFirst runs the [IOResult] monad returned by the function but returns the result of the original monad
|
||||
//
|
||||
//go:inline
|
||||
func MonadChainFirst[A, B any](ma IOResult[A], f Kleisli[A, B]) IOResult[A] {
|
||||
return ioeither.MonadChainFirst(ma, f)
|
||||
}
|
||||
|
||||
// ChainFirst runs the [IOResult] monad returned by the function but returns the result of the original monad
|
||||
//
|
||||
//go:inline
|
||||
func ChainFirst[A, B any](f Kleisli[A, B]) Operator[A, A] {
|
||||
return ioeither.ChainFirst(f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadChainFirstEitherK[A, B any](ma IOResult[A], f func(A) Result[B]) IOResult[A] {
|
||||
return ioeither.MonadChainFirstEitherK(ma, f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadChainFirstResultK[A, B any](ma IOResult[A], f func(A) Result[B]) IOResult[A] {
|
||||
return ioeither.MonadChainFirstEitherK(ma, f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func ChainFirstEitherK[A, B any](f func(A) Result[B]) Operator[A, A] {
|
||||
return ioeither.ChainFirstEitherK(f)
|
||||
}
|
||||
|
||||
// MonadChainFirstIOK runs [IO] the monad returned by the function but returns the result of the original monad
|
||||
//
|
||||
//go:inline
|
||||
func MonadChainFirstIOK[A, B any](ma IOResult[A], f func(A) IO[B]) IOResult[A] {
|
||||
return ioeither.MonadChainFirstIOK(ma, f)
|
||||
}
|
||||
|
||||
// ChainFirstIOK runs the [IO] monad returned by the function but returns the result of the original monad
|
||||
//
|
||||
//go:inline
|
||||
func ChainFirstIOK[A, B any](f func(A) IO[B]) Operator[A, A] {
|
||||
return ioeither.ChainFirstIOK[error](f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadFold[A, B any](ma IOResult[A], onLeft func(error) IO[B], onRight func(A) IO[B]) IO[B] {
|
||||
return ioeither.MonadFold(ma, onLeft, onRight)
|
||||
}
|
||||
|
||||
// WithResource constructs a function that creates a resourcthen operates on it and then releases the resource
|
||||
//
|
||||
//go:inline
|
||||
func WithResource[A, R, ANY any](onCreate IOResult[R], onRelease Kleisli[R, ANY]) Kleisli[Kleisli[R, A], A] {
|
||||
return ioeither.WithResource[A](onCreate, onRelease)
|
||||
}
|
||||
|
||||
// Swap changes the order of type parameters
|
||||
//
|
||||
//go:inline
|
||||
func Swap[A any](val IOResult[A]) ioeither.IOEither[A, error] {
|
||||
return ioeither.Swap(val)
|
||||
}
|
||||
|
||||
// FromImpure converts a side effect without a return value into a side effect that returns any
|
||||
//
|
||||
//go:inline
|
||||
func FromImpure[E any](f func()) IOResult[any] {
|
||||
return ioeither.FromImpure[error](f)
|
||||
}
|
||||
|
||||
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
||||
//
|
||||
//go:inline
|
||||
func Defer[A any](gen Lazy[IOResult[A]]) IOResult[A] {
|
||||
return ioeither.Defer(gen)
|
||||
}
|
||||
|
||||
// MonadAlt identifies an associative operation on a type constructor
|
||||
//
|
||||
//go:inline
|
||||
func MonadAlt[A any](first IOResult[A], second Lazy[IOResult[A]]) IOResult[A] {
|
||||
return ioeither.MonadAlt(first, second)
|
||||
}
|
||||
|
||||
// Alt identifies an associative operation on a type constructor
|
||||
//
|
||||
//go:inline
|
||||
func Alt[A any](second Lazy[IOResult[A]]) Operator[A, A] {
|
||||
return ioeither.Alt(second)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func MonadFlap[B, A any](fab IOResult[func(A) B], a A) IOResult[B] {
|
||||
return ioeither.MonadFlap(fab, a)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func Flap[B, A any](a A) Operator[func(A) B, B] {
|
||||
return ioeither.Flap[error, B](a)
|
||||
}
|
||||
|
||||
// ToIOOption converts an [IOResult] to an [IOO.IOOption]
|
||||
//
|
||||
//go:inline
|
||||
func ToIOOption[A any](ioe IOResult[A]) IOO.IOOption[A] {
|
||||
return ioeither.ToIOOption(ioe)
|
||||
}
|
||||
|
||||
// Delay creates an operation that passes in the value after some delay
|
||||
//
|
||||
//go:inline
|
||||
func Delay[A any](delay time.Duration) Operator[A, A] {
|
||||
return ioeither.Delay[error, A](delay)
|
||||
}
|
||||
|
||||
// After creates an operation that passes after the given [time.Time]
|
||||
//
|
||||
//go:inline
|
||||
func After[A any](timestamp time.Time) Operator[A, A] {
|
||||
return ioeither.After[error, A](timestamp)
|
||||
}
|
||||
152
v2/ioresult/ioeither_test.go
Normal file
152
v2/ioresult/ioeither_test.go
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/IBM/fp-go/v2/internal/utils"
|
||||
"github.com/IBM/fp-go/v2/io"
|
||||
O "github.com/IBM/fp-go/v2/option"
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
assert.Equal(t, result.Of(2), F.Pipe1(
|
||||
Of(1),
|
||||
Map(utils.Double),
|
||||
)())
|
||||
|
||||
}
|
||||
|
||||
func TestChainEitherK(t *testing.T) {
|
||||
|
||||
a := errors.New("a")
|
||||
b := errors.New("b")
|
||||
|
||||
f := ChainEitherK(func(n int) Result[int] {
|
||||
if n > 0 {
|
||||
return result.Of(n)
|
||||
}
|
||||
return result.Left[int](a)
|
||||
|
||||
})
|
||||
assert.Equal(t, result.Right(1), f(Right(1))())
|
||||
assert.Equal(t, result.Left[int](a), f(Right(-1))())
|
||||
assert.Equal(t, result.Left[int](b), f(Left[int](b))())
|
||||
}
|
||||
|
||||
func TestChainOptionK(t *testing.T) {
|
||||
|
||||
a := errors.New("a")
|
||||
b := errors.New("b")
|
||||
|
||||
f := ChainOptionK[int, int](F.Constant(a))(func(n int) O.Option[int] {
|
||||
if n > 0 {
|
||||
return O.Some(n)
|
||||
}
|
||||
return O.None[int]()
|
||||
})
|
||||
|
||||
assert.Equal(t, result.Right(1), f(Right(1))())
|
||||
assert.Equal(t, result.Left[int](a), f(Right(-1))())
|
||||
assert.Equal(t, result.Left[int](b), f(Left[int](b))())
|
||||
}
|
||||
|
||||
func TestFromOption(t *testing.T) {
|
||||
|
||||
a := errors.New("a")
|
||||
|
||||
f := FromOption[int](F.Constant(a))
|
||||
assert.Equal(t, result.Right(1), f(O.Some(1))())
|
||||
assert.Equal(t, result.Left[int](a), f(O.None[int]())())
|
||||
}
|
||||
|
||||
func TestChainIOK(t *testing.T) {
|
||||
b := errors.New("b")
|
||||
|
||||
f := ChainIOK(func(n int) io.IO[string] {
|
||||
return func() string {
|
||||
return fmt.Sprintf("%d", n)
|
||||
}
|
||||
})
|
||||
|
||||
assert.Equal(t, result.Right("1"), f(Right(1))())
|
||||
assert.Equal(t, result.Left[string](b), f(Left[int](b))())
|
||||
}
|
||||
|
||||
func TestChainWithIO(t *testing.T) {
|
||||
|
||||
r := F.Pipe1(
|
||||
Of("test"),
|
||||
// sad, we need the generics version ...
|
||||
io.Map(result.IsRight[string]),
|
||||
)
|
||||
|
||||
assert.True(t, r())
|
||||
}
|
||||
|
||||
func TestChainFirst(t *testing.T) {
|
||||
|
||||
foo := errors.New("foo")
|
||||
|
||||
f := func(a string) IOResult[int] {
|
||||
if len(a) > 2 {
|
||||
return Of(len(a))
|
||||
}
|
||||
return Left[int](foo)
|
||||
}
|
||||
good := Of("foo")
|
||||
bad := Of("a")
|
||||
ch := ChainFirst(f)
|
||||
|
||||
assert.Equal(t, result.Of("foo"), F.Pipe1(good, ch)())
|
||||
assert.Equal(t, result.Left[string](foo), F.Pipe1(bad, ch)())
|
||||
}
|
||||
|
||||
func TestChainFirstIOK(t *testing.T) {
|
||||
f := func(a string) io.IO[int] {
|
||||
return io.Of(len(a))
|
||||
}
|
||||
good := Of("foo")
|
||||
ch := ChainFirstIOK(f)
|
||||
|
||||
assert.Equal(t, result.Of("foo"), F.Pipe1(good, ch)())
|
||||
}
|
||||
|
||||
func TestApFirst(t *testing.T) {
|
||||
|
||||
x := F.Pipe1(
|
||||
Of("a"),
|
||||
ApFirst[string](Of("b")),
|
||||
)
|
||||
|
||||
assert.Equal(t, result.Of("a"), x())
|
||||
}
|
||||
|
||||
func TestApSecond(t *testing.T) {
|
||||
|
||||
x := F.Pipe1(
|
||||
Of("a"),
|
||||
ApSecond[string](Of("b")),
|
||||
)
|
||||
|
||||
assert.Equal(t, result.Of("b"), x())
|
||||
}
|
||||
28
v2/ioresult/logging.go
Normal file
28
v2/ioresult/logging.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
)
|
||||
|
||||
// LogJSON converts the argument to pretty printed JSON and then logs it via the format string
|
||||
// Can be used with [ChainFirst]
|
||||
//
|
||||
//go:inline
|
||||
func LogJSON[A any](prefix string) Kleisli[A, any] {
|
||||
return ioeither.LogJSON[A](prefix)
|
||||
}
|
||||
42
v2/ioresult/logging_test.go
Normal file
42
v2/ioresult/logging_test.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLogging(t *testing.T) {
|
||||
|
||||
type SomeData struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
src := &SomeData{Key: "key", Value: "value"}
|
||||
|
||||
res := F.Pipe1(
|
||||
Of(src),
|
||||
ChainFirst(LogJSON[*SomeData]("Data: \n%s")),
|
||||
)
|
||||
|
||||
dst := res()
|
||||
assert.Equal(t, E.Of[error](src), dst)
|
||||
}
|
||||
69
v2/ioresult/monad.go
Normal file
69
v2/ioresult/monad.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2024 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/internal/functor"
|
||||
"github.com/IBM/fp-go/v2/internal/monad"
|
||||
"github.com/IBM/fp-go/v2/internal/pointed"
|
||||
)
|
||||
|
||||
type (
|
||||
ioEitherPointed[A any] struct{}
|
||||
|
||||
ioEitherMonad[A, B any] struct{}
|
||||
|
||||
ioEitherFunctor[A, B any] struct{}
|
||||
)
|
||||
|
||||
func (o *ioEitherPointed[A]) Of(a A) IOResult[A] {
|
||||
return Of(a)
|
||||
}
|
||||
|
||||
func (o *ioEitherMonad[A, B]) Of(a A) IOResult[A] {
|
||||
return Of(a)
|
||||
}
|
||||
|
||||
func (o *ioEitherMonad[A, B]) Map(f func(A) B) Operator[A, B] {
|
||||
return Map(f)
|
||||
}
|
||||
|
||||
func (o *ioEitherMonad[A, B]) Chain(f Kleisli[A, B]) Operator[A, B] {
|
||||
return Chain(f)
|
||||
}
|
||||
|
||||
func (o *ioEitherMonad[A, B]) Ap(fa IOResult[A]) Operator[func(A) B, B] {
|
||||
return Ap[B](fa)
|
||||
}
|
||||
|
||||
func (o *ioEitherFunctor[A, B]) Map(f func(A) B) Operator[A, B] {
|
||||
return Map(f)
|
||||
}
|
||||
|
||||
// Pointed implements the pointed operations for [IOResult]
|
||||
func Pointed[A any]() pointed.Pointed[A, IOResult[A]] {
|
||||
return &ioEitherPointed[A]{}
|
||||
}
|
||||
|
||||
// Functor implements the monadic operations for [IOResult]
|
||||
func Functor[A, B any]() functor.Functor[A, B, IOResult[A], IOResult[B]] {
|
||||
return &ioEitherFunctor[A, B]{}
|
||||
}
|
||||
|
||||
// Monad implements the monadic operations for [IOResult]
|
||||
func Monad[A, B any]() monad.Monad[A, B, IOResult[A], IOResult[B], IOResult[func(A) B]] {
|
||||
return &ioEitherMonad[A, B]{}
|
||||
}
|
||||
48
v2/ioresult/monoid.go
Normal file
48
v2/ioresult/monoid.go
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
"github.com/IBM/fp-go/v2/monoid"
|
||||
)
|
||||
|
||||
// ApplicativeMonoid returns a [Monoid] that concatenates [IOResult] instances via their applicative
|
||||
//
|
||||
//go:inline
|
||||
func ApplicativeMonoid[A any](
|
||||
m monoid.Monoid[A],
|
||||
) Monoid[A] {
|
||||
return ioeither.ApplicativeMonoid[error](m)
|
||||
}
|
||||
|
||||
// ApplicativeMonoid returns a [Monoid] that concatenates [IOResult] instances via their applicative
|
||||
//
|
||||
//go:inline
|
||||
func ApplicativeMonoidSeq[A any](
|
||||
m monoid.Monoid[A],
|
||||
) Monoid[A] {
|
||||
return ioeither.ApplicativeMonoidSeq[error](m)
|
||||
}
|
||||
|
||||
// ApplicativeMonoid returns a [Monoid] that concatenates [IOResult] instances via their applicative
|
||||
//
|
||||
//go:inline
|
||||
func ApplicativeMonoidPar[A any](
|
||||
m monoid.Monoid[A],
|
||||
) Monoid[A] {
|
||||
return ioeither.ApplicativeMonoidPar[error](m)
|
||||
}
|
||||
42
v2/ioresult/monoid_test.go
Normal file
42
v2/ioresult/monoid_test.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2023 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
S "github.com/IBM/fp-go/v2/string"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestApplicativeMonoid(t *testing.T) {
|
||||
m := ApplicativeMonoid(S.Monoid)
|
||||
|
||||
// good cases
|
||||
assert.Equal(t, result.Of("ab"), m.Concat(Of("a"), Of("b"))())
|
||||
assert.Equal(t, result.Of("a"), m.Concat(Of("a"), m.Empty())())
|
||||
assert.Equal(t, result.Of("b"), m.Concat(m.Empty(), Of("b"))())
|
||||
|
||||
// bad cases
|
||||
e1 := fmt.Errorf("e1")
|
||||
e2 := fmt.Errorf("e1")
|
||||
|
||||
assert.Equal(t, result.Left[string](e1), m.Concat(Left[string](e1), Of("b"))())
|
||||
assert.Equal(t, result.Left[string](e1), m.Concat(Left[string](e1), Left[string](e2))())
|
||||
assert.Equal(t, result.Left[string](e2), m.Concat(Of("a"), Left[string](e2))())
|
||||
}
|
||||
36
v2/ioresult/retry.go
Normal file
36
v2/ioresult/retry.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
R "github.com/IBM/fp-go/v2/retry"
|
||||
)
|
||||
|
||||
// Retrying will retry the actions according to the check policy
|
||||
//
|
||||
// policy - refers to the retry policy
|
||||
// action - converts a status into an operation to be executed
|
||||
// check - checks if the result of the action needs to be retried
|
||||
//
|
||||
//go:inline
|
||||
func Retrying[A any](
|
||||
policy R.RetryPolicy,
|
||||
action Kleisli[R.RetryStatus, A],
|
||||
check func(Result[A]) bool,
|
||||
) IOResult[A] {
|
||||
return ioeither.Retrying(policy, action, check)
|
||||
}
|
||||
49
v2/ioresult/retry_test.go
Normal file
49
v2/ioresult/retry_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
R "github.com/IBM/fp-go/v2/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var expLogBackoff = R.ExponentialBackoff(10 * time.Millisecond)
|
||||
|
||||
// our retry policy with a 1s cap
|
||||
var testLogPolicy = R.CapDelay(
|
||||
2*time.Second,
|
||||
R.Monoid.Concat(expLogBackoff, R.LimitRetries(20)),
|
||||
)
|
||||
|
||||
func TestRetry(t *testing.T) {
|
||||
action := func(status R.RetryStatus) IOResult[string] {
|
||||
if status.IterNumber < 5 {
|
||||
return Left[string](fmt.Errorf("retrying %d", status.IterNumber))
|
||||
}
|
||||
return Of(fmt.Sprintf("Retrying %d", status.IterNumber))
|
||||
}
|
||||
check := result.IsLeft[string]
|
||||
|
||||
r := Retrying(testLogPolicy, action, check)
|
||||
|
||||
assert.Equal(t, E.Of[error]("Retrying 5"), r())
|
||||
}
|
||||
27
v2/ioresult/semigroup.go
Normal file
27
v2/ioresult/semigroup.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
)
|
||||
|
||||
// AltSemigroup is a [Semigroup] that tries the first item and then the second one using an alternative
|
||||
//
|
||||
//go:inline
|
||||
func AltSemigroup[A any]() Semigroup[A] {
|
||||
return ioeither.AltSemigroup[error, A]()
|
||||
}
|
||||
83
v2/ioresult/sequence_test.go
Normal file
83
v2/ioresult/sequence_test.go
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
A "github.com/IBM/fp-go/v2/array"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
TST "github.com/IBM/fp-go/v2/internal/testing"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMapSeq(t *testing.T) {
|
||||
var results []string
|
||||
|
||||
handler := func(value string) IOResult[string] {
|
||||
return func() result.Result[string] {
|
||||
results = append(results, value)
|
||||
return result.Of(value)
|
||||
}
|
||||
}
|
||||
|
||||
src := A.From("a", "b", "c")
|
||||
|
||||
res := F.Pipe2(
|
||||
src,
|
||||
TraverseArraySeq(handler),
|
||||
Map(func(data []string) bool {
|
||||
return assert.Equal(t, data, results)
|
||||
}),
|
||||
)
|
||||
|
||||
assert.Equal(t, result.Of(true), res())
|
||||
}
|
||||
|
||||
func TestSequenceArray(t *testing.T) {
|
||||
|
||||
s := TST.SequenceArrayTest(
|
||||
FromStrictEquals[bool](),
|
||||
Pointed[string](),
|
||||
Pointed[bool](),
|
||||
Functor[[]string, bool](),
|
||||
SequenceArray[string],
|
||||
)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
t.Run(fmt.Sprintf("TestSequenceArray %d", i), s(i))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSequenceArrayError(t *testing.T) {
|
||||
|
||||
s := TST.SequenceArrayErrorTest(
|
||||
FromStrictEquals[bool](),
|
||||
Left[string],
|
||||
Left[bool],
|
||||
Pointed[string](),
|
||||
Pointed[bool](),
|
||||
Functor[[]string, bool](),
|
||||
SequenceArray[string],
|
||||
)
|
||||
|
||||
// run across four bits
|
||||
s(4)(t)
|
||||
}
|
||||
29
v2/ioresult/sync.go
Normal file
29
v2/ioresult/sync.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
)
|
||||
|
||||
// WithLock executes the provided IO operation in the scope of a lock
|
||||
//
|
||||
//go:inline
|
||||
func WithLock[A any](lock IO[context.CancelFunc]) Operator[A, A] {
|
||||
return ioeither.WithLock[error, A](lock)
|
||||
}
|
||||
36
v2/ioresult/testing/laws.go
Normal file
36
v2/ioresult/testing/laws.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package testing
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/IBM/fp-go/v2/eq"
|
||||
IOET "github.com/IBM/fp-go/v2/ioeither/testing"
|
||||
)
|
||||
|
||||
// AssertLaws asserts the apply monad laws for the `IOEither` monad
|
||||
func AssertLaws[A, B, C any](t *testing.T,
|
||||
eqa eq.Eq[A],
|
||||
eqb eq.Eq[B],
|
||||
eqc eq.Eq[C],
|
||||
|
||||
ab func(A) B,
|
||||
bc func(B) C,
|
||||
) func(a A) bool {
|
||||
|
||||
return IOET.AssertLaws(t, eq.FromStrictEquals[error](), eqa, eqb, eqc, ab, bc)
|
||||
}
|
||||
47
v2/ioresult/testing/laws_test.go
Normal file
47
v2/ioresult/testing/laws_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/IBM/fp-go/v2/eq"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMonadLaws(t *testing.T) {
|
||||
// some comparison
|
||||
eqa := eq.FromStrictEquals[bool]()
|
||||
eqb := eq.FromStrictEquals[int]()
|
||||
eqc := eq.FromStrictEquals[string]()
|
||||
|
||||
ab := func(a bool) int {
|
||||
if a {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
bc := func(b int) string {
|
||||
return fmt.Sprintf("value %d", b)
|
||||
}
|
||||
|
||||
laws := AssertLaws(t, eqa, eqb, eqc, ab, bc)
|
||||
|
||||
assert.True(t, laws(true))
|
||||
assert.True(t, laws(false))
|
||||
}
|
||||
146
v2/ioresult/traverse.go
Normal file
146
v2/ioresult/traverse.go
Normal file
@@ -0,0 +1,146 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
)
|
||||
|
||||
// TraverseArray transforms an array
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
||||
return ioeither.TraverseArray(f)
|
||||
}
|
||||
|
||||
// TraverseArrayWithIndex transforms an array
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArrayWithIndex[A, B any](f func(int, A) IOResult[B]) Kleisli[[]A, []B] {
|
||||
return ioeither.TraverseArrayWithIndex(f)
|
||||
}
|
||||
|
||||
// SequenceArray converts a homogeneous sequence of either into an either of sequence
|
||||
//
|
||||
//go:inline
|
||||
func SequenceArray[A any](ma []IOResult[A]) IOResult[[]A] {
|
||||
return ioeither.SequenceArray(ma)
|
||||
}
|
||||
|
||||
// TraverseRecord transforms a record
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecord[K comparable, A, B any](f Kleisli[A, B]) Kleisli[map[K]A, map[K]B] {
|
||||
return ioeither.TraverseRecord[K](f)
|
||||
}
|
||||
|
||||
// TraverseRecordWithIndex transforms a record
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecordWithIndex[K comparable, A, B any](f func(K, A) IOResult[B]) Kleisli[map[K]A, map[K]B] {
|
||||
return ioeither.TraverseRecordWithIndex(f)
|
||||
}
|
||||
|
||||
// SequenceRecord converts a homogeneous sequence of either into an either of sequence
|
||||
//
|
||||
//go:inline
|
||||
func SequenceRecord[K comparable, A any](ma map[K]IOResult[A]) IOResult[map[K]A] {
|
||||
return ioeither.SequenceRecord(ma)
|
||||
}
|
||||
|
||||
// TraverseArraySeq transforms an array
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArraySeq[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
||||
return ioeither.TraverseArraySeq(f)
|
||||
}
|
||||
|
||||
// TraverseArrayWithIndexSeq transforms an array
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArrayWithIndexSeq[A, B any](f func(int, A) IOResult[B]) Kleisli[[]A, []B] {
|
||||
return ioeither.TraverseArrayWithIndexSeq(f)
|
||||
}
|
||||
|
||||
// SequenceArraySeq converts a homogeneous sequence of either into an either of sequence
|
||||
//
|
||||
//go:inline
|
||||
func SequenceArraySeq[A any](ma []IOResult[A]) IOResult[[]A] {
|
||||
return ioeither.SequenceArraySeq(ma)
|
||||
}
|
||||
|
||||
// TraverseRecordSeq transforms a record
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecordSeq[K comparable, A, B any](f Kleisli[A, B]) Kleisli[map[K]A, map[K]B] {
|
||||
return ioeither.TraverseRecordSeq[K](f)
|
||||
}
|
||||
|
||||
// TraverseRecordWithIndexSeq transforms a record
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecordWithIndexSeq[K comparable, A, B any](f func(K, A) IOResult[B]) Kleisli[map[K]A, map[K]B] {
|
||||
return ioeither.TraverseRecordWithIndexSeq(f)
|
||||
}
|
||||
|
||||
// SequenceRecordSeq converts a homogeneous sequence of either into an either of sequence
|
||||
//
|
||||
//go:inline
|
||||
func SequenceRecordSeq[K comparable, A any](ma map[K]IOResult[A]) IOResult[map[K]A] {
|
||||
return ioeither.SequenceRecordSeq(ma)
|
||||
}
|
||||
|
||||
// TraverseArrayPar transforms an array
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArrayPar[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
||||
return ioeither.TraverseArrayPar(f)
|
||||
}
|
||||
|
||||
// TraverseArrayWithIndexPar transforms an array
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArrayWithIndexPar[A, B any](f func(int, A) IOResult[B]) Kleisli[[]A, []B] {
|
||||
return ioeither.TraverseArrayWithIndexPar(f)
|
||||
}
|
||||
|
||||
// SequenceArrayPar converts a homogeneous Paruence of either into an either of Paruence
|
||||
//
|
||||
//go:inline
|
||||
func SequenceArrayPar[A any](ma []IOResult[A]) IOResult[[]A] {
|
||||
return ioeither.SequenceArrayPar(ma)
|
||||
}
|
||||
|
||||
// TraverseRecordPar transforms a record
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecordPar[K comparable, A, B any](f Kleisli[A, B]) Kleisli[map[K]A, map[K]B] {
|
||||
return ioeither.TraverseRecordPar[K](f)
|
||||
}
|
||||
|
||||
// TraverseRecordWithIndexPar transforms a record
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecordWithIndexPar[K comparable, A, B any](f func(K, A) IOResult[B]) Kleisli[map[K]A, map[K]B] {
|
||||
return ioeither.TraverseRecordWithIndexPar(f)
|
||||
}
|
||||
|
||||
// SequenceRecordPar converts a homogeneous Paruence of either into an either of Paruence
|
||||
//
|
||||
//go:inline
|
||||
func SequenceRecordPar[K comparable, A any](ma map[K]IOResult[A]) IOResult[map[K]A] {
|
||||
return ioeither.SequenceRecordPar(ma)
|
||||
}
|
||||
37
v2/ioresult/traverse_test.go
Normal file
37
v2/ioresult/traverse_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2023 - 2025 IBM Corp.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache LicensVersion 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 ioresult
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
A "github.com/IBM/fp-go/v2/array"
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTraverseArray(t *testing.T) {
|
||||
|
||||
src := A.From("A", "B")
|
||||
|
||||
trfrm := TraverseArrayWithIndex(func(idx int, data string) IOResult[string] {
|
||||
return Of(fmt.Sprintf("idx: %d, data: %s", idx, data))
|
||||
})
|
||||
|
||||
assert.Equal(t, result.Of(A.From("idx: 0, data: A", "idx: 1, data: B")), trfrm(src)())
|
||||
|
||||
}
|
||||
29
v2/ioresult/types.go
Normal file
29
v2/ioresult/types.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package ioresult
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/either"
|
||||
"github.com/IBM/fp-go/v2/endomorphism"
|
||||
"github.com/IBM/fp-go/v2/io"
|
||||
"github.com/IBM/fp-go/v2/lazy"
|
||||
"github.com/IBM/fp-go/v2/monoid"
|
||||
"github.com/IBM/fp-go/v2/reader"
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
"github.com/IBM/fp-go/v2/semigroup"
|
||||
)
|
||||
|
||||
type (
|
||||
IO[A any] = io.IO[A]
|
||||
Lazy[A any] = lazy.Lazy[A]
|
||||
Either[E, A any] = either.Either[E, A]
|
||||
Result[A any] = result.Result[A]
|
||||
Endomorphism[A any] = endomorphism.Endomorphism[A]
|
||||
|
||||
// IOEither represents a synchronous computation that may fail
|
||||
// refer to [https://andywhite.xyz/posts/2021-01-27-rte-foundations/#ioeitherlte-agt] for more details
|
||||
IOResult[A any] = IO[Result[A]]
|
||||
Monoid[A any] = monoid.Monoid[IOResult[A]]
|
||||
Semigroup[A any] = semigroup.Semigroup[IOResult[A]]
|
||||
|
||||
Kleisli[A, B any] = reader.Reader[A, IOResult[B]]
|
||||
Operator[A, B any] = Kleisli[IOResult[A], B]
|
||||
)
|
||||
@@ -35,7 +35,7 @@ import (
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArrayG[GA ~[]A, GB ~[]B, A, B any](f Kleisli[A, B]) Kleisli[GA, GB] {
|
||||
return either.TraverseArrayG[GA, GB, error, A, B](f)
|
||||
return either.TraverseArrayG[GA, GB](f)
|
||||
}
|
||||
|
||||
// TraverseArray transforms an array by applying a function that returns an Either to each element.
|
||||
@@ -53,7 +53,7 @@ func TraverseArrayG[GA ~[]A, GB ~[]B, A, B any](f Kleisli[A, B]) Kleisli[GA, GB]
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
||||
return either.TraverseArray[error](f)
|
||||
return either.TraverseArray(f)
|
||||
}
|
||||
|
||||
// TraverseArrayWithIndexG transforms an array by applying an indexed function that returns an Either.
|
||||
@@ -74,7 +74,7 @@ func TraverseArray[A, B any](f Kleisli[A, B]) Kleisli[[]A, []B] {
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArrayWithIndexG[GA ~[]A, GB ~[]B, A, B any](f func(int, A) Result[B]) Kleisli[GA, GB] {
|
||||
return either.TraverseArrayWithIndexG[GA, GB, error, A, B](f)
|
||||
return either.TraverseArrayWithIndexG[GA, GB](f)
|
||||
}
|
||||
|
||||
// TraverseArrayWithIndex transforms an array by applying an indexed function that returns an Either.
|
||||
@@ -94,12 +94,12 @@ func TraverseArrayWithIndexG[GA ~[]A, GB ~[]B, A, B any](f func(int, A) Result[B
|
||||
//
|
||||
//go:inline
|
||||
func TraverseArrayWithIndex[A, B any](f func(int, A) Result[B]) Kleisli[[]A, []B] {
|
||||
return either.TraverseArrayWithIndex[error, A, B](f)
|
||||
return either.TraverseArrayWithIndex(f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func SequenceArrayG[GA ~[]A, GOA ~[]Result[A], A any](ma GOA) Result[GA] {
|
||||
return either.SequenceArrayG[GA, GOA, error, A](ma)
|
||||
return either.SequenceArrayG[GA](ma)
|
||||
}
|
||||
|
||||
// SequenceArray converts a homogeneous sequence of Either into an Either of sequence.
|
||||
@@ -118,7 +118,7 @@ func SequenceArrayG[GA ~[]A, GOA ~[]Result[A], A any](ma GOA) Result[GA] {
|
||||
//
|
||||
//go:inline
|
||||
func SequenceArray[A any](ma []Result[A]) Result[[]A] {
|
||||
return either.SequenceArray[error, A](ma)
|
||||
return either.SequenceArray(ma)
|
||||
}
|
||||
|
||||
// CompactArrayG discards all Left values and keeps only the Right values.
|
||||
@@ -136,7 +136,7 @@ func SequenceArray[A any](ma []Result[A]) Result[[]A] {
|
||||
//
|
||||
//go:inline
|
||||
func CompactArrayG[A1 ~[]Result[A], A2 ~[]A, A any](fa A1) A2 {
|
||||
return either.CompactArrayG[A1, A2, error, A](fa)
|
||||
return either.CompactArrayG[A1, A2](fa)
|
||||
}
|
||||
|
||||
// CompactArray discards all Left values and keeps only the Right values.
|
||||
@@ -153,5 +153,5 @@ func CompactArrayG[A1 ~[]Result[A], A2 ~[]A, A any](fa A1) A2 {
|
||||
//
|
||||
//go:inline
|
||||
func CompactArray[A any](fa []Result[A]) []A {
|
||||
return either.CompactArray[error, A](fa)
|
||||
return either.CompactArray(fa)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
func Do[S any](
|
||||
empty S,
|
||||
) Result[S] {
|
||||
return either.Do[error, S](empty)
|
||||
return either.Do[error](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context S1 to produce a context S2.
|
||||
@@ -57,7 +57,7 @@ func Bind[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f Kleisli[S1, T],
|
||||
) Operator[S1, S2] {
|
||||
return either.Bind[error](setter, f)
|
||||
return either.Bind(setter, f)
|
||||
}
|
||||
|
||||
// Let attaches the result of a pure computation to a context S1 to produce a context S2.
|
||||
@@ -146,7 +146,7 @@ func ApS[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
fa Result[T],
|
||||
) Operator[S1, S2] {
|
||||
return either.ApS[error](setter, fa)
|
||||
return either.ApS(setter, fa)
|
||||
}
|
||||
|
||||
// ApSL attaches a value to a context using a lens-based setter.
|
||||
@@ -194,7 +194,7 @@ func ApSL[S, T any](
|
||||
lens Lens[S, T],
|
||||
fa Result[T],
|
||||
) Operator[S, S] {
|
||||
return either.ApSL[error](lens, fa)
|
||||
return either.ApSL(lens, fa)
|
||||
}
|
||||
|
||||
// BindL attaches the result of a computation to a context using a lens-based setter.
|
||||
@@ -249,7 +249,7 @@ func BindL[S, T any](
|
||||
lens Lens[S, T],
|
||||
f Kleisli[T, T],
|
||||
) Operator[S, S] {
|
||||
return either.BindL[error](lens, f)
|
||||
return either.BindL(lens, f)
|
||||
}
|
||||
|
||||
// LetL attaches the result of a pure computation to a context using a lens-based setter.
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
// curried := either.Curry0(getConfig)
|
||||
// result := curried() // Right("config")
|
||||
func Curry0[R any](f func() (R, error)) func() Result[R] {
|
||||
return either.Curry0[R](f)
|
||||
return either.Curry0(f)
|
||||
}
|
||||
|
||||
// Curry1 converts a Go function that returns (R, error) into a curried version that returns Result[R].
|
||||
@@ -38,7 +38,7 @@ func Curry0[R any](f func() (R, error)) func() Result[R] {
|
||||
// curried := either.Curry1(parse)
|
||||
// result := curried("42") // Right(42)
|
||||
func Curry1[T1, R any](f func(T1) (R, error)) func(T1) Result[R] {
|
||||
return either.Curry1[T1, R](f)
|
||||
return either.Curry1(f)
|
||||
}
|
||||
|
||||
// Curry2 converts a 2-argument Go function that returns (R, error) into a curried version.
|
||||
@@ -52,17 +52,17 @@ func Curry1[T1, R any](f func(T1) (R, error)) func(T1) Result[R] {
|
||||
// curried := either.Curry2(divide)
|
||||
// result := curried(10)(2) // Right(5)
|
||||
func Curry2[T1, T2, R any](f func(T1, T2) (R, error)) func(T1) func(T2) Result[R] {
|
||||
return either.Curry2[T1, T2, R](f)
|
||||
return either.Curry2(f)
|
||||
}
|
||||
|
||||
// Curry3 converts a 3-argument Go function that returns (R, error) into a curried version.
|
||||
func Curry3[T1, T2, T3, R any](f func(T1, T2, T3) (R, error)) func(T1) func(T2) func(T3) Result[R] {
|
||||
return either.Curry3[T1, T2, T3, R](f)
|
||||
return either.Curry3(f)
|
||||
}
|
||||
|
||||
// Curry4 converts a 4-argument Go function that returns (R, error) into a curried version.
|
||||
func Curry4[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) (R, error)) func(T1) func(T2) func(T3) func(T4) Result[R] {
|
||||
return either.Curry4[T1, T2, T3, T4, R](f)
|
||||
return either.Curry4(f)
|
||||
}
|
||||
|
||||
// Uncurry0 converts a function returning Result[R] back to Go's (R, error) style.
|
||||
@@ -73,7 +73,7 @@ func Curry4[T1, T2, T3, T4, R any](f func(T1, T2, T3, T4) (R, error)) func(T1) f
|
||||
// uncurried := either.Uncurry0(curried)
|
||||
// result, err := uncurried() // "value", nil
|
||||
func Uncurry0[R any](f func() Result[R]) func() (R, error) {
|
||||
return either.Uncurry0[R](f)
|
||||
return either.Uncurry0(f)
|
||||
}
|
||||
|
||||
// Uncurry1 converts a function returning Result[R] back to Go's (R, error) style.
|
||||
@@ -84,20 +84,20 @@ func Uncurry0[R any](f func() Result[R]) func() (R, error) {
|
||||
// uncurried := either.Uncurry1(curried)
|
||||
// result, err := uncurried(42) // "42", nil
|
||||
func Uncurry1[T1, R any](f func(T1) Result[R]) func(T1) (R, error) {
|
||||
return either.Uncurry1[T1, R](f)
|
||||
return either.Uncurry1(f)
|
||||
}
|
||||
|
||||
// Uncurry2 converts a curried function returning Result[R] back to Go's (R, error) style.
|
||||
func Uncurry2[T1, T2, R any](f func(T1) func(T2) Result[R]) func(T1, T2) (R, error) {
|
||||
return either.Uncurry2[T1, T2, R](f)
|
||||
return either.Uncurry2(f)
|
||||
}
|
||||
|
||||
// Uncurry3 converts a curried function returning Result[R] back to Go's (R, error) style.
|
||||
func Uncurry3[T1, T2, T3, R any](f func(T1) func(T2) func(T3) Result[R]) func(T1, T2, T3) (R, error) {
|
||||
return either.Uncurry3[T1, T2, T3, R](f)
|
||||
return either.Uncurry3(f)
|
||||
}
|
||||
|
||||
// Uncurry4 converts a curried function returning Result[R] back to Go's (R, error) style.
|
||||
func Uncurry4[T1, T2, T3, T4, R any](f func(T1) func(T2) func(T3) func(T4) Result[R]) func(T1, T2, T3, T4) (R, error) {
|
||||
return either.Uncurry4[T1, T2, T3, T4, R](f)
|
||||
return either.Uncurry4(f)
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import (
|
||||
//
|
||||
//go:inline
|
||||
func Of[A any](value A) Result[A] {
|
||||
return either.Of[error, A](value)
|
||||
return either.Of[error](value)
|
||||
}
|
||||
|
||||
// FromIO executes an IO operation and wraps the result in a Right value.
|
||||
@@ -47,7 +47,7 @@ func Of[A any](value A) Result[A] {
|
||||
//
|
||||
//go:inline
|
||||
func FromIO[IO ~func() A, A any](f IO) Result[A] {
|
||||
return either.FromIO[error, IO, A](f)
|
||||
return either.FromIO[error](f)
|
||||
}
|
||||
|
||||
// MonadAp applies a function wrapped in Either to a value wrapped in Either.
|
||||
@@ -62,7 +62,7 @@ func FromIO[IO ~func() A, A any](f IO) Result[A] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadAp[B, A any](fab Result[func(a A) B], fa Result[A]) Result[B] {
|
||||
return either.MonadAp[B, error, A](fab, fa)
|
||||
return either.MonadAp(fab, fa)
|
||||
}
|
||||
|
||||
// Ap is the curried version of [MonadAp].
|
||||
@@ -70,7 +70,7 @@ func MonadAp[B, A any](fab Result[func(a A) B], fa Result[A]) Result[B] {
|
||||
//
|
||||
//go:inline
|
||||
func Ap[B, A any](fa Result[A]) Operator[func(A) B, B] {
|
||||
return either.Ap[B, error, A](fa)
|
||||
return either.Ap[B](fa)
|
||||
}
|
||||
|
||||
// MonadMap transforms the Right value using the provided function.
|
||||
@@ -86,7 +86,7 @@ func Ap[B, A any](fa Result[A]) Operator[func(A) B, B] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadMap[A, B any](fa Result[A], f func(a A) B) Result[B] {
|
||||
return either.MonadMap[error, A, B](fa, f)
|
||||
return either.MonadMap(fa, f)
|
||||
}
|
||||
|
||||
// MonadBiMap applies two functions: one to transform a Left value, another to transform a Right value.
|
||||
@@ -102,7 +102,7 @@ func MonadMap[A, B any](fa Result[A], f func(a A) B) Result[B] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadBiMap[E, A, B any](fa Result[A], f func(error) E, g func(a A) B) Either[E, B] {
|
||||
return either.MonadBiMap[error, E, A, B](fa, f, g)
|
||||
return either.MonadBiMap(fa, f, g)
|
||||
}
|
||||
|
||||
// BiMap is the curried version of [MonadBiMap].
|
||||
@@ -110,7 +110,7 @@ func MonadBiMap[E, A, B any](fa Result[A], f func(error) E, g func(a A) B) Eithe
|
||||
//
|
||||
//go:inline
|
||||
func BiMap[E, A, B any](f func(error) E, g func(a A) B) func(Result[A]) Either[E, B] {
|
||||
return either.BiMap[error, E, A, B](f, g)
|
||||
return either.BiMap(f, g)
|
||||
}
|
||||
|
||||
// MonadMapTo replaces the Right value with a constant value.
|
||||
@@ -122,14 +122,14 @@ func BiMap[E, A, B any](f func(error) E, g func(a A) B) func(Result[A]) Either[E
|
||||
//
|
||||
//go:inline
|
||||
func MonadMapTo[A, B any](fa Result[A], b B) Result[B] {
|
||||
return either.MonadMapTo[error, A, B](fa, b)
|
||||
return either.MonadMapTo(fa, b)
|
||||
}
|
||||
|
||||
// MapTo is the curried version of [MonadMapTo].
|
||||
//
|
||||
//go:inline
|
||||
func MapTo[A, B any](b B) Operator[A, B] {
|
||||
return either.MapTo[error, A, B](b)
|
||||
return either.MapTo[error, A](b)
|
||||
}
|
||||
|
||||
// MonadMapLeft applies a transformation function to the Left (error) value.
|
||||
@@ -144,7 +144,7 @@ func MapTo[A, B any](b B) Operator[A, B] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadMapLeft[A, E any](fa Result[A], f func(error) E) Either[E, A] {
|
||||
return either.MonadMapLeft[error, A, E](fa, f)
|
||||
return either.MonadMapLeft(fa, f)
|
||||
}
|
||||
|
||||
// Map is the curried version of [MonadMap].
|
||||
@@ -152,7 +152,7 @@ func MonadMapLeft[A, E any](fa Result[A], f func(error) E) Either[E, A] {
|
||||
//
|
||||
//go:inline
|
||||
func Map[A, B any](f func(a A) B) Operator[A, B] {
|
||||
return either.Map[error, A, B](f)
|
||||
return either.Map[error](f)
|
||||
}
|
||||
|
||||
// MapLeft is the curried version of [MonadMapLeft].
|
||||
@@ -160,7 +160,7 @@ func Map[A, B any](f func(a A) B) Operator[A, B] {
|
||||
//
|
||||
//go:inline
|
||||
func MapLeft[A, E any](f func(error) E) func(fa Result[A]) Either[E, A] {
|
||||
return either.MapLeft[A, error, E](f)
|
||||
return either.MapLeft[A](f)
|
||||
}
|
||||
|
||||
// MonadChain sequences two computations, where the second depends on the result of the first.
|
||||
@@ -178,7 +178,7 @@ func MapLeft[A, E any](f func(error) E) func(fa Result[A]) Either[E, A] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadChain[A, B any](fa Result[A], f Kleisli[A, B]) Result[B] {
|
||||
return either.MonadChain[error, A, B](fa, f)
|
||||
return either.MonadChain(fa, f)
|
||||
}
|
||||
|
||||
// MonadChainFirst executes a side-effect computation but returns the original value.
|
||||
@@ -196,7 +196,7 @@ func MonadChain[A, B any](fa Result[A], f Kleisli[A, B]) Result[B] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadChainFirst[A, B any](ma Result[A], f Kleisli[A, B]) Result[A] {
|
||||
return either.MonadChainFirst[error, A, B](ma, f)
|
||||
return either.MonadChainFirst(ma, f)
|
||||
}
|
||||
|
||||
// MonadChainTo ignores the first Either and returns the second.
|
||||
@@ -204,7 +204,7 @@ func MonadChainFirst[A, B any](ma Result[A], f Kleisli[A, B]) Result[A] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadChainTo[A, B any](ma Result[A], mb Result[B]) Result[B] {
|
||||
return either.MonadChainTo[A, error, B](ma, mb)
|
||||
return either.MonadChainTo(ma, mb)
|
||||
}
|
||||
|
||||
// MonadChainOptionK chains a function that returns an Option, converting None to Left.
|
||||
@@ -222,21 +222,21 @@ func MonadChainTo[A, B any](ma Result[A], mb Result[B]) Result[B] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadChainOptionK[A, B any](onNone func() error, ma Result[A], f option.Kleisli[A, B]) Result[B] {
|
||||
return either.MonadChainOptionK[A, B, error](onNone, ma, f)
|
||||
return either.MonadChainOptionK(onNone, ma, f)
|
||||
}
|
||||
|
||||
// ChainOptionK is the curried version of [MonadChainOptionK].
|
||||
//
|
||||
//go:inline
|
||||
func ChainOptionK[A, B any](onNone func() error) func(option.Kleisli[A, B]) Operator[A, B] {
|
||||
return either.ChainOptionK[A, B, error](onNone)
|
||||
return either.ChainOptionK[A, B](onNone)
|
||||
}
|
||||
|
||||
// ChainTo is the curried version of [MonadChainTo].
|
||||
//
|
||||
//go:inline
|
||||
func ChainTo[A, B any](mb Result[B]) Operator[A, B] {
|
||||
return either.ChainTo[A, error, B](mb)
|
||||
return either.ChainTo[A](mb)
|
||||
}
|
||||
|
||||
// Chain is the curried version of [MonadChain].
|
||||
@@ -244,14 +244,14 @@ func ChainTo[A, B any](mb Result[B]) Operator[A, B] {
|
||||
//
|
||||
//go:inline
|
||||
func Chain[A, B any](f Kleisli[A, B]) Operator[A, B] {
|
||||
return either.Chain[error, A, B](f)
|
||||
return either.Chain(f)
|
||||
}
|
||||
|
||||
// ChainFirst is the curried version of [MonadChainFirst].
|
||||
//
|
||||
//go:inline
|
||||
func ChainFirst[A, B any](f Kleisli[A, B]) Operator[A, A] {
|
||||
return either.ChainFirst[error, A, B](f)
|
||||
return either.ChainFirst(f)
|
||||
}
|
||||
|
||||
// Flatten removes one level of nesting from a nested Either.
|
||||
@@ -263,7 +263,7 @@ func ChainFirst[A, B any](f Kleisli[A, B]) Operator[A, A] {
|
||||
//
|
||||
//go:inline
|
||||
func Flatten[A any](mma Result[Result[A]]) Result[A] {
|
||||
return either.Flatten[error, A](mma)
|
||||
return either.Flatten(mma)
|
||||
}
|
||||
|
||||
// TryCatch converts a (value, error) tuple into an Either, applying a transformation to the error.
|
||||
@@ -277,7 +277,7 @@ func Flatten[A any](mma Result[Result[A]]) Result[A] {
|
||||
//
|
||||
//go:inline
|
||||
func TryCatch[FE Endomorphism[error], A any](val A, err error, onThrow FE) Result[A] {
|
||||
return either.TryCatch[FE, error, A](val, err, onThrow)
|
||||
return either.TryCatch(val, err, onThrow)
|
||||
}
|
||||
|
||||
// TryCatchError is a specialized version of [TryCatch] for error types.
|
||||
@@ -290,7 +290,7 @@ func TryCatch[FE Endomorphism[error], A any](val A, err error, onThrow FE) Resul
|
||||
//
|
||||
//go:inline
|
||||
func TryCatchError[A any](val A, err error) Result[A] {
|
||||
return either.TryCatchError[A](val, err)
|
||||
return either.TryCatchError(val, err)
|
||||
}
|
||||
|
||||
// Sequence2 sequences two Either values using a combining function.
|
||||
@@ -298,7 +298,7 @@ func TryCatchError[A any](val A, err error) Result[A] {
|
||||
//
|
||||
//go:inline
|
||||
func Sequence2[T1, T2, R any](f func(T1, T2) Result[R]) func(Result[T1], Result[T2]) Result[R] {
|
||||
return either.Sequence2[error, T1, T2, R](f)
|
||||
return either.Sequence2(f)
|
||||
}
|
||||
|
||||
// Sequence3 sequences three Either values using a combining function.
|
||||
@@ -306,7 +306,7 @@ func Sequence2[T1, T2, R any](f func(T1, T2) Result[R]) func(Result[T1], Result[
|
||||
//
|
||||
//go:inline
|
||||
func Sequence3[T1, T2, T3, R any](f func(T1, T2, T3) Result[R]) func(Result[T1], Result[T2], Result[T3]) Result[R] {
|
||||
return either.Sequence3[error, T1, T2, T3, R](f)
|
||||
return either.Sequence3(f)
|
||||
}
|
||||
|
||||
// FromOption converts an Option to an Either, using the provided function to generate a Left value for None.
|
||||
@@ -318,7 +318,7 @@ func Sequence3[T1, T2, T3, R any](f func(T1, T2, T3) Result[R]) func(Result[T1],
|
||||
//
|
||||
//go:inline
|
||||
func FromOption[A any](onNone func() error) func(Option[A]) Result[A] {
|
||||
return either.FromOption[A, error](onNone)
|
||||
return either.FromOption[A](onNone)
|
||||
}
|
||||
|
||||
// ToOption converts an Either to an Option, discarding the Left value.
|
||||
@@ -330,7 +330,7 @@ func FromOption[A any](onNone func() error) func(Option[A]) Result[A] {
|
||||
//
|
||||
//go:inline
|
||||
func ToOption[A any](ma Result[A]) Option[A] {
|
||||
return either.ToOption[error, A](ma)
|
||||
return either.ToOption(ma)
|
||||
}
|
||||
|
||||
// FromError creates an Either from a function that may return an error.
|
||||
@@ -346,7 +346,7 @@ func ToOption[A any](ma Result[A]) Option[A] {
|
||||
//
|
||||
//go:inline
|
||||
func FromError[A any](f func(a A) error) Kleisli[A, A] {
|
||||
return either.FromError[A](f)
|
||||
return either.FromError(f)
|
||||
}
|
||||
|
||||
// ToError converts an Result[A] to an error, returning nil for Right values.
|
||||
@@ -358,7 +358,7 @@ func FromError[A any](f func(a A) error) Kleisli[A, A] {
|
||||
//
|
||||
//go:inline
|
||||
func ToError[A any](e Result[A]) error {
|
||||
return either.ToError[A](e)
|
||||
return either.ToError(e)
|
||||
}
|
||||
|
||||
// Fold is the curried version of [MonadFold].
|
||||
@@ -373,7 +373,7 @@ func ToError[A any](e Result[A]) error {
|
||||
//
|
||||
//go:inline
|
||||
func Fold[A, B any](onLeft func(error) B, onRight func(A) B) func(Result[A]) B {
|
||||
return either.Fold[error, A, B](onLeft, onRight)
|
||||
return either.Fold(onLeft, onRight)
|
||||
}
|
||||
|
||||
// UnwrapError converts an Result[A] into the idiomatic Go tuple (A, error).
|
||||
@@ -385,7 +385,7 @@ func Fold[A, B any](onLeft func(error) B, onRight func(A) B) func(Result[A]) B {
|
||||
//
|
||||
//go:inline
|
||||
func UnwrapError[A any](ma Result[A]) (A, error) {
|
||||
return either.UnwrapError[A](ma)
|
||||
return either.UnwrapError(ma)
|
||||
}
|
||||
|
||||
// FromPredicate creates an Either based on a predicate.
|
||||
@@ -402,7 +402,7 @@ func UnwrapError[A any](ma Result[A]) (A, error) {
|
||||
//
|
||||
//go:inline
|
||||
func FromPredicate[A any](pred func(A) bool, onFalse func(A) error) Kleisli[A, A] {
|
||||
return either.FromPredicate[error, A](pred, onFalse)
|
||||
return either.FromPredicate(pred, onFalse)
|
||||
}
|
||||
|
||||
// FromNillable creates an Either from a pointer, using the provided error for nil pointers.
|
||||
@@ -416,7 +416,7 @@ func FromPredicate[A any](pred func(A) bool, onFalse func(A) error) Kleisli[A, A
|
||||
//
|
||||
//go:inline
|
||||
func FromNillable[A any](e error) func(*A) Result[*A] {
|
||||
return either.FromNillable[A, error](e)
|
||||
return either.FromNillable[A](e)
|
||||
}
|
||||
|
||||
// GetOrElse extracts the Right value or computes a default from the Left value.
|
||||
@@ -428,7 +428,7 @@ func FromNillable[A any](e error) func(*A) Result[*A] {
|
||||
//
|
||||
//go:inline
|
||||
func GetOrElse[A any](onLeft func(error) A) func(Result[A]) A {
|
||||
return either.GetOrElse[error, A](onLeft)
|
||||
return either.GetOrElse(onLeft)
|
||||
}
|
||||
|
||||
// Reduce folds an Either into a single value using a reducer function.
|
||||
@@ -451,7 +451,7 @@ func Reduce[A, B any](f func(B, A) B, initial B) func(Result[A]) B {
|
||||
//
|
||||
//go:inline
|
||||
func AltW[E1, A any](that Lazy[Either[E1, A]]) func(Result[A]) Either[E1, A] {
|
||||
return either.AltW[error, E1, A](that)
|
||||
return either.AltW[error](that)
|
||||
}
|
||||
|
||||
// Alt provides an alternative Either if the first is Left.
|
||||
@@ -465,7 +465,7 @@ func AltW[E1, A any](that Lazy[Either[E1, A]]) func(Result[A]) Either[E1, A] {
|
||||
//
|
||||
//go:inline
|
||||
func Alt[A any](that Lazy[Result[A]]) Operator[A, A] {
|
||||
return either.Alt[error](that)
|
||||
return either.Alt(that)
|
||||
}
|
||||
|
||||
// OrElse recovers from a Left by providing an alternative computation.
|
||||
@@ -479,7 +479,7 @@ func Alt[A any](that Lazy[Result[A]]) Operator[A, A] {
|
||||
//
|
||||
//go:inline
|
||||
func OrElse[A any](onLeft Kleisli[error, A]) Operator[A, A] {
|
||||
return either.OrElse[error, A](onLeft)
|
||||
return either.OrElse(onLeft)
|
||||
}
|
||||
|
||||
// ToType attempts to convert an any value to a specific type, returning Either.
|
||||
@@ -494,14 +494,14 @@ func OrElse[A any](onLeft Kleisli[error, A]) Operator[A, A] {
|
||||
//
|
||||
//go:inline
|
||||
func ToType[A any](onError func(any) error) Kleisli[any, A] {
|
||||
return either.ToType[A, error](onError)
|
||||
return either.ToType[A](onError)
|
||||
}
|
||||
|
||||
// Memoize returns the Either unchanged (Either values are already memoized).
|
||||
//
|
||||
//go:inline
|
||||
func Memoize[A any](val Result[A]) Result[A] {
|
||||
return either.Memoize[error, A](val)
|
||||
return either.Memoize(val)
|
||||
}
|
||||
|
||||
// MonadSequence2 sequences two Either values using a combining function.
|
||||
@@ -509,7 +509,7 @@ func Memoize[A any](val Result[A]) Result[A] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadSequence2[T1, T2, R any](e1 Result[T1], e2 Result[T2], f func(T1, T2) Result[R]) Result[R] {
|
||||
return either.MonadSequence2[error, T1, T2, R](e1, e2, f)
|
||||
return either.MonadSequence2(e1, e2, f)
|
||||
}
|
||||
|
||||
// MonadSequence3 sequences three Either values using a combining function.
|
||||
@@ -517,7 +517,7 @@ func MonadSequence2[T1, T2, R any](e1 Result[T1], e2 Result[T2], f func(T1, T2)
|
||||
//
|
||||
//go:inline
|
||||
func MonadSequence3[T1, T2, T3, R any](e1 Result[T1], e2 Result[T2], e3 Result[T3], f func(T1, T2, T3) Result[R]) Result[R] {
|
||||
return either.MonadSequence3[error, T1, T2, T3, R](e1, e2, e3, f)
|
||||
return either.MonadSequence3(e1, e2, e3, f)
|
||||
}
|
||||
|
||||
// Swap exchanges the Left and Right type parameters.
|
||||
@@ -529,7 +529,7 @@ func MonadSequence3[T1, T2, T3, R any](e1 Result[T1], e2 Result[T2], e3 Result[T
|
||||
//
|
||||
//go:inline
|
||||
func Swap[A any](val Result[A]) Either[A, error] {
|
||||
return either.Swap[error, A](val)
|
||||
return either.Swap(val)
|
||||
}
|
||||
|
||||
// MonadFlap applies a value to a function wrapped in Either.
|
||||
@@ -537,14 +537,14 @@ func Swap[A any](val Result[A]) Either[A, error] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadFlap[B, A any](fab Result[func(A) B], a A) Result[B] {
|
||||
return either.MonadFlap[error, B, A](fab, a)
|
||||
return either.MonadFlap(fab, a)
|
||||
}
|
||||
|
||||
// Flap is the curried version of [MonadFlap].
|
||||
//
|
||||
//go:inline
|
||||
func Flap[B, A any](a A) Operator[func(A) B, B] {
|
||||
return either.Flap[error, B, A](a)
|
||||
return either.Flap[error, B](a)
|
||||
}
|
||||
|
||||
// MonadAlt provides an alternative Either if the first is Left.
|
||||
@@ -552,5 +552,5 @@ func Flap[B, A any](a A) Operator[func(A) B, B] {
|
||||
//
|
||||
//go:inline
|
||||
func MonadAlt[A any](fa Result[A], that Lazy[Result[A]]) Result[A] {
|
||||
return either.MonadAlt[error, A](fa, that)
|
||||
return either.MonadAlt(fa, that)
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestMapEither(t *testing.T) {
|
||||
e := errors.New("s")
|
||||
assert.Equal(t, F.Pipe1(Right("abc"), Map(utils.StringLen)), Right(3))
|
||||
|
||||
val2 := F.Pipe1(Left[string](e), Map[string](utils.StringLen))
|
||||
val2 := F.Pipe1(Left[string](e), Map(utils.StringLen))
|
||||
exp2 := Left[int](e)
|
||||
|
||||
assert.Equal(t, val2, exp2)
|
||||
@@ -68,8 +68,8 @@ func TestReduce(t *testing.T) {
|
||||
|
||||
s := S.Semigroup()
|
||||
|
||||
assert.Equal(t, "foobar", F.Pipe1(Right("bar"), Reduce[string](s.Concat, "foo")))
|
||||
assert.Equal(t, "foo", F.Pipe1(Left[string](errors.New("bar")), Reduce[string](s.Concat, "foo")))
|
||||
assert.Equal(t, "foobar", F.Pipe1(Right("bar"), Reduce(s.Concat, "foo")))
|
||||
assert.Equal(t, "foo", F.Pipe1(Left[string](errors.New("bar")), Reduce(s.Concat, "foo")))
|
||||
|
||||
}
|
||||
func TestAp(t *testing.T) {
|
||||
@@ -78,9 +78,9 @@ func TestAp(t *testing.T) {
|
||||
maError := errors.New("maError")
|
||||
mabError := errors.New("mabError")
|
||||
|
||||
assert.Equal(t, Right(3), F.Pipe1(Right(f), Ap[int, string](Right("abc"))))
|
||||
assert.Equal(t, Left[int](maError), F.Pipe1(Right(f), Ap[int, string](Left[string](maError))))
|
||||
assert.Equal(t, Left[int](mabError), F.Pipe1(Left[func(string) int](mabError), Ap[int, string](Left[string](maError))))
|
||||
assert.Equal(t, Right(3), F.Pipe1(Right(f), Ap[int](Right("abc"))))
|
||||
assert.Equal(t, Left[int](maError), F.Pipe1(Right(f), Ap[int](Left[string](maError))))
|
||||
assert.Equal(t, Left[int](mabError), F.Pipe1(Left[func(string) int](mabError), Ap[int](Left[string](maError))))
|
||||
}
|
||||
|
||||
func TestAlt(t *testing.T) {
|
||||
|
||||
@@ -18,7 +18,6 @@ package result
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/either"
|
||||
"github.com/IBM/fp-go/v2/eq"
|
||||
EQ "github.com/IBM/fp-go/v2/eq"
|
||||
)
|
||||
|
||||
// Eq constructs an equality predicate for Either values.
|
||||
@@ -34,8 +33,8 @@ import (
|
||||
// eq := either.Eq(eq.FromStrictEquals[error](), eq.FromStrictEquals[int]())
|
||||
// result := eq.Equals(either.Right[error](42), either.Right[error](42)) // true
|
||||
// result2 := eq.Equals(either.Right[error](42), either.Right[error](43)) // false
|
||||
func Eq[A any](a EQ.Eq[A]) EQ.Eq[Result[A]] {
|
||||
return either.Eq[error, A](eq.FromStrictEquals[error](), a)
|
||||
func Eq[A any](a eq.Eq[A]) eq.Eq[Result[A]] {
|
||||
return either.Eq(eq.FromStrictEquals[error](), a)
|
||||
}
|
||||
|
||||
// FromStrictEquals constructs an equality predicate using Go's == operator.
|
||||
@@ -45,6 +44,6 @@ func Eq[A any](a EQ.Eq[A]) EQ.Eq[Result[A]] {
|
||||
//
|
||||
// eq := either.FromStrictEquals[error, int]()
|
||||
// result := eq.Equals(either.Right[error](42), either.Right[error](42)) // true
|
||||
func FromStrictEquals[A comparable]() EQ.Eq[Result[A]] {
|
||||
func FromStrictEquals[A comparable]() eq.Eq[Result[A]] {
|
||||
return either.FromStrictEquals[error, A]()
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
type eitherFunctor[A, B any] struct{}
|
||||
|
||||
func (o *eitherFunctor[A, B]) Map(f func(A) B) Operator[A, B] {
|
||||
return Map[A, B](f)
|
||||
return Map(f)
|
||||
}
|
||||
|
||||
// Functor implements the functoric operations for Either.
|
||||
|
||||
@@ -59,7 +59,7 @@ func TestUneitherize1(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "positive", result)
|
||||
|
||||
result, err = uneitherized(-1)
|
||||
_, err = uneitherized(-1)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func TestUneitherize2(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 8, result)
|
||||
|
||||
result, err = uneitherized(-1, 3)
|
||||
_, err = uneitherized(-1, 3)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,19 +22,19 @@ import (
|
||||
type eitherMonad[A, B any] struct{}
|
||||
|
||||
func (o *eitherMonad[A, B]) Of(a A) Result[A] {
|
||||
return Of[A](a)
|
||||
return Of(a)
|
||||
}
|
||||
|
||||
func (o *eitherMonad[A, B]) Map(f func(A) B) Operator[A, B] {
|
||||
return Map[A, B](f)
|
||||
return Map(f)
|
||||
}
|
||||
|
||||
func (o *eitherMonad[A, B]) Chain(f func(A) Result[B]) Operator[A, B] {
|
||||
return Chain[A, B](f)
|
||||
return Chain(f)
|
||||
}
|
||||
|
||||
func (o *eitherMonad[A, B]) Ap(fa Result[A]) Operator[func(A) B, B] {
|
||||
return Ap[B, A](fa)
|
||||
return Ap[B](fa)
|
||||
}
|
||||
|
||||
// Monad implements the monadic operations for Either.
|
||||
|
||||
@@ -34,7 +34,7 @@ import (
|
||||
//
|
||||
//go:inline
|
||||
func AlternativeMonoid[A any](m M.Monoid[A]) Monoid[A] {
|
||||
return either.AlternativeMonoid[error, A](m)
|
||||
return either.AlternativeMonoid[error](m)
|
||||
}
|
||||
|
||||
// AltMonoid creates a monoid for Either using the Alt operation.
|
||||
@@ -50,5 +50,5 @@ func AlternativeMonoid[A any](m M.Monoid[A]) Monoid[A] {
|
||||
//
|
||||
//go:inline
|
||||
func AltMonoid[A any](zero Lazy[Result[A]]) Monoid[A] {
|
||||
return either.AltMonoid[error, A](zero)
|
||||
return either.AltMonoid(zero)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
type eitherPointed[A any] struct{}
|
||||
|
||||
func (o *eitherPointed[A]) Of(a A) Result[A] {
|
||||
return Of[A](a)
|
||||
return Of(a)
|
||||
}
|
||||
|
||||
// Pointed implements the pointed functor operations for Either.
|
||||
|
||||
@@ -35,7 +35,7 @@ import (
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, A, B any](f Kleisli[A, B]) Kleisli[GA, GB] {
|
||||
return either.TraverseRecordG[GA, GB, K, error, A, B](f)
|
||||
return either.TraverseRecordG[GA, GB](f)
|
||||
}
|
||||
|
||||
// TraverseRecord transforms a map by applying a function that returns an Either to each value.
|
||||
@@ -53,7 +53,7 @@ func TraverseRecordG[GA ~map[K]A, GB ~map[K]B, K comparable, A, B any](f Kleisli
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecord[K comparable, A, B any](f Kleisli[A, B]) Kleisli[map[K]A, map[K]B] {
|
||||
return either.TraverseRecord[K, error, A, B](f)
|
||||
return either.TraverseRecord[K](f)
|
||||
}
|
||||
|
||||
// TraverseRecordWithIndexG transforms a map by applying an indexed function that returns an Either.
|
||||
@@ -74,7 +74,7 @@ func TraverseRecord[K comparable, A, B any](f Kleisli[A, B]) Kleisli[map[K]A, ma
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecordWithIndexG[GA ~map[K]A, GB ~map[K]B, K comparable, A, B any](f func(K, A) Result[B]) Kleisli[GA, GB] {
|
||||
return either.TraverseRecordWithIndexG[GA, GB, K, error, A, B](f)
|
||||
return either.TraverseRecordWithIndexG[GA, GB](f)
|
||||
}
|
||||
|
||||
// TraverseRecordWithIndex transforms a map by applying an indexed function that returns an Either.
|
||||
@@ -94,12 +94,12 @@ func TraverseRecordWithIndexG[GA ~map[K]A, GB ~map[K]B, K comparable, A, B any](
|
||||
//
|
||||
//go:inline
|
||||
func TraverseRecordWithIndex[K comparable, A, B any](f func(K, A) Result[B]) Kleisli[map[K]A, map[K]B] {
|
||||
return either.TraverseRecordWithIndex[K, error, A, B](f)
|
||||
return either.TraverseRecordWithIndex(f)
|
||||
}
|
||||
|
||||
//go:inline
|
||||
func SequenceRecordG[GA ~map[K]A, GOA ~map[K]Result[A], K comparable, A any](ma GOA) Result[GA] {
|
||||
return either.SequenceRecordG[GA, GOA, K, error, A](ma)
|
||||
return either.SequenceRecordG[GA](ma)
|
||||
}
|
||||
|
||||
// SequenceRecord converts a map of Either values into an Either of a map.
|
||||
@@ -117,7 +117,7 @@ func SequenceRecordG[GA ~map[K]A, GOA ~map[K]Result[A], K comparable, A any](ma
|
||||
//
|
||||
//go:inline
|
||||
func SequenceRecord[K comparable, A any](ma map[K]Result[A]) Result[map[K]A] {
|
||||
return either.SequenceRecord[K, error, A](ma)
|
||||
return either.SequenceRecord(ma)
|
||||
}
|
||||
|
||||
// CompactRecordG discards all Left values and keeps only the Right values.
|
||||
@@ -133,7 +133,7 @@ func SequenceRecord[K comparable, A any](ma map[K]Result[A]) Result[map[K]A] {
|
||||
// result := either.CompactRecordG[map[string]either.Result[int], map[string]int](eithers)
|
||||
// // result is map[string]int{"a": 1, "c": 3}
|
||||
func CompactRecordG[M1 ~map[K]Result[A], M2 ~map[K]A, K comparable, A any](m M1) M2 {
|
||||
return either.CompactRecordG[M1, M2, K, error, A](m)
|
||||
return either.CompactRecordG[M1, M2](m)
|
||||
}
|
||||
|
||||
// CompactRecord discards all Left values and keeps only the Right values.
|
||||
@@ -150,5 +150,5 @@ func CompactRecordG[M1 ~map[K]Result[A], M2 ~map[K]A, K comparable, A any](m M1)
|
||||
//
|
||||
//go:inline
|
||||
func CompactRecord[K comparable, A any](m map[K]Result[A]) map[K]A {
|
||||
return either.CompactRecord[K, error, A](m)
|
||||
return either.CompactRecord(m)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func Traverse[A, B, HKTB, HKTRB any](
|
||||
mof func(Result[B]) HKTRB,
|
||||
mmap func(Kleisli[B, B]) func(HKTB) HKTRB,
|
||||
) func(func(A) HKTB) func(Result[A]) HKTRB {
|
||||
return either.Traverse[A, error, B](mof, mmap)
|
||||
return either.Traverse[A](mof, mmap)
|
||||
}
|
||||
|
||||
// Sequence converts an Either of some higher kinded type into the higher kinded type of an Either.
|
||||
@@ -62,5 +62,5 @@ func Sequence[A, HKTA, HKTRA any](
|
||||
mof func(Result[A]) HKTRA,
|
||||
mmap func(Kleisli[A, A]) func(HKTA) HKTRA,
|
||||
) func(Result[HKTA]) HKTRA {
|
||||
return either.Sequence[error, A, HKTA, HKTRA](mof, mmap)
|
||||
return either.Sequence(mof, mmap)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
package result
|
||||
|
||||
import "github.com/IBM/fp-go/v2/either"
|
||||
|
||||
// Variadic0 converts a function taking a slice and returning (R, error) into a variadic function returning Either.
|
||||
//
|
||||
// Example:
|
||||
@@ -26,71 +28,61 @@ package result
|
||||
// }
|
||||
// variadicSum := either.Variadic0(sum)
|
||||
// result := variadicSum(1, 2, 3) // Right(6)
|
||||
//go:inline
|
||||
func Variadic0[V, R any](f func([]V) (R, error)) func(...V) Result[R] {
|
||||
return func(v ...V) Result[R] {
|
||||
return TryCatchError(f(v))
|
||||
}
|
||||
return either.Variadic0(f)
|
||||
}
|
||||
|
||||
// Variadic1 converts a function with 1 fixed parameter and a slice into a variadic function returning Either.
|
||||
//go:inline
|
||||
func Variadic1[T1, V, R any](f func(T1, []V) (R, error)) func(T1, ...V) Result[R] {
|
||||
return func(t1 T1, v ...V) Result[R] {
|
||||
return TryCatchError(f(t1, v))
|
||||
}
|
||||
return either.Variadic1(f)
|
||||
}
|
||||
|
||||
// Variadic2 converts a function with 2 fixed parameters and a slice into a variadic function returning Either.
|
||||
//go:inline
|
||||
func Variadic2[T1, T2, V, R any](f func(T1, T2, []V) (R, error)) func(T1, T2, ...V) Result[R] {
|
||||
return func(t1 T1, t2 T2, v ...V) Result[R] {
|
||||
return TryCatchError(f(t1, t2, v))
|
||||
}
|
||||
return either.Variadic2(f)
|
||||
}
|
||||
|
||||
// Variadic3 converts a function with 3 fixed parameters and a slice into a variadic function returning Either.
|
||||
//go:inline
|
||||
func Variadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, []V) (R, error)) func(T1, T2, T3, ...V) Result[R] {
|
||||
return func(t1 T1, t2 T2, t3 T3, v ...V) Result[R] {
|
||||
return TryCatchError(f(t1, t2, t3, v))
|
||||
}
|
||||
return either.Variadic3(f)
|
||||
}
|
||||
|
||||
// Variadic4 converts a function with 4 fixed parameters and a slice into a variadic function returning Either.
|
||||
//go:inline
|
||||
func Variadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, []V) (R, error)) func(T1, T2, T3, T4, ...V) Result[R] {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, v ...V) Result[R] {
|
||||
return TryCatchError(f(t1, t2, t3, t4, v))
|
||||
}
|
||||
return either.Variadic4(f)
|
||||
}
|
||||
|
||||
// Unvariadic0 converts a variadic function returning (R, error) into a function taking a slice and returning Either.
|
||||
//go:inline
|
||||
func Unvariadic0[V, R any](f func(...V) (R, error)) func([]V) Result[R] {
|
||||
return func(v []V) Result[R] {
|
||||
return TryCatchError(f(v...))
|
||||
}
|
||||
return either.Unvariadic0(f)
|
||||
}
|
||||
|
||||
// Unvariadic1 converts a variadic function with 1 fixed parameter into a function taking a slice and returning Either.
|
||||
//go:inline
|
||||
func Unvariadic1[T1, V, R any](f func(T1, ...V) (R, error)) func(T1, []V) Result[R] {
|
||||
return func(t1 T1, v []V) Result[R] {
|
||||
return TryCatchError(f(t1, v...))
|
||||
}
|
||||
return either.Unvariadic1(f)
|
||||
}
|
||||
|
||||
// Unvariadic2 converts a variadic function with 2 fixed parameters into a function taking a slice and returning Either.
|
||||
//go:inline
|
||||
func Unvariadic2[T1, T2, V, R any](f func(T1, T2, ...V) (R, error)) func(T1, T2, []V) Result[R] {
|
||||
return func(t1 T1, t2 T2, v []V) Result[R] {
|
||||
return TryCatchError(f(t1, t2, v...))
|
||||
}
|
||||
return either.Unvariadic2(f)
|
||||
}
|
||||
|
||||
// Unvariadic3 converts a variadic function with 3 fixed parameters into a function taking a slice and returning Either.
|
||||
//go:inline
|
||||
func Unvariadic3[T1, T2, T3, V, R any](f func(T1, T2, T3, ...V) (R, error)) func(T1, T2, T3, []V) Result[R] {
|
||||
return func(t1 T1, t2 T2, t3 T3, v []V) Result[R] {
|
||||
return TryCatchError(f(t1, t2, t3, v...))
|
||||
}
|
||||
return either.Unvariadic3(f)
|
||||
}
|
||||
|
||||
// Unvariadic4 converts a variadic function with 4 fixed parameters into a function taking a slice and returning Either.
|
||||
//go:inline
|
||||
func Unvariadic4[T1, T2, T3, T4, V, R any](f func(T1, T2, T3, T4, ...V) (R, error)) func(T1, T2, T3, T4, []V) Result[R] {
|
||||
return func(t1 T1, t2 T2, t3 T3, t4 T4, v []V) Result[R] {
|
||||
return TryCatchError(f(t1, t2, t3, t4, v...))
|
||||
}
|
||||
return either.Unvariadic4(f)
|
||||
}
|
||||
|
||||
@@ -24,10 +24,11 @@ import (
|
||||
"github.com/IBM/fp-go/v2/errors"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
I "github.com/IBM/fp-go/v2/identity"
|
||||
IOE "github.com/IBM/fp-go/v2/ioeither"
|
||||
"github.com/IBM/fp-go/v2/ioresult"
|
||||
N "github.com/IBM/fp-go/v2/number"
|
||||
O "github.com/IBM/fp-go/v2/option"
|
||||
"github.com/IBM/fp-go/v2/ord"
|
||||
R "github.com/IBM/fp-go/v2/result"
|
||||
S "github.com/IBM/fp-go/v2/string"
|
||||
)
|
||||
|
||||
@@ -108,7 +109,7 @@ var (
|
||||
checkActive = E.FromPredicate(Chapter08User.isActive, F.Constant1[Chapter08User](fmt.Errorf("your account is not active")))
|
||||
|
||||
// validateUser :: (User -> Either String ()) -> User -> Either String User
|
||||
validateUser = F.Curry2(func(validate func(Chapter08User) Either[any], user Chapter08User) Either[Chapter08User] {
|
||||
validateUser = F.Curry2(func(validate func(Chapter08User) Result[any], user Chapter08User) Result[Chapter08User] {
|
||||
return F.Pipe2(
|
||||
user,
|
||||
validate,
|
||||
@@ -117,8 +118,8 @@ var (
|
||||
})
|
||||
|
||||
// save :: User -> IOEither error User
|
||||
save = func(user Chapter08User) IOEither[Chapter08User] {
|
||||
return IOE.FromIO[error](func() Chapter08User {
|
||||
save = func(user Chapter08User) IOResult[Chapter08User] {
|
||||
return ioresult.FromIO(func() Chapter08User {
|
||||
var u = user
|
||||
u.Saved = true
|
||||
return u
|
||||
@@ -151,11 +152,11 @@ func MakeUser(d string) User {
|
||||
|
||||
var parseDate = F.Bind1of2(E.Eitherize2(time.Parse))(time.DateOnly)
|
||||
|
||||
func GetAge(now time.Time) func(User) Either[float64] {
|
||||
func GetAge(now time.Time) func(User) Result[float64] {
|
||||
return F.Flow3(
|
||||
getBirthDate,
|
||||
parseDate,
|
||||
E.Map[error](F.Flow3(
|
||||
R.Map(F.Flow3(
|
||||
now.Sub,
|
||||
time.Duration.Hours,
|
||||
N.Mul(1/24.0),
|
||||
@@ -189,7 +190,7 @@ func Example_getAge() {
|
||||
|
||||
zoltar := F.Flow3(
|
||||
GetAge(now),
|
||||
E.Map[error](fortune),
|
||||
R.Map(fortune),
|
||||
E.GetOrElse(errors.ToString),
|
||||
)
|
||||
|
||||
@@ -228,7 +229,7 @@ func Example_solution08C() {
|
||||
// eitherWelcome :: User -> Either String String
|
||||
eitherWelcome := F.Flow2(
|
||||
checkActive,
|
||||
E.Map[error](showWelcome),
|
||||
R.Map(showWelcome),
|
||||
)
|
||||
|
||||
fmt.Println(eitherWelcome(gary08))
|
||||
@@ -248,18 +249,18 @@ func Example_solution08D() {
|
||||
S.Size,
|
||||
ord.Gt(ord.FromStrictCompare[int]())(3),
|
||||
), errors.OnSome[string]("Your name %s is larger than 3 characters")),
|
||||
E.Map[error](F.ToAny[string]),
|
||||
R.Map(F.ToAny[string]),
|
||||
)
|
||||
|
||||
saveAndWelcome := F.Flow2(
|
||||
save,
|
||||
IOE.Map[error](showWelcome),
|
||||
ioresult.Map(showWelcome),
|
||||
)
|
||||
|
||||
register := F.Flow3(
|
||||
validateUser(validateName),
|
||||
IOE.FromEither[error, Chapter08User],
|
||||
IOE.Chain(saveAndWelcome),
|
||||
ioresult.FromEither[Chapter08User],
|
||||
ioresult.Chain(saveAndWelcome),
|
||||
)
|
||||
|
||||
fmt.Println(validateName(gary08))
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"github.com/IBM/fp-go/v2/errors"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
"github.com/IBM/fp-go/v2/io"
|
||||
IOE "github.com/IBM/fp-go/v2/ioeither"
|
||||
"github.com/IBM/fp-go/v2/ioresult"
|
||||
O "github.com/IBM/fp-go/v2/option"
|
||||
S "github.com/IBM/fp-go/v2/string"
|
||||
)
|
||||
@@ -112,7 +112,7 @@ var (
|
||||
// addToMailingList :: Email -> IOEither([Email])
|
||||
addToMailingList = F.Flow2(
|
||||
A.Of[string],
|
||||
IOE.Of[error, []string],
|
||||
ioresult.Of[[]string],
|
||||
)
|
||||
|
||||
// validateEmail :: Email -> Either error Email
|
||||
@@ -121,7 +121,7 @@ var (
|
||||
// emailBlast :: [Email] -> IO ()
|
||||
emailBlast = F.Flow2(
|
||||
A.Intercalate(S.Monoid)(","),
|
||||
IOE.Of[error, string],
|
||||
ioresult.Of[string],
|
||||
)
|
||||
)
|
||||
|
||||
@@ -172,9 +172,9 @@ func Example_solution09C() {
|
||||
// // joinMailingList :: Email -> Either String (IO ())
|
||||
joinMailingList := F.Flow4(
|
||||
validateEmail,
|
||||
IOE.FromEither[error, string],
|
||||
IOE.Chain(addToMailingList),
|
||||
IOE.Chain(emailBlast),
|
||||
ioresult.FromEither[string],
|
||||
ioresult.Chain(addToMailingList),
|
||||
ioresult.Chain(emailBlast),
|
||||
)
|
||||
|
||||
fmt.Println(joinMailingList("sleepy@grandpa.net")())
|
||||
|
||||
@@ -20,31 +20,31 @@ import (
|
||||
"regexp"
|
||||
|
||||
A "github.com/IBM/fp-go/v2/array"
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
IOE "github.com/IBM/fp-go/v2/ioeither"
|
||||
"github.com/IBM/fp-go/v2/ioresult"
|
||||
R "github.com/IBM/fp-go/v2/result"
|
||||
S "github.com/IBM/fp-go/v2/string"
|
||||
)
|
||||
|
||||
func findUserByID(id int) IOEither[Chapter08User] {
|
||||
func findUserByID(id int) IOResult[Chapter08User] {
|
||||
switch id {
|
||||
case 1:
|
||||
return IOE.Of[error](albert08)
|
||||
return ioresult.Of(albert08)
|
||||
case 2:
|
||||
return IOE.Of[error](gary08)
|
||||
return ioresult.Of(gary08)
|
||||
case 3:
|
||||
return IOE.Of[error](theresa08)
|
||||
return ioresult.Of(theresa08)
|
||||
default:
|
||||
return IOE.Left[Chapter08User](fmt.Errorf("user %d not found", id))
|
||||
return ioresult.Left[Chapter08User](fmt.Errorf("user %d not found", id))
|
||||
}
|
||||
}
|
||||
|
||||
func Example_solution11A() {
|
||||
// eitherToMaybe :: Either b a -> Maybe a
|
||||
eitherToMaybe := E.ToOption[error, string]
|
||||
eitherToMaybe := R.ToOption[string]
|
||||
|
||||
fmt.Println(eitherToMaybe(E.Of[error]("one eyed willy")))
|
||||
fmt.Println(eitherToMaybe(E.Left[string](fmt.Errorf("some error"))))
|
||||
fmt.Println(eitherToMaybe(R.Of("one eyed willy")))
|
||||
fmt.Println(eitherToMaybe(R.Left[string](fmt.Errorf("some error"))))
|
||||
|
||||
// Output:
|
||||
// Some[string](one eyed willy)
|
||||
@@ -54,7 +54,7 @@ func Example_solution11A() {
|
||||
func Example_solution11B() {
|
||||
findByNameID := F.Flow2(
|
||||
findUserByID,
|
||||
IOE.Map[error](Chapter08User.getName),
|
||||
ioresult.Map(Chapter08User.getName),
|
||||
)
|
||||
|
||||
fmt.Println(findByNameID(1)())
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
"github.com/IBM/fp-go/v2/errors"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
IOE "github.com/IBM/fp-go/v2/ioeither"
|
||||
"github.com/IBM/fp-go/v2/ioresult"
|
||||
O "github.com/IBM/fp-go/v2/option"
|
||||
P "github.com/IBM/fp-go/v2/predicate"
|
||||
S "github.com/IBM/fp-go/v2/string"
|
||||
@@ -32,7 +32,7 @@ var (
|
||||
// httpGet :: Route -> Task Error JSON
|
||||
httpGet = F.Flow2(
|
||||
S.Format[string]("json for %s"),
|
||||
IOE.Of[error, string],
|
||||
ioresult.Of[string],
|
||||
)
|
||||
|
||||
// routes :: Map Route Route
|
||||
@@ -45,17 +45,17 @@ var (
|
||||
validatePlayer = E.FromPredicate(P.ContraMap(Player.getName)(S.IsNonEmpty), F.Flow2(Player.getID, errors.OnSome[int]("player %d must have a name")))
|
||||
|
||||
// readfile :: String -> String -> Task Error String
|
||||
readfile = F.Curry2(func(encoding, file string) IOEither[string] {
|
||||
return IOE.Of[error](fmt.Sprintf("content of %s (%s)", file, encoding))
|
||||
readfile = F.Curry2(func(encoding, file string) IOResult[string] {
|
||||
return ioresult.Of(fmt.Sprintf("content of %s (%s)", file, encoding))
|
||||
})
|
||||
|
||||
// readdir :: String -> Task Error [String]
|
||||
readdir = IOE.Of[error](A.From("file1", "file2", "file3"))
|
||||
readdir = ioresult.Of(A.From("file1", "file2", "file3"))
|
||||
)
|
||||
|
||||
func Example_solution12A() {
|
||||
// getJsons :: Map Route Route -> Task Error (Map Route JSON)
|
||||
getJsons := IOE.TraverseRecord[string](httpGet)
|
||||
getJsons := ioresult.TraverseRecord[string](httpGet)
|
||||
|
||||
fmt.Println(getJsons(routes)())
|
||||
|
||||
@@ -80,15 +80,15 @@ func Example_solution12B() {
|
||||
|
||||
func Example_solution12C() {
|
||||
traverseO := O.Traverse[string](
|
||||
IOE.Of[error, Option[string]],
|
||||
IOE.Map[error, string, Option[string]],
|
||||
ioresult.Of[Option[string]],
|
||||
ioresult.Map[string, Option[string]],
|
||||
)
|
||||
|
||||
// readFirst :: String -> Task Error (Maybe String)
|
||||
readFirst := F.Pipe2(
|
||||
readdir,
|
||||
IOE.Map[error](A.Head[string]),
|
||||
IOE.Chain(traverseO(readfile("utf-8"))),
|
||||
ioresult.Map(A.Head[string]),
|
||||
ioresult.Chain(traverseO(readfile("utf-8"))),
|
||||
)
|
||||
|
||||
fmt.Println(readFirst())
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
package mostlyadequate
|
||||
|
||||
import (
|
||||
"github.com/IBM/fp-go/v2/either"
|
||||
"github.com/IBM/fp-go/v2/ioeither"
|
||||
"github.com/IBM/fp-go/v2/iooption"
|
||||
"github.com/IBM/fp-go/v2/ioresult"
|
||||
"github.com/IBM/fp-go/v2/option"
|
||||
"github.com/IBM/fp-go/v2/result"
|
||||
)
|
||||
|
||||
type (
|
||||
Either[A any] = either.Either[error, A]
|
||||
IOEither[A any] = ioeither.IOEither[error, A]
|
||||
Result[A any] = result.Result[A]
|
||||
IOOption[A any] = iooption.IOOption[A]
|
||||
Option[A any] = option.Option[A]
|
||||
IOResult[A any] = ioresult.IOResult[A]
|
||||
)
|
||||
|
||||
@@ -21,10 +21,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
E "github.com/IBM/fp-go/v2/either"
|
||||
F "github.com/IBM/fp-go/v2/function"
|
||||
IOE "github.com/IBM/fp-go/v2/ioeither"
|
||||
IOEF "github.com/IBM/fp-go/v2/ioeither/file"
|
||||
R "github.com/IBM/fp-go/v2/result"
|
||||
T "github.com/IBM/fp-go/v2/tuple"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -49,7 +49,7 @@ func TestSampleConvertDocx1(t *testing.T) {
|
||||
|
||||
resE := resIOE()
|
||||
|
||||
assert.True(t, E.IsRight(resE))
|
||||
assert.True(t, R.IsRight(resE))
|
||||
}
|
||||
|
||||
func TestSampleConvertDocx2(t *testing.T) {
|
||||
@@ -59,12 +59,12 @@ func TestSampleConvertDocx2(t *testing.T) {
|
||||
// idea for large inputs
|
||||
convertDocx := func(data []byte) Either[T.Tuple2[string, map[string]string]] {
|
||||
text, meta, err := sampleConvertDocx(bytes.NewReader(data))
|
||||
return E.TryCatchError(T.MakeTuple2(text, meta), err)
|
||||
return R.TryCatchError(T.MakeTuple2(text, meta), err)
|
||||
}
|
||||
|
||||
resE := convertDocx([]byte("abc"))
|
||||
|
||||
assert.True(t, E.IsRight(resE))
|
||||
assert.True(t, R.IsRight(resE))
|
||||
}
|
||||
|
||||
// onClose closes a closeable resource
|
||||
@@ -112,7 +112,7 @@ func TestSampleConvertDocx3(t *testing.T) {
|
||||
resIOE := convertDocx3(acquire)
|
||||
resE := resIOE()
|
||||
|
||||
assert.True(t, E.IsRight(resE))
|
||||
assert.True(t, R.IsRight(resE))
|
||||
}
|
||||
|
||||
func TestSampleConvertDocx4(t *testing.T) {
|
||||
@@ -124,5 +124,5 @@ func TestSampleConvertDocx4(t *testing.T) {
|
||||
resIOE := convertDocx4(acquire)
|
||||
resE := resIOE()
|
||||
|
||||
assert.True(t, E.IsRight(resE))
|
||||
assert.True(t, R.IsRight(resE))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user