mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
fix: add support for context sensitive readers
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
24
readerioeither/array_test.go
Normal file
24
readerioeither/array_test.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
A "github.com/ibm/fp-go/array"
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTraverseArray(t *testing.T) {
|
||||
f := TraverseArray(func(a string) ReaderIOEither[context.Context, string, string] {
|
||||
if len(a) > 0 {
|
||||
return Right[context.Context, string](a + a)
|
||||
}
|
||||
return Left[context.Context, string, string]("e")
|
||||
})
|
||||
ctx := context.Background()
|
||||
assert.Equal(t, ET.Right[string](A.Empty[string]()), F.Pipe1(A.Empty[string](), f)(ctx)())
|
||||
assert.Equal(t, ET.Right[string]([]string{"aa", "bb"}), F.Pipe1([]string{"a", "b"}, f)(ctx)())
|
||||
assert.Equal(t, ET.Left[[]string]("e"), F.Pipe1([]string{"a", ""}, f)(ctx)())
|
||||
}
|
18
readerioeither/bracket.go
Normal file
18
readerioeither/bracket.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
G "github.com/ibm/fp-go/readerioeither/generic"
|
||||
)
|
||||
|
||||
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||
// whether the body action returns and error or not.
|
||||
func Bracket[
|
||||
R, E, A, B, ANY any](
|
||||
|
||||
acquire ReaderIOEither[R, E, A],
|
||||
use func(A) ReaderIOEither[R, E, B],
|
||||
release func(A, ET.Either[E, B]) ReaderIOEither[R, E, ANY],
|
||||
) ReaderIOEither[R, E, B] {
|
||||
return G.Bracket(acquire, use, release)
|
||||
}
|
17
readerioeither/eq.go
Normal file
17
readerioeither/eq.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
G "github.com/ibm/fp-go/readerioeither/generic"
|
||||
)
|
||||
|
||||
// Eq implements the equals predicate for values contained in the IOEither monad
|
||||
func Eq[R, E, A any](eq EQ.Eq[ET.Either[E, A]]) func(R) EQ.Eq[ReaderIOEither[R, E, A]] {
|
||||
return G.Eq[ReaderIOEither[R, E, A]](eq)
|
||||
}
|
||||
|
||||
// FromStrictEquals constructs an `Eq` from the canonical comparison function
|
||||
func FromStrictEquals[R, E, A comparable]() func(R) EQ.Eq[ReaderIOEither[R, E, A]] {
|
||||
return G.FromStrictEquals[ReaderIOEither[R, E, A]]()
|
||||
}
|
24
readerioeither/from.go
Normal file
24
readerioeither/from.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/readerioeither/generic"
|
||||
)
|
||||
|
||||
// these functions From a golang function with the context as the firsr parameter into a either reader with the context as the last parameter
|
||||
// this goes back to the advice in https://pkg.go.dev/context to put the context as a first parameter as a convention
|
||||
|
||||
func From0[R, A any](f func(R) func() (A, error)) ReaderIOEither[R, error, A] {
|
||||
return G.From0[ReaderIOEither[R, error, A]](f)
|
||||
}
|
||||
|
||||
func From1[R, T1, A any](f func(R, T1) func() (A, error)) func(T1) ReaderIOEither[R, error, A] {
|
||||
return G.From1[ReaderIOEither[R, error, A]](f)
|
||||
}
|
||||
|
||||
func From2[R, T1, T2, A any](f func(R, T1, T2) func() (A, error)) func(T1, T2) ReaderIOEither[R, error, A] {
|
||||
return G.From2[ReaderIOEither[R, error, A]](f)
|
||||
}
|
||||
|
||||
func From3[R, T1, T2, T3, A any](f func(R, T1, T2, T3) func() (A, error)) func(T1, T2, T3) ReaderIOEither[R, error, A] {
|
||||
return G.From3[ReaderIOEither[R, error, A]](f)
|
||||
}
|
36
readerioeither/generic/bracket.go
Normal file
36
readerioeither/generic/bracket.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
G "github.com/ibm/fp-go/internal/file"
|
||||
I "github.com/ibm/fp-go/readerio/generic"
|
||||
)
|
||||
|
||||
// Bracket makes sure that a resource is cleaned up in the event of an error. The release action is called regardless of
|
||||
// whether the body action returns and error or not.
|
||||
func Bracket[
|
||||
GA ~func(R) TA,
|
||||
GB ~func(R) TB,
|
||||
GANY ~func(R) TANY,
|
||||
|
||||
TA ~func() ET.Either[E, A],
|
||||
TB ~func() ET.Either[E, B],
|
||||
TANY ~func() ET.Either[E, ANY],
|
||||
|
||||
R, E, A, B, ANY any](
|
||||
|
||||
acquire GA,
|
||||
use func(A) GB,
|
||||
release func(A, ET.Either[E, B]) GANY,
|
||||
) GB {
|
||||
return G.Bracket[GA, GB, GANY, ET.Either[E, B], A, B](
|
||||
I.Of[GB, TB, R, ET.Either[E, B]],
|
||||
MonadChain[GA, GB, TA, TB, R, E, A, B],
|
||||
I.MonadChain[GB, GB, TB, TB, R, ET.Either[E, B], ET.Either[E, B]],
|
||||
MonadChain[GANY, GB, TANY, TB, R, E, ANY, B],
|
||||
|
||||
acquire,
|
||||
use,
|
||||
release,
|
||||
)
|
||||
}
|
48
readerioeither/generic/eitherize.go
Normal file
48
readerioeither/generic/eitherize.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
)
|
||||
|
||||
// these functions From a golang function with the context as the first parameter into a either reader with the context as the last parameter
|
||||
// this goes back to the advice in https://pkg.go.dev/context to put the context as a first parameter as a convention
|
||||
|
||||
func Eitherize0[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, A any](f func(R) (A, error)) GEA {
|
||||
return From0[GEA](func(r R) func() (A, error) {
|
||||
return func() (A, error) {
|
||||
return f(r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Eitherize1[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, T1, A any](f func(R, T1) (A, error)) func(T1) GEA {
|
||||
return From1[GEA](func(r R, t1 T1) func() (A, error) {
|
||||
return func() (A, error) {
|
||||
return f(r, t1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Eitherize2[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, T1, T2, A any](f func(R, T1, T2) (A, error)) func(T1, T2) GEA {
|
||||
return From2[GEA](func(r R, t1 T1, t2 T2) func() (A, error) {
|
||||
return func() (A, error) {
|
||||
return f(r, t1, t2)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Eitherize3[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, T1, T2, T3, A any](f func(R, T1, T2, T3) (A, error)) func(T1, T2, T3) GEA {
|
||||
return From3[GEA](func(r R, t1 T1, t2 T2, t3 T3) func() (A, error) {
|
||||
return func() (A, error) {
|
||||
return f(r, t1, t2, t3)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Eitherize4[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, T1, T2, T3, T4, A any](f func(R, T1, T2, T3, T4) (A, error)) func(T1, T2, T3, T4) GEA {
|
||||
return From4[GEA](func(r R, t1 T1, t2 T2, t3 T3, t4 T4) func() (A, error) {
|
||||
return func() (A, error) {
|
||||
return f(r, t1, t2, t3, t4)
|
||||
}
|
||||
})
|
||||
}
|
17
readerioeither/generic/eq.go
Normal file
17
readerioeither/generic/eq.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
EQ "github.com/ibm/fp-go/eq"
|
||||
G "github.com/ibm/fp-go/readerio/generic"
|
||||
)
|
||||
|
||||
// Eq implements the equals predicate for values contained in the IOEither monad
|
||||
func Eq[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](eq EQ.Eq[ET.Either[E, A]]) func(R) EQ.Eq[GEA] {
|
||||
return G.Eq[GEA](eq)
|
||||
}
|
||||
|
||||
// FromStrictEquals constructs an `Eq` from the canonical comparison function
|
||||
func FromStrictEquals[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R any, E, A comparable]() func(R) EQ.Eq[GEA] {
|
||||
return Eq[GEA](ET.FromStrictEquals[E, A]())
|
||||
}
|
39
readerioeither/generic/from.go
Normal file
39
readerioeither/generic/from.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
G "github.com/ibm/fp-go/reader/generic"
|
||||
)
|
||||
|
||||
// these functions From a golang function with the context as the first parameter into a either reader with the context as the last parameter
|
||||
// this goes back to the advice in https://pkg.go.dev/context to put the context as a first parameter as a convention
|
||||
|
||||
func From0[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, A any](f func(R) func() (A, error)) GEA {
|
||||
return G.From0[GEA](func(r R) GIOA {
|
||||
return ET.Eitherize0(f(r))
|
||||
})
|
||||
}
|
||||
|
||||
func From1[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, T1, A any](f func(R, T1) func() (A, error)) func(T1) GEA {
|
||||
return G.From1[GEA](func(r R, t1 T1) GIOA {
|
||||
return ET.Eitherize0(f(r, t1))
|
||||
})
|
||||
}
|
||||
|
||||
func From2[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, T1, T2, A any](f func(R, T1, T2) func() (A, error)) func(T1, T2) GEA {
|
||||
return G.From2[GEA](func(r R, t1 T1, t2 T2) GIOA {
|
||||
return ET.Eitherize0(f(r, t1, t2))
|
||||
})
|
||||
}
|
||||
|
||||
func From3[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, T1, T2, T3, A any](f func(R, T1, T2, T3) func() (A, error)) func(T1, T2, T3) GEA {
|
||||
return G.From3[GEA](func(r R, t1 T1, t2 T2, t3 T3) GIOA {
|
||||
return ET.Eitherize0(f(r, t1, t2, t3))
|
||||
})
|
||||
}
|
||||
|
||||
func From4[GEA ~func(R) GIOA, GIOA ~func() ET.Either[error, A], R, T1, T2, T3, T4, A any](f func(R, T1, T2, T3, T4) func() (A, error)) func(T1, T2, T3, T4) GEA {
|
||||
return G.From4[GEA](func(r R, t1 T1, t2 T2, t3 T3, t4 T4) GIOA {
|
||||
return ET.Eitherize0(f(r, t1, t2, t3, t4))
|
||||
})
|
||||
}
|
283
readerioeither/generic/reader.go
Normal file
283
readerioeither/generic/reader.go
Normal file
@@ -0,0 +1,283 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
"github.com/ibm/fp-go/internal/eithert"
|
||||
FE "github.com/ibm/fp-go/internal/fromeither"
|
||||
FIO "github.com/ibm/fp-go/internal/fromio"
|
||||
FIOE "github.com/ibm/fp-go/internal/fromioeither"
|
||||
FR "github.com/ibm/fp-go/internal/fromreader"
|
||||
GIO "github.com/ibm/fp-go/ioeither/generic"
|
||||
IOE "github.com/ibm/fp-go/ioeither/generic"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
RD "github.com/ibm/fp-go/reader/generic"
|
||||
G "github.com/ibm/fp-go/readerio/generic"
|
||||
)
|
||||
|
||||
// MakeReader constructs an instance of a reader
|
||||
func MakeReader[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](f func(R) GIOA) GEA {
|
||||
return f
|
||||
}
|
||||
|
||||
func MonadMap[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](fa GEA, f func(A) B) GEB {
|
||||
return eithert.MonadMap(G.MonadMap[GEA, GEB, GIOA, GIOB, R, ET.Either[E, A], ET.Either[E, B]], fa, f)
|
||||
}
|
||||
|
||||
func Map[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](f func(A) B) func(GEA) GEB {
|
||||
return F.Bind2nd(MonadMap[GEA, GEB, GIOA, GIOB, R, E, A, B], f)
|
||||
}
|
||||
|
||||
func MonadMapTo[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](fa GEA, b B) GEB {
|
||||
return MonadMap[GEA, GEB](fa, F.Constant1[A](b))
|
||||
}
|
||||
|
||||
func MapTo[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](b B) func(GEA) GEB {
|
||||
return Map[GEA, GEB](F.Constant1[A](b))
|
||||
}
|
||||
|
||||
func MonadChain[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](fa GEA, f func(A) GEB) GEB {
|
||||
return eithert.MonadChain(
|
||||
G.MonadChain[GEA, GEB, GIOA, GIOB, R, ET.Either[E, A], ET.Either[E, B]],
|
||||
G.Of[GEB, GIOB, R, ET.Either[E, B]],
|
||||
fa,
|
||||
f)
|
||||
}
|
||||
|
||||
func Chain[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](f func(A) GEB) func(fa GEA) GEB {
|
||||
return F.Bind2nd(MonadChain[GEA, GEB, GIOA, GIOB, R, E, A, B], f)
|
||||
}
|
||||
|
||||
func MonadChainEitherK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](ma GEA, f func(A) ET.Either[E, B]) GEB {
|
||||
return FE.MonadChainEitherK(
|
||||
MonadChain[GEA, GEB, GIOA, GIOB, R, E, A, B],
|
||||
FromEither[GEB, GIOB, R, E, B],
|
||||
ma,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func ChainEitherK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](f func(A) ET.Either[E, B]) func(ma GEA) GEB {
|
||||
return F.Bind2nd(MonadChainEitherK[GEA, GEB, GIOA, GIOB, R, E, A, B], f)
|
||||
}
|
||||
|
||||
func MonadChainReaderK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], GB ~func(R) B, R, E, A, B any](ma GEA, f func(A) GB) GEB {
|
||||
return FR.MonadChainReaderK(
|
||||
MonadChain[GEA, GEB, GIOA, GIOB, R, E, A, B],
|
||||
FromReader[GB, GEB, GIOB, R, E, B],
|
||||
ma,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func ChainReaderK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], GB ~func(R) B, R, E, A, B any](f func(A) GB) func(GEA) GEB {
|
||||
return FR.ChainReaderK(
|
||||
MonadChain[GEA, GEB, GIOA, GIOB, R, E, A, B],
|
||||
FromReader[GB, GEB, GIOB, R, E, B],
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func MonadChainIOEitherK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](ma GEA, f func(A) GIOB) GEB {
|
||||
return FIOE.MonadChainIOEitherK(
|
||||
MonadChain[GEA, GEB, GIOA, GIOB, R, E, A, B],
|
||||
FromIOEither[GEB, GIOB, R, E, B],
|
||||
ma,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func ChainIOEitherK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](f func(A) GIOB) func(GEA) GEB {
|
||||
return F.Bind2nd(MonadChainIOEitherK[GEA, GEB, GIOA, GIOB, R, E, A, B], f)
|
||||
}
|
||||
|
||||
func MonadChainIOK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], GIO ~func() B, R, E, A, B any](ma GEA, f func(A) GIO) GEB {
|
||||
return FIO.MonadChainIOK(
|
||||
MonadChain[GEA, GEB, GIOA, GIOB, R, E, A, B],
|
||||
FromIO[GEB, GIOB, GIO, R, E, B],
|
||||
ma,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
func ChainIOK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], GIO ~func() B, R, E, A, B any](f func(A) GIO) func(GEA) GEB {
|
||||
return F.Bind2nd(MonadChainIOK[GEA, GEB, GIOA, GIOB, GIO, R, E, A, B], f)
|
||||
}
|
||||
|
||||
func ChainOptionK[GEA ~func(R) GIOA, GEB ~func(R) GIOB, GIOA ~func() ET.Either[E, A], GIOB ~func() ET.Either[E, B], R, E, A, B any](onNone func() E) func(func(A) O.Option[B]) func(GEA) GEB {
|
||||
return FE.ChainOptionK(MonadChain[GEA, GEB, GIOA, GIOB, R, E, A, B], FromEither[GEB, GIOB, R, E, B], onNone)
|
||||
}
|
||||
|
||||
func MonadAp[
|
||||
GEA ~func(R) GIOA,
|
||||
GEB ~func(R) GIOB,
|
||||
GEFAB ~func(R) GIOFAB,
|
||||
GIOA ~func() ET.Either[E, A],
|
||||
GIOB ~func() ET.Either[E, B],
|
||||
GIOFAB ~func() ET.Either[E, func(A) B],
|
||||
R, E, A, B any](fab GEFAB, fa GEA) GEB {
|
||||
|
||||
return eithert.MonadAp(
|
||||
G.MonadAp[GEA, GEB, func(R) func() func(ET.Either[E, A]) ET.Either[E, B], GIOA, GIOB, func() func(ET.Either[E, A]) ET.Either[E, B], R, ET.Either[E, A], ET.Either[E, B]],
|
||||
G.MonadMap[GEFAB, func(R) func() func(ET.Either[E, A]) ET.Either[E, B], GIOFAB, func() func(ET.Either[E, A]) ET.Either[E, B], R, ET.Either[E, func(A) B], func(ET.Either[E, A]) ET.Either[E, B]],
|
||||
fab,
|
||||
fa,
|
||||
)
|
||||
}
|
||||
|
||||
func Ap[
|
||||
GEA ~func(R) GIOA,
|
||||
GEB ~func(R) GIOB,
|
||||
GEFAB ~func(R) GIOFAB,
|
||||
GIOA ~func() ET.Either[E, A],
|
||||
GIOB ~func() ET.Either[E, B],
|
||||
GIOFAB ~func() ET.Either[E, func(A) B],
|
||||
R, E, A, B any](fa GEA) func(fab GEFAB) GEB {
|
||||
return F.Bind2nd(MonadAp[GEA, GEB, GEFAB, GIOA, GIOB, GIOFAB, R, E, A, B], fa)
|
||||
}
|
||||
|
||||
func Right[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](a A) GEA {
|
||||
return eithert.Right(G.Of[GEA, GIOA, R, ET.Either[E, A]], a)
|
||||
}
|
||||
|
||||
func Left[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](e E) GEA {
|
||||
return eithert.Left(G.Of[GEA, GIOA, R, ET.Either[E, A]], e)
|
||||
}
|
||||
|
||||
func ThrowError[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](e E) GEA {
|
||||
return Left[GEA](e)
|
||||
}
|
||||
|
||||
// Of returns a Reader with a fixed value
|
||||
func Of[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](a A) GEA {
|
||||
return Right[GEA](a)
|
||||
}
|
||||
|
||||
func Flatten[GEA ~func(R) GIOA, GGEA ~func(R) GIOEA, GIOA ~func() ET.Either[E, A], GIOEA ~func() ET.Either[E, GEA], R, E, A any](mma GGEA) GEA {
|
||||
return MonadChain(mma, F.Identity[GEA])
|
||||
}
|
||||
|
||||
func FromIOEither[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](t GIOA) GEA {
|
||||
return RD.Of[GEA](t)
|
||||
}
|
||||
|
||||
func FromEither[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](t ET.Either[E, A]) GEA {
|
||||
return G.Of[GEA](t)
|
||||
}
|
||||
|
||||
func RightReader[GA ~func(R) A, GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](ma GA) GEA {
|
||||
return F.Flow2(ma, GIO.Right[GIOA, E, A])
|
||||
}
|
||||
|
||||
func LeftReader[GE ~func(R) E, GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](ma GE) GEA {
|
||||
return F.Flow2(ma, GIO.Left[GIOA, E, A])
|
||||
}
|
||||
|
||||
func FromReader[GA ~func(R) A, GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](ma GA) GEA {
|
||||
return RightReader[GA, GEA](ma)
|
||||
}
|
||||
|
||||
func MonadFromReaderIO[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], GRIO ~func(R) GIO, GIO ~func() A, R, E, A any](a A, f func(A) GRIO) GEA {
|
||||
return F.Pipe2(
|
||||
a,
|
||||
f,
|
||||
RightReaderIO[GEA, GIOA, GRIO, GIO, R, E, A],
|
||||
)
|
||||
}
|
||||
|
||||
func FromReaderIO[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], GRIO ~func(R) GIO, GIO ~func() A, R, E, A any](f func(A) GRIO) func(A) GEA {
|
||||
return F.Bind2nd(MonadFromReaderIO[GEA, GIOA, GRIO, GIO, R, E, A], f)
|
||||
}
|
||||
|
||||
func RightReaderIO[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], GRIO ~func(R) GIO, GIO ~func() A, R, E, A any](ma GRIO) GEA {
|
||||
return eithert.RightF(
|
||||
G.MonadMap[GRIO, GEA, GIO, GIOA, R, A, ET.Either[E, A]],
|
||||
ma,
|
||||
)
|
||||
}
|
||||
|
||||
func LeftReaderIO[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], GRIO ~func(R) GIO, GIO ~func() E, R, E, A any](me GRIO) GEA {
|
||||
return eithert.LeftF(
|
||||
G.MonadMap[GRIO, GEA, GIO, GIOA, R, E, ET.Either[E, A]],
|
||||
me,
|
||||
)
|
||||
}
|
||||
|
||||
func RightIO[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], GR ~func() A, R, E, A any](ma GR) GEA {
|
||||
return F.Pipe2(ma, GIO.RightIO[GIOA, GR, E, A], FromIOEither[GEA, GIOA, R, E, A])
|
||||
}
|
||||
|
||||
func LeftIO[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], GR ~func() E, R, E, A any](ma GR) GEA {
|
||||
return F.Pipe2(ma, GIO.LeftIO[GIOA, GR, E, A], FromIOEither[GEA, GIOA, R, E, A])
|
||||
}
|
||||
|
||||
func FromIO[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], GR ~func() A, R, E, A any](ma GR) GEA {
|
||||
return RightIO[GEA](ma)
|
||||
}
|
||||
|
||||
func FromReaderEither[GA ~func(R) ET.Either[E, A], GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](ma GA) GEA {
|
||||
return F.Flow2(ma, GIO.FromEither[GIOA, E, A])
|
||||
}
|
||||
|
||||
func Ask[GER ~func(R) GIOR, GIOR ~func() ET.Either[E, R], R, E any]() GER {
|
||||
return FR.Ask(FromReader[func(R) R, GER, GIOR, R, E, R])()
|
||||
}
|
||||
|
||||
func Asks[GA ~func(R) A, GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](r GA) GEA {
|
||||
return FR.Asks(FromReader[GA, GEA, GIOA, R, E, A])(r)
|
||||
}
|
||||
|
||||
func FromOption[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](onNone func() E) func(O.Option[A]) GEA {
|
||||
return FE.FromOption(FromEither[GEA, GIOA, R, E, A], onNone)
|
||||
}
|
||||
|
||||
func FromPredicate[GEA ~func(R) GIOA, GIOA ~func() ET.Either[E, A], R, E, A any](pred func(A) bool, onFalse func(A) E) func(A) GEA {
|
||||
return FE.FromPredicate(FromEither[GEA, GIOA, R, E, A], pred, onFalse)
|
||||
}
|
||||
|
||||
func Fold[GB ~func(R) GIOB, GEA ~func(R) GIOA, GIOB ~func() B, GIOA ~func() ET.Either[E, A], R, E, A, B any](onLeft func(E) GB, onRight func(A) GB) func(GEA) GB {
|
||||
return eithert.MatchE(G.MonadChain[GEA, GB, GIOA, GIOB, R, ET.Either[E, A], B], onLeft, onRight)
|
||||
}
|
||||
|
||||
func GetOrElse[GA ~func(R) GIOB, GEA ~func(R) GIOA, GIOB ~func() A, GIOA ~func() ET.Either[E, A], R, E, A any](onLeft func(E) GA) func(GEA) GA {
|
||||
return eithert.GetOrElse(G.MonadChain[GEA, GA, GIOA, GIOB, R, ET.Either[E, A], A], G.Of[GA, GIOB, R, A], onLeft)
|
||||
}
|
||||
|
||||
func OrElse[GEA1 ~func(R) GIOA1, GEA2 ~func(R) GIOA2, GIOA1 ~func() ET.Either[E1, A], GIOA2 ~func() ET.Either[E2, A], R, E1, A, E2 any](onLeft func(E1) GEA2) func(GEA1) GEA2 {
|
||||
return eithert.OrElse(G.MonadChain[GEA1, GEA2, GIOA1, GIOA2, R, ET.Either[E1, A], ET.Either[E2, A]], G.Of[GEA2, GIOA2, R, ET.Either[E2, A]], onLeft)
|
||||
}
|
||||
|
||||
func OrLeft[GEA1 ~func(R) GIOA1, GE2 ~func(R) GIOE2, GEA2 ~func(R) GIOA2, GIOA1 ~func() ET.Either[E1, A], GIOE2 ~func() E2, GIOA2 ~func() ET.Either[E2, A], E1, R, E2, A any](onLeft func(E1) GE2) func(GEA1) GEA2 {
|
||||
return eithert.OrLeft(
|
||||
G.MonadChain[GEA1, GEA2, GIOA1, GIOA2, R, ET.Either[E1, A], ET.Either[E2, A]],
|
||||
G.MonadMap[GE2, GEA2, GIOE2, GIOA2, R, E2, ET.Either[E2, A]],
|
||||
G.Of[GEA2, GIOA2, R, ET.Either[E2, A]],
|
||||
onLeft,
|
||||
)
|
||||
}
|
||||
|
||||
func MonadBiMap[GA ~func(R) GE1A, GB ~func(R) GE2B, GE1A ~func() ET.Either[E1, A], GE2B ~func() ET.Either[E2, B], R, E1, E2, A, B any](fa GA, f func(E1) E2, g func(A) B) GB {
|
||||
return eithert.MonadBiMap(G.MonadMap[GA, GB, GE1A, GE2B, R, ET.Either[E1, A], ET.Either[E2, B]], fa, f, g)
|
||||
}
|
||||
|
||||
// BiMap maps a pair of functions over the two type arguments of the bifunctor.
|
||||
func BiMap[GA ~func(R) GE1A, GB ~func(R) GE2B, GE1A ~func() ET.Either[E1, A], GE2B ~func() ET.Either[E2, B], R, E1, E2, A, B any](f func(E1) E2, g func(A) B) func(GA) GB {
|
||||
return eithert.BiMap(G.MonadMap[GA, GB, GE1A, GE2B, R, ET.Either[E1, A], ET.Either[E2, B]], f, g)
|
||||
}
|
||||
|
||||
// Swap changes the order of type parameters
|
||||
func Swap[GREA ~func(R) GEA, GRAE ~func(R) GAE, GEA ~func() ET.Either[E, A], GAE ~func() ET.Either[A, E], R, E, A any](val GREA) GRAE {
|
||||
return RD.MonadMap[GREA, GRAE, R, GEA, GAE](val, GIO.Swap[GEA, GAE])
|
||||
}
|
||||
|
||||
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
||||
func Defer[GEA ~func(R) GA, GA ~func() ET.Either[E, A], R, E, A any](gen func() GEA) GEA {
|
||||
return G.Defer[GEA](gen)
|
||||
}
|
||||
|
||||
// TryCatch wraps a reader returning a tuple as an error into ReaderIOEither
|
||||
func TryCatch[GEA ~func(R) GA, GA ~func() ET.Either[E, A], R, E, A any](f func(R) func() (A, error), onThrow func(error) E) GEA {
|
||||
return func(r R) GA {
|
||||
return IOE.TryCatch[GA](f(r), onThrow)
|
||||
}
|
||||
}
|
33
readerioeither/generic/resource.go
Normal file
33
readerioeither/generic/resource.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
IOE "github.com/ibm/fp-go/ioeither/generic"
|
||||
)
|
||||
|
||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
||||
func WithResource[
|
||||
GEA ~func(L) TEA,
|
||||
GER ~func(L) TER,
|
||||
GEANY ~func(L) TEANY,
|
||||
|
||||
TEA ~func() ET.Either[E, A],
|
||||
TER ~func() ET.Either[E, R],
|
||||
TEANY ~func() ET.Either[E, ANY],
|
||||
|
||||
L, E, R, A, ANY any](onCreate GER, onRelease func(R) GEANY) func(func(R) GEA) GEA {
|
||||
|
||||
return func(f func(R) GEA) GEA {
|
||||
return func(l L) TEA {
|
||||
// dispatch to the generic implementation
|
||||
return IOE.WithResource[TEA](
|
||||
onCreate(l),
|
||||
func(r R) TEANY {
|
||||
return onRelease(r)(l)
|
||||
},
|
||||
)(func(r R) TEA {
|
||||
return f(r)(l)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
79
readerioeither/generic/sequence.go
Normal file
79
readerioeither/generic/sequence.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
"github.com/ibm/fp-go/internal/apply"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
)
|
||||
|
||||
// SequenceT converts n inputs of higher kinded types into a higher kinded types of n strongly typed values, represented as a tuple
|
||||
|
||||
func SequenceT1[
|
||||
GA ~func(E) GIOA,
|
||||
GTA ~func(E) GIOTA,
|
||||
GIOA ~func() ET.Either[L, A],
|
||||
GIOTA ~func() ET.Either[L, T.Tuple1[A]],
|
||||
E, L, A any](a GA) GTA {
|
||||
return apply.SequenceT1(
|
||||
Map[GA, GTA, GIOA, GIOTA, E, L, A, T.Tuple1[A]],
|
||||
|
||||
a,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT2[
|
||||
GA ~func(E) GIOA,
|
||||
GB ~func(E) GIOB,
|
||||
GTAB ~func(E) GIOTAB,
|
||||
GIOA ~func() ET.Either[L, A],
|
||||
GIOB ~func() ET.Either[L, B],
|
||||
GIOTAB ~func() ET.Either[L, T.Tuple2[A, B]],
|
||||
E, L, A, B any](a GA, b GB) GTAB {
|
||||
return apply.SequenceT2(
|
||||
Map[GA, func(E) func() ET.Either[L, func(B) T.Tuple2[A, B]], GIOA, func() ET.Either[L, func(B) T.Tuple2[A, B]], E, L, A, func(B) T.Tuple2[A, B]],
|
||||
Ap[GB, GTAB, func(E) func() ET.Either[L, func(B) T.Tuple2[A, B]], GIOB, GIOTAB, func() ET.Either[L, func(B) T.Tuple2[A, B]], E, L, B, T.Tuple2[A, B]],
|
||||
|
||||
a, b,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT3[
|
||||
GA ~func(E) GIOA,
|
||||
GB ~func(E) GIOB,
|
||||
GC ~func(E) GIOC,
|
||||
GTABC ~func(E) GIOTABC,
|
||||
GIOA ~func() ET.Either[L, A],
|
||||
GIOB ~func() ET.Either[L, B],
|
||||
GIOC ~func() ET.Either[L, C],
|
||||
GIOTABC ~func() ET.Either[L, T.Tuple3[A, B, C]],
|
||||
E, L, A, B, C any](a GA, b GB, c GC) GTABC {
|
||||
return apply.SequenceT3(
|
||||
Map[GA, func(E) func() ET.Either[L, func(B) func(C) T.Tuple3[A, B, C]], GIOA, func() ET.Either[L, func(B) func(C) T.Tuple3[A, B, C]], E, L, A, func(B) func(C) T.Tuple3[A, B, C]],
|
||||
Ap[GB, func(E) func() ET.Either[L, func(C) T.Tuple3[A, B, C]], func(E) func() ET.Either[L, func(B) func(C) T.Tuple3[A, B, C]], GIOB, func() ET.Either[L, func(C) T.Tuple3[A, B, C]], func() ET.Either[L, func(B) func(C) T.Tuple3[A, B, C]], E, L, B, func(C) T.Tuple3[A, B, C]],
|
||||
Ap[GC, GTABC, func(E) func() ET.Either[L, func(C) T.Tuple3[A, B, C]], GIOC, GIOTABC, func() ET.Either[L, func(C) T.Tuple3[A, B, C]], E, L, C, T.Tuple3[A, B, C]],
|
||||
|
||||
a, b, c,
|
||||
)
|
||||
}
|
||||
|
||||
func SequenceT4[
|
||||
GA ~func(E) GIOA,
|
||||
GB ~func(E) GIOB,
|
||||
GC ~func(E) GIOC,
|
||||
GD ~func(E) GIOD,
|
||||
GTABCD ~func(E) GIOTABCD,
|
||||
GIOA ~func() ET.Either[L, A],
|
||||
GIOB ~func() ET.Either[L, B],
|
||||
GIOC ~func() ET.Either[L, C],
|
||||
GIOD ~func() ET.Either[L, D],
|
||||
GIOTABCD ~func() ET.Either[L, T.Tuple4[A, B, C, D]],
|
||||
E, L, A, B, C, D any](a GA, b GB, c GC, d GD) GTABCD {
|
||||
return apply.SequenceT4(
|
||||
Map[GA, func(E) func() ET.Either[L, func(B) func(C) func(D) T.Tuple4[A, B, C, D]], GIOA, func() ET.Either[L, func(B) func(C) func(D) T.Tuple4[A, B, C, D]], E, L, A, func(B) func(C) func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GB, func(E) func() ET.Either[L, func(C) func(D) T.Tuple4[A, B, C, D]], func(E) func() ET.Either[L, func(B) func(C) func(D) T.Tuple4[A, B, C, D]], GIOB, func() ET.Either[L, func(C) func(D) T.Tuple4[A, B, C, D]], func() ET.Either[L, func(B) func(C) func(D) T.Tuple4[A, B, C, D]], E, L, B, func(C) func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GC, func(E) func() ET.Either[L, func(D) T.Tuple4[A, B, C, D]], func(E) func() ET.Either[L, func(C) func(D) T.Tuple4[A, B, C, D]], GIOC, func() ET.Either[L, func(D) T.Tuple4[A, B, C, D]], func() ET.Either[L, func(C) func(D) T.Tuple4[A, B, C, D]], E, L, C, func(D) T.Tuple4[A, B, C, D]],
|
||||
Ap[GD, GTABCD, func(E) func() ET.Either[L, func(D) T.Tuple4[A, B, C, D]], GIOD, GIOTABCD, func() ET.Either[L, func(D) T.Tuple4[A, B, C, D]], E, L, D, T.Tuple4[A, B, C, D]],
|
||||
|
||||
a, b, c, d,
|
||||
)
|
||||
}
|
63
readerioeither/generic/traverse.go
Normal file
63
readerioeither/generic/traverse.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package generic
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
RA "github.com/ibm/fp-go/internal/array"
|
||||
RR "github.com/ibm/fp-go/internal/record"
|
||||
)
|
||||
|
||||
// MonadTraverseArray transforms an array
|
||||
func MonadTraverseArray[GB ~func(E) GIOB, GBS ~func(E) GIOBS, GIOB ~func() ET.Either[L, B], GIOBS ~func() ET.Either[L, BBS], AAS ~[]A, BBS ~[]B, E, L, A, B any](ma AAS, f func(A) GB) GBS {
|
||||
return RA.MonadTraverse[AAS](
|
||||
Of[GBS, GIOBS, E, L, BBS],
|
||||
Map[GBS, func(E) func() ET.Either[L, func(B) BBS], GIOBS, func() ET.Either[L, func(B) BBS], E, L, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func(E) func() ET.Either[L, func(B) BBS], GIOB, GIOBS, func() ET.Either[L, func(B) BBS], E, L, B, BBS],
|
||||
|
||||
ma, f,
|
||||
)
|
||||
}
|
||||
|
||||
// TraverseArray transforms an array
|
||||
func TraverseArray[GB ~func(E) GIOB, GBS ~func(E) GIOBS, GIOB ~func() ET.Either[L, B], GIOBS ~func() ET.Either[L, BBS], AAS ~[]A, BBS ~[]B, E, L, A, B any](f func(A) GB) func(AAS) GBS {
|
||||
return RA.Traverse[AAS](
|
||||
Of[GBS, GIOBS, E, L, BBS],
|
||||
Map[GBS, func(E) func() ET.Either[L, func(B) BBS], GIOBS, func() ET.Either[L, func(B) BBS], E, L, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func(E) func() ET.Either[L, func(B) BBS], GIOB, GIOBS, func() ET.Either[L, func(B) BBS], E, L, B, BBS],
|
||||
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// SequenceArray converts a homogeneous sequence of either into an either of sequence
|
||||
func SequenceArray[GA ~func(E) GIOA, GAS ~func(E) GIOAS, GIOA ~func() ET.Either[L, A], GIOAS ~func() ET.Either[L, AAS], AAS ~[]A, GAAS ~[]GA, E, L, A any](ma GAAS) GAS {
|
||||
return MonadTraverseArray[GA, GAS](ma, F.Identity[GA])
|
||||
}
|
||||
|
||||
// MonadTraverseRecord transforms an array
|
||||
func MonadTraverseRecord[GB ~func(C) GIOB, GBS ~func(C) GIOBS, GIOB ~func() ET.Either[E, B], GIOBS ~func() ET.Either[E, BBS], AAS ~map[K]A, BBS ~map[K]B, K comparable, C, E, A, B any](tas AAS, f func(A) GB) GBS {
|
||||
return RR.MonadTraverse[AAS](
|
||||
Of[GBS, GIOBS, C, E, BBS],
|
||||
Map[GBS, func(C) func() ET.Either[E, func(B) BBS], GIOBS, func() ET.Either[E, func(B) BBS], C, E, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func(C) func() ET.Either[E, func(B) BBS], GIOB, GIOBS, func() ET.Either[E, func(B) BBS], C, E, B, BBS],
|
||||
|
||||
tas,
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// TraverseRecord transforms an array
|
||||
func TraverseRecord[GB ~func(C) GIOB, GBS ~func(C) GIOBS, GIOB ~func() ET.Either[E, B], GIOBS ~func() ET.Either[E, BBS], AAS ~map[K]A, BBS ~map[K]B, K comparable, C, E, A, B any](f func(A) GB) func(AAS) GBS {
|
||||
return RR.Traverse[AAS](
|
||||
Of[GBS, GIOBS, C, E, BBS],
|
||||
Map[GBS, func(C) func() ET.Either[E, func(B) BBS], GIOBS, func() ET.Either[E, func(B) BBS], C, E, BBS, func(B) BBS],
|
||||
Ap[GB, GBS, func(C) func() ET.Either[E, func(B) BBS], GIOB, GIOBS, func() ET.Either[E, func(B) BBS], C, E, B, BBS],
|
||||
|
||||
f,
|
||||
)
|
||||
}
|
||||
|
||||
// SequenceRecord converts a homogeneous sequence of either into an either of sequence
|
||||
func SequenceRecord[GA ~func(C) GIOA, GAS ~func(C) GIOAS, GIOA ~func() ET.Either[E, A], GIOAS ~func() ET.Either[E, AAS], AAS ~map[K]A, GAAS ~map[K]GA, K comparable, C, E, A any](tas GAAS) GAS {
|
||||
return MonadTraverseRecord[GA, GAS](tas, F.Identity[GA])
|
||||
}
|
216
readerioeither/reader.go
Normal file
216
readerioeither/reader.go
Normal file
@@ -0,0 +1,216 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
"github.com/ibm/fp-go/io"
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
O "github.com/ibm/fp-go/option"
|
||||
RD "github.com/ibm/fp-go/reader"
|
||||
RE "github.com/ibm/fp-go/readereither"
|
||||
RIO "github.com/ibm/fp-go/readerio"
|
||||
G "github.com/ibm/fp-go/readerioeither/generic"
|
||||
)
|
||||
|
||||
type ReaderIOEither[R, E, A any] RD.Reader[R, IOE.IOEither[E, A]]
|
||||
|
||||
// MakeReader constructs an instance of a reader
|
||||
func MakeReader[R, E, A any](f func(R) IOE.IOEither[E, A]) ReaderIOEither[R, E, A] {
|
||||
return G.MakeReader[ReaderIOEither[R, E, A]](f)
|
||||
}
|
||||
|
||||
func MonadFromReaderIO[R, E, A any](a A, f func(A) RIO.ReaderIO[R, A]) ReaderIOEither[R, E, A] {
|
||||
return G.MonadFromReaderIO[ReaderIOEither[R, E, A]](a, f)
|
||||
}
|
||||
|
||||
func FromReaderIO[R, E, A any](f func(A) RIO.ReaderIO[R, A]) func(A) ReaderIOEither[R, E, A] {
|
||||
return G.FromReaderIO[ReaderIOEither[R, E, A]](f)
|
||||
}
|
||||
|
||||
func RightReaderIO[R, E, A any](ma RIO.ReaderIO[R, A]) ReaderIOEither[R, E, A] {
|
||||
return G.RightReaderIO[ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func LeftReaderIO[R, E, A any](me RIO.ReaderIO[R, E]) ReaderIOEither[R, E, A] {
|
||||
return G.LeftReaderIO[ReaderIOEither[R, E, A]](me)
|
||||
}
|
||||
|
||||
func MonadMap[R, E, A, B any](fa ReaderIOEither[R, E, A], f func(A) B) ReaderIOEither[R, E, B] {
|
||||
return G.MonadMap[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](fa, f)
|
||||
}
|
||||
|
||||
func Map[R, E, A, B any](f func(A) B) func(fa ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.Map[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](f)
|
||||
}
|
||||
|
||||
func MonadMapTo[R, E, A, B any](fa ReaderIOEither[R, E, A], b B) ReaderIOEither[R, E, B] {
|
||||
return G.MonadMapTo[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](fa, b)
|
||||
}
|
||||
|
||||
func MapTo[R, E, A, B any](b B) func(ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.MapTo[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](b)
|
||||
}
|
||||
|
||||
func MonadChain[R, E, A, B any](fa ReaderIOEither[R, E, A], f func(A) ReaderIOEither[R, E, B]) ReaderIOEither[R, E, B] {
|
||||
return G.MonadChain(fa, f)
|
||||
}
|
||||
|
||||
func MonadChainEitherK[R, E, A, B any](ma ReaderIOEither[R, E, A], f func(A) ET.Either[E, B]) ReaderIOEither[R, E, B] {
|
||||
return G.MonadChainEitherK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](ma, f)
|
||||
}
|
||||
|
||||
func ChainEitherK[R, E, A, B any](f func(A) ET.Either[E, B]) func(ma ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.ChainEitherK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](f)
|
||||
}
|
||||
|
||||
func MonadChainReaderK[R, E, A, B any](ma ReaderIOEither[R, E, A], f func(A) RD.Reader[R, B]) ReaderIOEither[R, E, B] {
|
||||
return G.MonadChainReaderK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](ma, f)
|
||||
}
|
||||
|
||||
func ChainReaderK[R, E, A, B any](f func(A) RD.Reader[R, B]) func(ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.ChainReaderK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](f)
|
||||
}
|
||||
|
||||
func MonadChainIOEitherK[R, E, A, B any](ma ReaderIOEither[R, E, A], f func(A) IOE.IOEither[E, B]) ReaderIOEither[R, E, B] {
|
||||
return G.MonadChainIOEitherK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](ma, f)
|
||||
}
|
||||
|
||||
func ChainIOEitherK[R, E, A, B any](f func(A) IOE.IOEither[E, B]) func(ma ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.ChainIOEitherK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](f)
|
||||
}
|
||||
|
||||
func MonadChainIOK[R, E, A, B any](ma ReaderIOEither[R, E, A], f func(A) io.IO[B]) ReaderIOEither[R, E, B] {
|
||||
return G.MonadChainIOK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](ma, f)
|
||||
}
|
||||
|
||||
func ChainIOK[R, E, A, B any](f func(A) io.IO[B]) func(ma ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.ChainIOK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](f)
|
||||
}
|
||||
|
||||
func ChainOptionK[R, E, A, B any](onNone func() E) func(func(A) O.Option[B]) func(ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.ChainOptionK[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](onNone)
|
||||
}
|
||||
|
||||
func MonadAp[R, E, A, B any](fab ReaderIOEither[R, E, func(A) B], fa ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.MonadAp[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B]](fab, fa)
|
||||
}
|
||||
|
||||
func Ap[R, E, A, B any](fa ReaderIOEither[R, E, A]) func(fab ReaderIOEither[R, E, func(A) B]) ReaderIOEither[R, E, B] {
|
||||
return G.Ap[ReaderIOEither[R, E, A], ReaderIOEither[R, E, B], ReaderIOEither[R, E, func(A) B]](fa)
|
||||
}
|
||||
|
||||
func Chain[R, E, A, B any](f func(A) ReaderIOEither[R, E, B]) func(fa ReaderIOEither[R, E, A]) ReaderIOEither[R, E, B] {
|
||||
return G.Chain[ReaderIOEither[R, E, A]](f)
|
||||
}
|
||||
|
||||
func Right[R, E, A any](a A) ReaderIOEither[R, E, A] {
|
||||
return G.Right[ReaderIOEither[R, E, A]](a)
|
||||
}
|
||||
|
||||
func Left[R, E, A any](e E) ReaderIOEither[R, E, A] {
|
||||
return G.Left[ReaderIOEither[R, E, A]](e)
|
||||
}
|
||||
|
||||
func ThrowError[R, E, A any](e E) ReaderIOEither[R, E, A] {
|
||||
return G.ThrowError[ReaderIOEither[R, E, A]](e)
|
||||
}
|
||||
|
||||
// Of returns a Reader with a fixed value
|
||||
func Of[R, E, A any](a A) ReaderIOEither[R, E, A] {
|
||||
return G.Of[ReaderIOEither[R, E, A]](a)
|
||||
}
|
||||
|
||||
func Flatten[R, E, A any](mma ReaderIOEither[R, E, ReaderIOEither[R, E, A]]) ReaderIOEither[R, E, A] {
|
||||
return G.Flatten(mma)
|
||||
}
|
||||
|
||||
func FromEither[R, E, A any](t ET.Either[E, A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromEither[ReaderIOEither[R, E, A]](t)
|
||||
}
|
||||
|
||||
func RightReader[R, E, A any](ma RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
return G.RightReader[RD.Reader[R, A], ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func LeftReader[R, E, A any](ma RD.Reader[R, E]) ReaderIOEither[R, E, A] {
|
||||
return G.LeftReader[RD.Reader[R, E], ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func FromReader[R, E, A any](ma RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromReader[RD.Reader[R, A], ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func RightIO[R, E, A any](ma io.IO[A]) ReaderIOEither[R, E, A] {
|
||||
return G.RightIO[ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func LeftIO[R, E, A any](ma io.IO[E]) ReaderIOEither[R, E, A] {
|
||||
return G.LeftIO[ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func FromIO[R, E, A any](ma io.IO[A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromIO[ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func FromIOEither[R, E, A any](ma IOE.IOEither[E, A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromIOEither[ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func FromReaderEither[R, E, A any](ma RE.ReaderEither[R, E, A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromReaderEither[RE.ReaderEither[R, E, A], ReaderIOEither[R, E, A]](ma)
|
||||
}
|
||||
|
||||
func Ask[R, E any]() ReaderIOEither[R, E, R] {
|
||||
return G.Ask[ReaderIOEither[R, E, R]]()
|
||||
}
|
||||
|
||||
func Asks[R, E, A any](r RD.Reader[R, A]) ReaderIOEither[R, E, A] {
|
||||
return G.Asks[RD.Reader[R, A], ReaderIOEither[R, E, A]](r)
|
||||
}
|
||||
|
||||
func FromOption[R, E, A any](onNone func() E) func(O.Option[A]) ReaderIOEither[R, E, A] {
|
||||
return G.FromOption[ReaderIOEither[R, E, A]](onNone)
|
||||
}
|
||||
|
||||
func FromPredicate[R, E, A any](pred func(A) bool, onFalse func(A) E) func(A) ReaderIOEither[R, E, A] {
|
||||
return G.FromPredicate[ReaderIOEither[R, E, A]](pred, onFalse)
|
||||
}
|
||||
|
||||
func Fold[R, E, A, B any](onLeft func(E) RIO.ReaderIO[R, B], onRight func(A) RIO.ReaderIO[R, B]) func(ReaderIOEither[R, E, A]) RIO.ReaderIO[R, B] {
|
||||
return G.Fold[RIO.ReaderIO[R, B], ReaderIOEither[R, E, A]](onLeft, onRight)
|
||||
}
|
||||
|
||||
func GetOrElse[R, E, A any](onLeft func(E) RIO.ReaderIO[R, A]) func(ReaderIOEither[R, E, A]) RIO.ReaderIO[R, A] {
|
||||
return G.GetOrElse[RIO.ReaderIO[R, A], ReaderIOEither[R, E, A]](onLeft)
|
||||
}
|
||||
|
||||
func OrElse[R, E1, A, E2 any](onLeft func(E1) ReaderIOEither[R, E2, A]) func(ReaderIOEither[R, E1, A]) ReaderIOEither[R, E2, A] {
|
||||
return G.OrElse[ReaderIOEither[R, E1, A]](onLeft)
|
||||
}
|
||||
|
||||
func OrLeft[E1, R, E2, A any](onLeft func(E1) RIO.ReaderIO[R, E2]) func(ReaderIOEither[R, E1, A]) ReaderIOEither[R, E2, A] {
|
||||
return G.OrLeft[ReaderIOEither[R, E1, A], RIO.ReaderIO[R, E2], ReaderIOEither[R, E2, A]](onLeft)
|
||||
}
|
||||
|
||||
func MonadBiMap[R, E1, E2, A, B any](fa ReaderIOEither[R, E1, A], f func(E1) E2, g func(A) B) ReaderIOEither[R, E2, B] {
|
||||
return G.MonadBiMap[ReaderIOEither[R, E1, A], ReaderIOEither[R, E2, B]](fa, f, g)
|
||||
}
|
||||
|
||||
// BiMap maps a pair of functions over the two type arguments of the bifunctor.
|
||||
func BiMap[R, E1, E2, A, B any](f func(E1) E2, g func(A) B) func(ReaderIOEither[R, E1, A]) ReaderIOEither[R, E2, B] {
|
||||
return G.BiMap[ReaderIOEither[R, E1, A], ReaderIOEither[R, E2, B]](f, g)
|
||||
}
|
||||
|
||||
// Swap changes the order of type parameters
|
||||
func Swap[R, E, A any](val ReaderIOEither[R, E, A]) ReaderIOEither[R, A, E] {
|
||||
return G.Swap[ReaderIOEither[R, E, A], ReaderIOEither[R, A, E]](val)
|
||||
}
|
||||
|
||||
// Defer creates an IO by creating a brand new IO via a generator function, each time
|
||||
func Defer[R, E, A any](gen func() ReaderIOEither[R, E, A]) ReaderIOEither[R, E, A] {
|
||||
return G.Defer[ReaderIOEither[R, E, A]](gen)
|
||||
}
|
||||
|
||||
// TryCatch wraps a reader returning a tuple as an error into ReaderIOEither
|
||||
func TryCatch[R, E, A any](f func(R) func() (A, error), onThrow func(error) E) ReaderIOEither[R, E, A] {
|
||||
return G.TryCatch[ReaderIOEither[R, E, A]](f, onThrow)
|
||||
}
|
64
readerioeither/reader_test.go
Normal file
64
readerioeither/reader_test.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
E "github.com/ibm/fp-go/either"
|
||||
F "github.com/ibm/fp-go/function"
|
||||
"github.com/ibm/fp-go/internal/utils"
|
||||
R "github.com/ibm/fp-go/reader"
|
||||
RIO "github.com/ibm/fp-go/readerio"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
|
||||
g := F.Pipe1(
|
||||
Of[context.Context, error](1),
|
||||
Map[context.Context, error](utils.Double),
|
||||
)
|
||||
|
||||
assert.Equal(t, E.Of[error](2), g(context.Background())())
|
||||
}
|
||||
|
||||
func TestOrLeft(t *testing.T) {
|
||||
f := OrLeft[string, context.Context, string, int](func(s string) RIO.ReaderIO[context.Context, string] {
|
||||
return RIO.Of[context.Context](s + "!")
|
||||
})
|
||||
|
||||
g1 := F.Pipe1(
|
||||
Right[context.Context, string](1),
|
||||
f,
|
||||
)
|
||||
|
||||
g2 := F.Pipe1(
|
||||
Left[context.Context, string, int]("a"),
|
||||
f,
|
||||
)
|
||||
|
||||
assert.Equal(t, E.Of[string](1), g1(context.Background())())
|
||||
assert.Equal(t, E.Left[int]("a!"), g2(context.Background())())
|
||||
}
|
||||
|
||||
func TestAp(t *testing.T) {
|
||||
g := F.Pipe1(
|
||||
Right[context.Context, error](utils.Double),
|
||||
Ap[context.Context, error, int, int](Right[context.Context, error](1)),
|
||||
)
|
||||
|
||||
assert.Equal(t, E.Right[error](2), g(context.Background())())
|
||||
}
|
||||
|
||||
func TestChainReaderK(t *testing.T) {
|
||||
|
||||
g := F.Pipe1(
|
||||
Of[context.Context, error](1),
|
||||
ChainReaderK[context.Context, error](func(v int) R.Reader[context.Context, string] {
|
||||
return R.Of[context.Context](fmt.Sprintf("%d", v))
|
||||
}),
|
||||
)
|
||||
|
||||
assert.Equal(t, E.Right[error]("1"), g(context.Background())())
|
||||
}
|
10
readerioeither/resource.go
Normal file
10
readerioeither/resource.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/readerioeither/generic"
|
||||
)
|
||||
|
||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
||||
func WithResource[L, E, R, A any](onCreate ReaderIOEither[L, E, R], onRelease func(R) ReaderIOEither[L, E, any]) func(func(R) ReaderIOEither[L, E, A]) ReaderIOEither[L, E, A] {
|
||||
return G.WithResource[ReaderIOEither[L, E, A]](onCreate, onRelease)
|
||||
}
|
42
readerioeither/sequence.go
Normal file
42
readerioeither/sequence.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
G "github.com/ibm/fp-go/readerioeither/generic"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
)
|
||||
|
||||
// SequenceT converts n inputs of higher kinded types into a higher kinded types of n strongly typed values, represented as a tuple
|
||||
|
||||
func SequenceT1[R, E, A any](a ReaderIOEither[R, E, A]) ReaderIOEither[R, E, T.Tuple1[A]] {
|
||||
return G.SequenceT1[
|
||||
ReaderIOEither[R, E, A],
|
||||
ReaderIOEither[R, E, T.Tuple1[A]],
|
||||
](a)
|
||||
}
|
||||
|
||||
func SequenceT2[R, E, A, B any](a ReaderIOEither[R, E, A], b ReaderIOEither[R, E, B]) ReaderIOEither[R, E, T.Tuple2[A, B]] {
|
||||
return G.SequenceT2[
|
||||
ReaderIOEither[R, E, A],
|
||||
ReaderIOEither[R, E, B],
|
||||
ReaderIOEither[R, E, T.Tuple2[A, B]],
|
||||
](a, b)
|
||||
}
|
||||
|
||||
func SequenceT3[R, E, A, B, C any](a ReaderIOEither[R, E, A], b ReaderIOEither[R, E, B], c ReaderIOEither[R, E, C]) ReaderIOEither[R, E, T.Tuple3[A, B, C]] {
|
||||
return G.SequenceT3[
|
||||
ReaderIOEither[R, E, A],
|
||||
ReaderIOEither[R, E, B],
|
||||
ReaderIOEither[R, E, C],
|
||||
ReaderIOEither[R, E, T.Tuple3[A, B, C]],
|
||||
](a, b, c)
|
||||
}
|
||||
|
||||
func SequenceT4[R, E, A, B, C, D any](a ReaderIOEither[R, E, A], b ReaderIOEither[R, E, B], c ReaderIOEither[R, E, C], d ReaderIOEither[R, E, D]) ReaderIOEither[R, E, T.Tuple4[A, B, C, D]] {
|
||||
return G.SequenceT4[
|
||||
ReaderIOEither[R, E, A],
|
||||
ReaderIOEither[R, E, B],
|
||||
ReaderIOEither[R, E, C],
|
||||
ReaderIOEither[R, E, D],
|
||||
ReaderIOEither[R, E, T.Tuple4[A, B, C, D]],
|
||||
](a, b, c, d)
|
||||
}
|
23
readerioeither/sequence_test.go
Normal file
23
readerioeither/sequence_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
ET "github.com/ibm/fp-go/either"
|
||||
T "github.com/ibm/fp-go/tuple"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSequence2(t *testing.T) {
|
||||
// two readers of heterogeneous types
|
||||
first := Of[context.Context, error]("a")
|
||||
second := Of[context.Context, error](1)
|
||||
|
||||
// compose
|
||||
s2 := SequenceT2[context.Context, error, string, int]
|
||||
res := s2(first, second)
|
||||
|
||||
ctx := context.Background()
|
||||
assert.Equal(t, ET.Right[error](T.MakeTuple2("a", 1)), res(ctx)())
|
||||
}
|
26
readerioeither/traverse.go
Normal file
26
readerioeither/traverse.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package readerioeither
|
||||
|
||||
import (
|
||||
IOE "github.com/ibm/fp-go/ioeither"
|
||||
G "github.com/ibm/fp-go/readerioeither/generic"
|
||||
)
|
||||
|
||||
// TraverseArray transforms an array
|
||||
func TraverseArray[R, E, A, B any](f func(A) ReaderIOEither[R, E, B]) func([]A) ReaderIOEither[R, E, []B] {
|
||||
return G.TraverseArray[ReaderIOEither[R, E, B], ReaderIOEither[R, E, []B], IOE.IOEither[E, B], IOE.IOEither[E, []B], []A](f)
|
||||
}
|
||||
|
||||
// SequenceArray converts a homogeneous sequence of Readers into a Reader of a sequence
|
||||
func SequenceArray[R, E, A any](ma []ReaderIOEither[R, E, A]) ReaderIOEither[R, E, []A] {
|
||||
return G.SequenceArray[ReaderIOEither[R, E, A], ReaderIOEither[R, E, []A]](ma)
|
||||
}
|
||||
|
||||
// TraverseRecord transforms an array
|
||||
func TraverseRecord[R any, K comparable, E, A, B any](f func(A) ReaderIOEither[R, E, B]) func(map[K]A) ReaderIOEither[R, E, map[K]B] {
|
||||
return G.TraverseRecord[ReaderIOEither[R, E, B], ReaderIOEither[R, E, map[K]B], IOE.IOEither[E, B], IOE.IOEither[E, map[K]B], map[K]A](f)
|
||||
}
|
||||
|
||||
// SequenceRecord converts a homogeneous sequence of Readers into a Reader of a sequence
|
||||
func SequenceRecord[R any, K comparable, E, A any](ma map[K]ReaderIOEither[R, E, A]) ReaderIOEither[R, E, map[K]A] {
|
||||
return G.SequenceRecord[ReaderIOEither[R, E, A], ReaderIOEither[R, E, map[K]A]](ma)
|
||||
}
|
Reference in New Issue
Block a user