1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-08-10 22:31:32 +02:00

fix: migrate ioeither

Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
Dr. Carsten Leue
2025-03-03 11:44:51 +01:00
parent c641a1ae7c
commit 24a7cae6e9
29 changed files with 482 additions and 503 deletions

View File

@@ -25,7 +25,7 @@ const (
useParallel = true
)
//go:deprecate MonadApSeq implements the applicative on a single thread by first executing mab and the ma
// Deprecated: MonadApSeq implements the applicative on a single thread by first executing mab and the ma
func MonadApSeq[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
return MonadChain(mab, F.Bind1st(MonadMap[GA, GB], ma))
}
@@ -33,7 +33,7 @@ func MonadApSeq[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab
// MonadApPar implements the applicative on two threads, the main thread executes mab and the actuall
// apply operation and the second thread computes ma. Communication between the threads happens via a channel
//
//go:deprecate
// Deprecated:
func MonadApPar[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
return MakeIO[GB](func() B {
c := make(chan A)
@@ -48,7 +48,7 @@ func MonadApPar[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab
// MonadAp implements the `ap` operation. Depending on a feature flag this will be sequential or parallel, the preferred implementation
// is parallel
//
//go:deprecate
// Deprecated:
func MonadAp[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GAB, ma GA) GB {
if useParallel {
return MonadApPar[GA, GB](mab, ma)
@@ -58,7 +58,7 @@ func MonadAp[GA ~func() A, GB ~func() B, GAB ~func() func(A) B, A, B any](mab GA
// MonadApFirst combines two effectful actions, keeping only the result of the first.
//
//go:deprecate
// Deprecated:
func MonadApFirst[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](first GA, second GB) GA {
return G.MonadApFirst(
MonadAp[GB, GA, GBA, B, A],
@@ -71,7 +71,7 @@ func MonadApFirst[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](f
// MonadApFirstPar combines two effectful actions, keeping only the result of the first.
//
//go:deprecate
// Deprecated:
func MonadApFirstPar[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](first GA, second GB) GA {
return G.MonadApFirst(
MonadApPar[GB, GA, GBA, B, A],
@@ -84,7 +84,7 @@ func MonadApFirstPar[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any
// MonadApFirstSeq combines two effectful actions, keeping only the result of the first.
//
//go:deprecate
// Deprecated:
func MonadApFirstSeq[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](first GA, second GB) GA {
return G.MonadApFirst(
MonadApSeq[GB, GA, GBA, B, A],
@@ -97,7 +97,7 @@ func MonadApFirstSeq[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any
// ApFirst combines two effectful actions, keeping only the result of the first.
//
//go:deprecate
// Deprecated:
func ApFirst[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](second GB) func(GA) GA {
return G.ApFirst(
MonadAp[GB, GA, GBA, B, A],
@@ -109,7 +109,7 @@ func ApFirst[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](second
// ApFirstPar combines two effectful actions, keeping only the result of the first.
//
//go:deprecate
// Deprecated:
func ApFirstPar[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](second GB) func(GA) GA {
return G.ApFirst(
MonadApPar[GB, GA, GBA, B, A],
@@ -121,7 +121,7 @@ func ApFirstPar[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](sec
// ApFirstSeq combines two effectful actions, keeping only the result of the first.
//
//go:deprecate
// Deprecated:
func ApFirstSeq[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](second GB) func(GA) GA {
return G.ApFirst(
MonadApSeq[GB, GA, GBA, B, A],
@@ -133,7 +133,7 @@ func ApFirstSeq[GA ~func() A, GB ~func() B, GBA ~func() func(B) A, A, B any](sec
// MonadApSecond combines two effectful actions, keeping only the result of the second.
//
//go:deprecate
// Deprecated:
func MonadApSecond[GA ~func() A, GB ~func() B, GBB ~func() func(B) B, A, B any](first GA, second GB) GB {
return G.MonadApSecond(
MonadAp[GB, GB, GBB, B, B],
@@ -146,7 +146,7 @@ func MonadApSecond[GA ~func() A, GB ~func() B, GBB ~func() func(B) B, A, B any](
// ApSecond combines two effectful actions, keeping only the result of the second.
//
//go:deprecate
// Deprecated:
func ApSecond[GA ~func() A, GB ~func() B, GBB ~func() func(B) B, A, B any](second GB) func(GA) GB {
return G.ApSecond(
MonadAp[GB, GB, GBB, B, B],

View File

@@ -23,7 +23,7 @@ import (
// Bind creates an empty context of type [S] to be used with the [Bind] operation
//
//go:deprecate
// Deprecated:
func Do[GS ~func() S, S any](
empty S,
) GS {
@@ -32,7 +32,7 @@ func Do[GS ~func() S, S any](
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
//
//go:deprecate
// Deprecated:
func Bind[GS1 ~func() S1, GS2 ~func() S2, GT ~func() T, S1, S2, T any](
setter func(T) func(S1) S2,
f func(S1) GT,
@@ -47,7 +47,7 @@ func Bind[GS1 ~func() S1, GS2 ~func() S2, GT ~func() T, S1, S2, T any](
// Let attaches the result of a computation to a context [S1] to produce a context [S2]
//
//go:deprecate
// Deprecated:
func Let[GS1 ~func() S1, GS2 ~func() S2, S1, S2, T any](
key func(T) func(S1) S2,
f func(S1) T,
@@ -61,7 +61,7 @@ func Let[GS1 ~func() S1, GS2 ~func() S2, S1, S2, T any](
// LetTo attaches the a value to a context [S1] to produce a context [S2]
//
//go:deprecate
// Deprecated:
func LetTo[GS1 ~func() S1, GS2 ~func() S2, S1, S2, B any](
key func(B) func(S1) S2,
b B,
@@ -75,7 +75,7 @@ func LetTo[GS1 ~func() S1, GS2 ~func() S2, S1, S2, B any](
// BindTo initializes a new state [S1] from a value [T]
//
//go:deprecate
// Deprecated:
func BindTo[GS1 ~func() S1, GT ~func() T, S1, T any](
setter func(T) S1,
) func(GT) GS1 {
@@ -87,7 +87,7 @@ func BindTo[GS1 ~func() S1, GT ~func() T, S1, T any](
// ApS attaches a value to a context [S1] to produce a context [S2] by considering the context and the value concurrently
//
//go:deprecate
// Deprecated:
func ApS[GS1 ~func() S1, GS2 ~func() S2, GT ~func() T, S1, S2, T any](
setter func(T) func(S1) S2,
fa GT,

View File

@@ -22,7 +22,7 @@ import (
// 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:deprecate
// Deprecated:
func Bracket[
GA ~func() A,
GB ~func() B,

View File

@@ -21,7 +21,7 @@ import (
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
//
//go:deprecate
// Deprecated:
func WithResource[
GA ~func() A,
GR ~func() R,

View File

@@ -29,7 +29,7 @@ type retryStatusIO = func() R.RetryStatus
// 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:deprecate
// Deprecated:
func Retrying[GA ~func() A, A any](
policy R.RetryPolicy,

View File

@@ -21,7 +21,7 @@ import (
// WithLock executes the provided IO operation in the scope of a lock
//
//go:deprecate
// Deprecated:
func WithLock[GA ~func() A, A any](lock func() context.CancelFunc) func(fa GA) GA {
return func(fa GA) GA {
return func() A {

View File

@@ -21,7 +21,7 @@ import (
RR "github.com/IBM/fp-go/v2/internal/record"
)
//go:deprecate
// Deprecated:
func MonadTraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](tas AAS, f func(A) GB) GBS {
return RA.MonadTraverse(
Of[GBS, BBS],
@@ -33,7 +33,7 @@ func MonadTraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B
)
}
//go:deprecate
// Deprecated:
func MonadTraverseArraySeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](tas AAS, f func(A) GB) GBS {
return RA.MonadTraverse(
Of[GBS, BBS],
@@ -45,7 +45,7 @@ func MonadTraverseArraySeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A,
)
}
//go:deprecate
// Deprecated:
func MonadTraverseArrayPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](tas AAS, f func(A) GB) GBS {
return RA.MonadTraverse(
Of[GBS, BBS],
@@ -57,7 +57,7 @@ func MonadTraverseArrayPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A,
)
}
//go:deprecate
// Deprecated:
func TraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
return RA.Traverse[AAS](
Of[GBS, BBS],
@@ -68,7 +68,7 @@ func TraverseArray[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](
)
}
//go:deprecate
// Deprecated:
func TraverseArraySeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
return RA.Traverse[AAS](
Of[GBS, BBS],
@@ -79,7 +79,7 @@ func TraverseArraySeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B an
)
}
//go:deprecate
// Deprecated:
func TraverseArrayPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(A) GB) func(AAS) GBS {
return RA.Traverse[AAS](
Of[GBS, BBS],
@@ -90,7 +90,7 @@ func TraverseArrayPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B an
)
}
//go:deprecate
// Deprecated:
func TraverseArrayWithIndex[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
return RA.TraverseWithIndex[AAS](
Of[GBS, BBS],
@@ -101,7 +101,7 @@ func TraverseArrayWithIndex[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A
)
}
//go:deprecate
// Deprecated:
func TraverseArrayWithIndexSeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
return RA.TraverseWithIndex[AAS](
Of[GBS, BBS],
@@ -112,7 +112,7 @@ func TraverseArrayWithIndexSeq[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B
)
}
//go:deprecate
// Deprecated:
func TraverseArrayWithIndexPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B, A, B any](f func(int, A) GB) func(AAS) GBS {
return RA.TraverseWithIndex[AAS](
Of[GBS, BBS],
@@ -123,22 +123,22 @@ func TraverseArrayWithIndexPar[GB ~func() B, GBS ~func() BBS, AAS ~[]A, BBS ~[]B
)
}
//go:deprecate
// Deprecated:
func SequenceArray[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
return MonadTraverseArray[GA, GAS](tas, F.Identity[GA])
}
//go:deprecate
// Deprecated:
func SequenceArraySeq[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
return MonadTraverseArraySeq[GA, GAS](tas, F.Identity[GA])
}
//go:deprecate
// Deprecated:
func SequenceArrayPar[GA ~func() A, GAS ~func() AAS, AAS ~[]A, GAAS ~[]GA, A any](tas GAAS) GAS {
return MonadTraverseArrayPar[GA, GAS](tas, F.Identity[GA])
}
//go:deprecate MonadTraverseRecord transforms a record using an IO transform an IO of a record
// Deprecated: MonadTraverseRecord transforms a record using an IO transform an IO of a record
func MonadTraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
return RR.MonadTraverse[MA](
Of[GBS, MB],
@@ -148,7 +148,7 @@ func MonadTraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B,
)
}
//go:deprecate TraverseRecord transforms a record using an IO transform an IO of a record
// Deprecated: TraverseRecord transforms a record using an IO transform an IO of a record
func TraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
return RR.Traverse[MA](
Of[GBS, MB],
@@ -158,7 +158,7 @@ func TraverseRecord[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K co
)
}
//go:deprecate TraverseRecordWithIndex transforms a record using an IO transform an IO of a record
// Deprecated: TraverseRecordWithIndex transforms a record using an IO transform an IO of a record
func TraverseRecordWithIndex[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(K, A) GB) func(MA) GBS {
return RR.TraverseWithIndex[MA](
Of[GBS, MB],
@@ -168,12 +168,12 @@ func TraverseRecordWithIndex[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[
)
}
//go:deprecate
// Deprecated:
func SequenceRecord[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
return MonadTraverseRecord[GAS](tas, F.Identity[GA])
}
//go:deprecate MonadTraverseRecordSeq transforms a record using an IO transform an IO of a record
// Deprecated: MonadTraverseRecordSeq transforms a record using an IO transform an IO of a record
func MonadTraverseRecordSeq[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
return RR.MonadTraverse[MA](
Of[GBS, MB],
@@ -183,7 +183,7 @@ func MonadTraverseRecordSeq[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K
)
}
//go:deprecate TraverseRecordSeq transforms a record using an IO transform an IO of a record
// Deprecated: TraverseRecordSeq transforms a record using an IO transform an IO of a record
func TraverseRecordSeq[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
return RR.Traverse[MA](
Of[GBS, MB],
@@ -193,7 +193,7 @@ func TraverseRecordSeq[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K
)
}
//go:deprecate TraverseRecordWithIndexSeq transforms a record using an IO transform an IO of a record
// Deprecated: TraverseRecordWithIndexSeq transforms a record using an IO transform an IO of a record
func TraverseRecordWithIndexSeq[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(K, A) GB) func(MA) GBS {
return RR.TraverseWithIndex[MA](
Of[GBS, MB],
@@ -203,12 +203,12 @@ func TraverseRecordWithIndexSeq[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~m
)
}
//go:deprecate
// Deprecated:
func SequenceRecordSeq[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
return MonadTraverseRecordSeq[GAS](tas, F.Identity[GA])
}
//go:deprecate MonadTraverseRecordPar transforms a record using an IO transform an IO of a record
// Deprecated: MonadTraverseRecordPar transforms a record using an IO transform an IO of a record
func MonadTraverseRecordPar[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](ma MA, f func(A) GB) GBS {
return RR.MonadTraverse[MA](
Of[GBS, MB],
@@ -218,7 +218,7 @@ func MonadTraverseRecordPar[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K
)
}
//go:deprecate TraverseRecordPar transforms a record using an IO transform an IO of a record
// Deprecated: TraverseRecordPar transforms a record using an IO transform an IO of a record
func TraverseRecordPar[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K comparable, A, B any](f func(A) GB) func(MA) GBS {
return RR.Traverse[MA](
Of[GBS, MB],
@@ -228,7 +228,7 @@ func TraverseRecordPar[GBS ~func() MB, MA ~map[K]A, GB ~func() B, MB ~map[K]B, K
)
}
//go:deprecate TraverseRecordWithIndexPar transforms a record using an IO transform an IO of a record
// Deprecated: TraverseRecordWithIndexPar transforms a record using an IO transform an IO of a record
func TraverseRecordWithIndexPar[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~map[K]B, K comparable, A, B any](f func(K, A) GB) func(MA) GBS {
return RR.TraverseWithIndex[MA](
Of[GBS, MB],
@@ -238,7 +238,7 @@ func TraverseRecordWithIndexPar[GB ~func() B, GBS ~func() MB, MA ~map[K]A, MB ~m
)
}
//go:deprecate
// Deprecated:
func SequenceRecordPar[GA ~func() A, GAS ~func() AAS, AAS ~map[K]A, GAAS ~map[K]GA, K comparable, A any](tas GAAS) GAS {
return MonadTraverseRecordPar[GAS](tas, F.Identity[GA])
}

View File

@@ -134,6 +134,10 @@ func ApSeq[B, A any](ma IO[A]) Mapper[func(A) B, B] {
return Chain(F.Bind1st(MonadMap[A, B], ma))
}
func ApPar[B, A any](ma IO[A]) Mapper[func(A) B, B] {
return F.Bind2nd(MonadApPar[A, B], ma)
}
func Flatten[A any](mma IO[IO[A]]) IO[A] {
return MonadChain(mma, F.Identity)
}

View File

@@ -18,19 +18,19 @@ package file
import (
"os"
IOE "github.com/IBM/fp-go/v2/ioeither"
"github.com/IBM/fp-go/v2/ioeither"
)
// MkdirAll create a sequence of directories, see [os.MkdirAll]
func MkdirAll(path string, perm os.FileMode) IOE.IOEither[error, string] {
return IOE.TryCatchError(func() (string, error) {
func MkdirAll(path string, perm os.FileMode) ioeither.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) IOE.IOEither[error, string] {
return IOE.TryCatchError(func() (string, error) {
func Mkdir(path string, perm os.FileMode) ioeither.IOEither[error, string] {
return ioeither.TryCatchError(func() (string, error) {
return path, os.Mkdir(path, perm)
})
}

View File

@@ -19,37 +19,37 @@ import (
"io"
"os"
IOE "github.com/IBM/fp-go/v2/ioeither"
"github.com/IBM/fp-go/v2/ioeither"
)
var (
// Open opens a file for reading
Open = IOE.Eitherize1(os.Open)
Open = ioeither.Eitherize1(os.Open)
// Create opens a file for writing
Create = IOE.Eitherize1(os.Create)
Create = ioeither.Eitherize1(os.Create)
// ReadFile reads the context of a file
ReadFile = IOE.Eitherize1(os.ReadFile)
ReadFile = ioeither.Eitherize1(os.ReadFile)
)
// WriteFile writes a data blob to a file
func WriteFile(dstName string, perm os.FileMode) func([]byte) IOE.IOEither[error, []byte] {
return func(data []byte) IOE.IOEither[error, []byte] {
return IOE.TryCatchError(func() ([]byte, error) {
func WriteFile(dstName string, perm os.FileMode) func([]byte) ioeither.IOEither[error, []byte] {
return func(data []byte) ioeither.IOEither[error, []byte] {
return ioeither.TryCatchError(func() ([]byte, error) {
return data, os.WriteFile(dstName, data, perm)
})
}
}
// Remove removes a file by name
func Remove(name string) IOE.IOEither[error, string] {
return IOE.TryCatchError(func() (string, error) {
func Remove(name string) ioeither.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) IOE.IOEither[error, any] {
return IOE.TryCatchError(func() (any, error) {
func Close[C io.Closer](c C) ioeither.IOEither[error, any] {
return ioeither.TryCatchError(func() (any, error) {
return c, c.Close()
})
}

View File

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

View File

@@ -21,24 +21,24 @@ import (
F "github.com/IBM/fp-go/v2/function"
IO "github.com/IBM/fp-go/v2/io"
IOF "github.com/IBM/fp-go/v2/io/file"
IOE "github.com/IBM/fp-go/v2/ioeither"
"github.com/IBM/fp-go/v2/ioeither"
)
var (
// CreateTemp created a temp file with proper parametrization
CreateTemp = IOE.Eitherize2(os.CreateTemp)
CreateTemp = ioeither.Eitherize2(os.CreateTemp)
// onCreateTempFile creates a temp file with sensible defaults
onCreateTempFile = CreateTemp("", "*")
// destroy handler
onReleaseTempFile = F.Flow4(
IOF.Close[*os.File],
IO.Map((*os.File).Name),
IOE.FromIO[error, string],
IOE.Chain(Remove),
ioeither.FromIO[error, string],
ioeither.Chain(Remove),
)
)
// 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) IOE.IOEither[error, A]) IOE.IOEither[error, A] {
return IOE.WithResource[A](onCreateTempFile, onReleaseTempFile)(f)
func WithTempFile[A any](f func(*os.File) ioeither.IOEither[error, A]) ioeither.IOEither[error, A] {
return ioeither.WithResource[A](onCreateTempFile, onReleaseTempFile)(f)
}

View File

@@ -21,7 +21,7 @@ import (
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/ioeither"
"github.com/stretchr/testify/assert"
)
@@ -34,11 +34,11 @@ func TestWithTempFile(t *testing.T) {
func TestWithTempFileOnClosedFile(t *testing.T) {
res := WithTempFile(func(f *os.File) IOE.IOEither[error, []byte] {
res := WithTempFile(func(f *os.File) ioeither.IOEither[error, []byte] {
return F.Pipe2(
f,
onWriteAll[*os.File]([]byte("Carsten")),
IOE.ChainFirst(F.Constant1[[]byte](Close(f))),
ioeither.ChainFirst(F.Constant1[[]byte](Close(f))),
)
})

View File

@@ -18,12 +18,12 @@ package file
import (
"io"
IOE "github.com/IBM/fp-go/v2/ioeither"
"github.com/IBM/fp-go/v2/ioeither"
)
func onWriteAll[W io.Writer](data []byte) func(w W) IOE.IOEither[error, []byte] {
return func(w W) IOE.IOEither[error, []byte] {
return IOE.TryCatchError(func() ([]byte, error) {
func onWriteAll[W io.Writer](data []byte) func(w W) ioeither.IOEither[error, []byte] {
return func(w W) ioeither.IOEither[error, []byte] {
return ioeither.TryCatchError(func() ([]byte, error) {
_, err := w.Write(data)
return data, err
})
@@ -31,10 +31,10 @@ func onWriteAll[W io.Writer](data []byte) func(w W) IOE.IOEither[error, []byte]
}
// 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 IOE.IOEither[error, W]) IOE.IOEither[error, []byte] {
func WriteAll[W io.WriteCloser](data []byte) func(acquire ioeither.IOEither[error, W]) ioeither.IOEither[error, []byte] {
onWrite := onWriteAll[W](data)
return func(onCreate IOE.IOEither[error, W]) IOE.IOEither[error, []byte] {
return IOE.WithResource[[]byte](
return func(onCreate ioeither.IOEither[error, W]) ioeither.IOEither[error, []byte] {
return ioeither.WithResource[[]byte](
onCreate,
Close[W])(
onWrite,
@@ -43,8 +43,8 @@ func WriteAll[W io.WriteCloser](data []byte) func(acquire IOE.IOEither[error, W]
}
// Write uses a generator function to create a stream, writes data to it and closes it
func Write[R any, W io.WriteCloser](acquire IOE.IOEither[error, W]) func(use func(W) IOE.IOEither[error, R]) IOE.IOEither[error, R] {
return IOE.WithResource[R](
func Write[R any, W io.WriteCloser](acquire ioeither.IOEither[error, W]) func(use func(W) ioeither.IOEither[error, R]) ioeither.IOEither[error, R] {
return ioeither.WithResource[R](
acquire,
Close[W])
}

View File

@@ -31,30 +31,37 @@ import (
// type IOEither[E, A any] = func() Either[E, A]
// Deprecated:
func MakeIO[GA ~func() ET.Either[E, A], E, A any](f GA) GA {
return f
}
// Deprecated:
func Left[GA ~func() ET.Either[E, A], E, A any](l E) GA {
return MakeIO(eithert.Left(IO.MonadOf[GA, ET.Either[E, A]], l))
}
// Deprecated:
func Right[GA ~func() ET.Either[E, A], E, A any](r A) GA {
return MakeIO(eithert.Right(IO.MonadOf[GA, ET.Either[E, A]], r))
}
// Deprecated:
func Of[GA ~func() ET.Either[E, A], E, A any](r A) GA {
return Right[GA](r)
}
// Deprecated:
func MonadOf[GA ~func() ET.Either[E, A], E, A any](r A) GA {
return Of[GA](r)
}
// Deprecated:
func LeftIO[GA ~func() ET.Either[E, A], GE ~func() E, E, A any](ml GE) GA {
return MakeIO(eithert.LeftF(IO.MonadMap[GE, GA, E, ET.Either[E, A]], ml))
}
// Deprecated:
func RightIO[GA ~func() ET.Either[E, A], GR ~func() A, E, A any](mr GR) GA {
return MakeIO(eithert.RightF(IO.MonadMap[GR, GA, A, ET.Either[E, A]], mr))
}
@@ -78,30 +85,37 @@ func ChainOptionK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A,
)
}
// Deprecated:
func FromIO[GA ~func() ET.Either[E, A], GR ~func() A, E, A any](mr GR) GA {
return RightIO[GA](mr)
}
// Deprecated:
func MonadMap[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, f func(A) B) GB {
return eithert.MonadMap(IO.MonadMap[GA, GB, ET.Either[E, A], ET.Either[E, B]], fa, f)
}
// Deprecated:
func Map[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) B) func(GA) GB {
return eithert.Map(IO.Map[GA, GB, ET.Either[E, A], ET.Either[E, B]], f)
}
// Deprecated:
func MonadMapTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, b B) GB {
return MonadMap[GA, GB](fa, F.Constant1[A](b))
}
// Deprecated:
func MapTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](b B) func(GA) GB {
return Map[GA, GB](F.Constant1[A](b))
}
// Deprecated:
func MonadChain[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](fa GA, f func(A) GB) GB {
return eithert.MonadChain(IO.MonadChain[GA, GB, ET.Either[E, A], ET.Either[E, B]], IO.MonadOf[GB, ET.Either[E, B]], fa, f)
}
// Deprecated:
func Chain[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) GB) func(GA) GB {
return eithert.Chain(IO.Chain[GA, GB, ET.Either[E, A], ET.Either[E, B]], IO.Of[GB, ET.Either[E, B]], f)
}
@@ -114,6 +128,7 @@ func ChainTo[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any
return Chain[GA, GB, E, A, B](F.Constant1[A](fb))
}
// Deprecated:
func MonadChainEitherK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](ma GA, f func(A) ET.Either[E, B]) GB {
return FE.MonadChainEitherK(
MonadChain[GA, GB, E, A, B],
@@ -123,6 +138,7 @@ func MonadChainEitherK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E
)
}
// Deprecated:
func MonadChainIOK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GR ~func() B, E, A, B any](ma GA, f func(A) GR) GB {
return FI.MonadChainIOK(
MonadChain[GA, GB, E, A, B],
@@ -140,6 +156,7 @@ func ChainIOK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], GR ~func()
)
}
// Deprecated:
func ChainEitherK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) ET.Either[E, B]) func(GA) GB {
return FE.ChainEitherK(
Chain[GA, GB, E, A, B],
@@ -148,6 +165,7 @@ func ChainEitherK[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A,
)
}
// Deprecated:
func MonadAp[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~func() ET.Either[E, A], E, A, B any](mab GAB, ma GA) GB {
return eithert.MonadAp(
IO.MonadAp[GA, GB, func() func(ET.Either[E, A]) ET.Either[E, B], ET.Either[E, A], ET.Either[E, B]],
@@ -155,6 +173,7 @@ func MonadAp[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA
mab, ma)
}
// Deprecated:
func Ap[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~func() ET.Either[E, A], E, A, B any](ma GA) func(GAB) GB {
return eithert.Ap(
IO.Ap[GB, func() func(ET.Either[E, A]) ET.Either[E, B], GA, ET.Either[E, B], ET.Either[E, A]],
@@ -162,6 +181,7 @@ func Ap[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~fun
ma)
}
// Deprecated:
func MonadApSeq[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~func() ET.Either[E, A], E, A, B any](mab GAB, ma GA) GB {
return eithert.MonadAp(
IO.MonadApSeq[GA, GB, func() func(ET.Either[E, A]) ET.Either[E, B], ET.Either[E, A], ET.Either[E, B]],
@@ -169,6 +189,7 @@ func MonadApSeq[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B],
mab, ma)
}
// Deprecated:
func ApSeq[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~func() ET.Either[E, A], E, A, B any](ma GA) func(GAB) GB {
return eithert.Ap(
IO.ApSeq[GB, func() func(ET.Either[E, A]) ET.Either[E, B], GA, ET.Either[E, B], ET.Either[E, A]],
@@ -176,6 +197,7 @@ func ApSeq[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~
ma)
}
// Deprecated:
func MonadApPar[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~func() ET.Either[E, A], E, A, B any](mab GAB, ma GA) GB {
return eithert.MonadAp(
IO.MonadApPar[GA, GB, func() func(ET.Either[E, A]) ET.Either[E, B], ET.Either[E, A], ET.Either[E, B]],
@@ -183,6 +205,7 @@ func MonadApPar[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B],
mab, ma)
}
// Deprecated:
func ApPar[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~func() ET.Either[E, A], E, A, B any](ma GA) func(GAB) GB {
return eithert.Ap(
IO.ApPar[GB, func() func(ET.Either[E, A]) ET.Either[E, B], GA, ET.Either[E, B], ET.Either[E, A]],
@@ -190,10 +213,12 @@ func ApPar[GB ~func() ET.Either[E, B], GAB ~func() ET.Either[E, func(A) B], GA ~
ma)
}
// Deprecated:
func Flatten[GA ~func() ET.Either[E, A], GAA ~func() ET.Either[E, GA], E, A any](mma GAA) GA {
return MonadChain(mma, F.Identity[GA])
}
// Deprecated:
func TryCatch[GA ~func() ET.Either[E, A], E, A any](f func() (A, error), onThrow func(error) E) GA {
return MakeIO(func() ET.Either[E, A] {
a, err := f()
@@ -201,6 +226,7 @@ func TryCatch[GA ~func() ET.Either[E, A], E, A any](f func() (A, error), onThrow
})
}
// Deprecated:
func TryCatchError[GA ~func() ET.Either[error, A], A any](f func() (A, error)) GA {
return MakeIO(func() ET.Either[error, A] {
return ET.TryCatchError(f())
@@ -208,10 +234,13 @@ func TryCatchError[GA ~func() ET.Either[error, A], A any](f func() (A, error)) G
}
// Memoize computes the value of the provided IO monad lazily but exactly once
//
// Deprecated:
func Memoize[GA ~func() ET.Either[E, A], E, A any](ma GA) GA {
return IO.Memoize(ma)
}
// Deprecated:
func MonadMapLeft[GA1 ~func() ET.Either[E1, A], GA2 ~func() ET.Either[E2, A], E1, E2, A any](fa GA1, f func(E1) E2) GA2 {
return eithert.MonadMapLeft(
IO.MonadMap[GA1, GA2, ET.Either[E1, A], ET.Either[E2, A]],
@@ -220,6 +249,7 @@ func MonadMapLeft[GA1 ~func() ET.Either[E1, A], GA2 ~func() ET.Either[E2, A], E1
)
}
// Deprecated:
func MapLeft[GA1 ~func() ET.Either[E1, A], GA2 ~func() ET.Either[E2, A], E1, E2, A any](f func(E1) E2) func(GA1) GA2 {
return eithert.MapLeft(
IO.Map[GA1, GA2, ET.Either[E1, A], ET.Either[E2, A]],
@@ -228,25 +258,34 @@ func MapLeft[GA1 ~func() ET.Either[E1, A], GA2 ~func() ET.Either[E2, A], E1, E2,
}
// Delay creates an operation that passes in the value after some [time.Duration]
//
// Deprecated:
func Delay[GA ~func() ET.Either[E, A], E, A any](delay time.Duration) func(GA) GA {
return IO.Delay[GA](delay)
}
// After creates an operation that passes after the given [time.Time]
//
// Deprecated:
func After[GA ~func() ET.Either[E, A], E, A any](timestamp time.Time) func(GA) GA {
return IO.After[GA](timestamp)
}
// Deprecated:
func MonadBiMap[GA ~func() ET.Either[E1, A], GB ~func() ET.Either[E2, B], E1, E2, A, B any](fa GA, f func(E1) E2, g func(A) B) GB {
return eithert.MonadBiMap(IO.MonadMap[GA, GB, ET.Either[E1, A], ET.Either[E2, B]], fa, f, g)
}
// BiMap maps a pair of functions over the two type arguments of the bifunctor.
//
// Deprecated:
func BiMap[GA ~func() ET.Either[E1, A], GB ~func() ET.Either[E2, B], E1, E2, A, B any](f func(E1) E2, g func(A) B) func(GA) GB {
return eithert.BiMap(IO.Map[GA, GB, ET.Either[E1, A], ET.Either[E2, B]], f, g)
}
// Fold convers an IOEither into an IO
//
// Deprecated:
func Fold[GA ~func() ET.Either[E, A], GB ~func() B, E, A, B any](onLeft func(E) GB, onRight func(A) GB) func(GA) GB {
return eithert.MatchE(IO.MonadChain[GA, GB, ET.Either[E, A], B], onLeft, onRight)
}
@@ -261,6 +300,8 @@ func GetOrElse[GA ~func() ET.Either[E, A], GB ~func() A, E, A any](onLeft func(E
}
// MonadChainFirst runs the monad returned by the function but returns the result of the original monad
//
// Deprecated:
func MonadChainFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](ma GA, f func(A) GB) GA {
return C.MonadChainFirst(
MonadChain[GA, GA, E, A, A],
@@ -271,6 +312,8 @@ func MonadChainFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E,
}
// ChainFirst runs the monad returned by the function but returns the result of the original monad
//
// Deprecated:
func ChainFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B any](f func(A) GB) func(GA) GA {
return C.ChainFirst(
Chain[GA, GA, E, A, A],
@@ -280,6 +323,8 @@ func ChainFirst[GA ~func() ET.Either[E, A], GB ~func() ET.Either[E, B], E, A, B
}
// MonadChainFirstIOK runs the monad returned by the function but returns the result of the original monad
//
// Deprecated:
func MonadChainFirstIOK[GA ~func() ET.Either[E, A], GIOB ~func() B, E, A, B any](first GA, f func(A) GIOB) GA {
return FI.MonadChainFirstIOK(
MonadChain[GA, GA, E, A, A],
@@ -291,6 +336,8 @@ func MonadChainFirstIOK[GA ~func() ET.Either[E, A], GIOB ~func() B, E, A, B any]
}
// ChainFirstIOK runs the monad returned by the function but returns the result of the original monad
//
// Deprecated:
func ChainFirstIOK[GA ~func() ET.Either[E, A], GIOB ~func() B, E, A, B any](f func(A) GIOB) func(GA) GA {
return FI.ChainFirstIOK(
Chain[GA, GA, E, A, A],
@@ -301,6 +348,8 @@ func ChainFirstIOK[GA ~func() ET.Either[E, A], GIOB ~func() B, E, A, B any](f fu
}
// MonadChainFirstEitherK runs the monad returned by the function but returns the result of the original monad
//
// Deprecated:
func MonadChainFirstEitherK[GA ~func() ET.Either[E, A], E, A, B any](first GA, f func(A) ET.Either[E, B]) GA {
return FE.MonadChainFirstEitherK(
MonadChain[GA, GA, E, A, A],
@@ -312,6 +361,8 @@ func MonadChainFirstEitherK[GA ~func() ET.Either[E, A], E, A, B any](first GA, f
}
// ChainFirstEitherK runs the monad returned by the function but returns the result of the original monad
//
// Deprecated:
func ChainFirstEitherK[GA ~func() ET.Either[E, A], E, A, B any](f func(A) ET.Either[E, B]) func(GA) GA {
return FE.ChainFirstEitherK(
Chain[GA, GA, E, A, A],
@@ -322,11 +373,15 @@ func ChainFirstEitherK[GA ~func() ET.Either[E, A], E, A, B any](f func(A) ET.Eit
}
// Swap changes the order of type parameters
//
// Deprecated:
func Swap[GEA ~func() ET.Either[E, A], GAE ~func() ET.Either[A, E], E, A any](val GEA) GAE {
return MonadFold(val, Right[GAE], Left[GAE])
}
// FromImpure converts a side effect without a return value into a side effect that returns any
//
// Deprecated:
func FromImpure[GA ~func() ET.Either[E, any], IMP ~func(), E any](f IMP) GA {
return F.Pipe2(
f,
@@ -336,10 +391,13 @@ func FromImpure[GA ~func() ET.Either[E, any], IMP ~func(), E any](f IMP) GA {
}
// Defer creates an IO by creating a brand new IO via a generator function, each time
//
// Deprecated:
func Defer[GEA ~func() ET.Either[E, A], E, A any](gen func() GEA) GEA {
return IO.Defer[GEA](gen)
}
// Deprecated:
func MonadAlt[LAZY ~func() GIOA, GIOA ~func() ET.Either[E, A], E, A any](first GIOA, second LAZY) GIOA {
return eithert.MonadAlt(
IO.Of[GIOA],
@@ -350,18 +408,22 @@ func MonadAlt[LAZY ~func() GIOA, GIOA ~func() ET.Either[E, A], E, A any](first G
)
}
// Deprecated:
func Alt[LAZY ~func() GIOA, GIOA ~func() ET.Either[E, A], E, A any](second LAZY) func(GIOA) GIOA {
return F.Bind2nd(MonadAlt[LAZY], second)
}
// Deprecated:
func MonadFlap[GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], E, B, A any](fab GEAB, a A) GEB {
return FC.MonadFlap(MonadMap[GEAB, GEB], fab, a)
}
// Deprecated:
func Flap[GEAB ~func() ET.Either[E, func(A) B], GEB ~func() ET.Either[E, B], E, B, A any](a A) func(GEAB) GEB {
return FC.Flap(Map[GEAB, GEB], a)
}
// Deprecated:
func ToIOOption[GA ~func() O.Option[A], GEA ~func() ET.Either[E, A], E, A any](ioe GEA) GA {
return F.Pipe1(
ioe,
@@ -369,6 +431,7 @@ func ToIOOption[GA ~func() O.Option[A], GEA ~func() ET.Either[E, A], E, A any](i
)
}
// Deprecated:
func FromIOOption[GEA ~func() ET.Either[E, A], GA ~func() O.Option[A], E, A any](onNone func() E) func(ioo GA) GEA {
return IO.Map[GA, GEA](ET.FromOption[A](onNone))
}

View File

@@ -1,51 +0,0 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
"encoding/json"
"log"
B "github.com/IBM/fp-go/v2/bytes"
ET "github.com/IBM/fp-go/v2/either"
F "github.com/IBM/fp-go/v2/function"
)
// LogJSON converts the argument to JSON and then logs it via the format string
// Can be used with [ChainFirst]
func LogJSON[GA ~func() ET.Either[error, any], A any](prefix string) func(A) GA {
return func(a A) GA {
// log this
return F.Pipe3(
ET.TryCatchError(json.MarshalIndent(a, "", " ")),
ET.Map[error](B.ToString),
FromEither[func() ET.Either[error, string]],
Chain[func() ET.Either[error, string], GA](func(data string) GA {
return FromImpure[GA](func() {
log.Printf(prefix, data)
})
}),
)
}
}
// LogJson converts the argument to JSON and then logs it via the format string
// Can be used with [ChainFirst]
//
// Deprecated: use [LogJSON] instead
func LogJson[GA ~func() ET.Either[error, any], A any](prefix string) func(A) GA {
return LogJSON[GA, A](prefix)
}

View File

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

View File

@@ -1,54 +0,0 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
ET "github.com/IBM/fp-go/v2/either"
M "github.com/IBM/fp-go/v2/monoid"
)
func ApplicativeMonoid[GEA ~func() ET.Either[E, A], GEFA ~func() ET.Either[E, func(A) A], E, A any](
m M.Monoid[A],
) M.Monoid[GEA] {
return M.ApplicativeMonoid(
MonadOf[GEA],
MonadMap[GEA, GEFA],
MonadAp[GEA, GEFA, GEA],
m,
)
}
func ApplicativeMonoidSeq[GEA ~func() ET.Either[E, A], GEFA ~func() ET.Either[E, func(A) A], E, A any](
m M.Monoid[A],
) M.Monoid[GEA] {
return M.ApplicativeMonoid(
MonadOf[GEA],
MonadMap[GEA, GEFA],
MonadApSeq[GEA, GEFA, GEA],
m,
)
}
func ApplicativeMonoidPar[GEA ~func() ET.Either[E, A], GEFA ~func() ET.Either[E, func(A) A], E, A any](
m M.Monoid[A],
) M.Monoid[GEA] {
return M.ApplicativeMonoid(
MonadOf[GEA],
MonadMap[GEA, GEFA],
MonadApPar[GEA, GEFA, GEA],
m,
)
}

View File

@@ -1,37 +0,0 @@
// Copyright (c) 2023 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package generic
import (
ET "github.com/IBM/fp-go/v2/either"
F "github.com/IBM/fp-go/v2/function"
IF "github.com/IBM/fp-go/v2/internal/file"
)
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
func WithResource[
GA ~func() ET.Either[E, A],
GR ~func() ET.Either[E, R],
GANY ~func() ET.Either[E, ANY],
E, R, A, ANY any](onCreate GR, onRelease func(R) GANY) func(func(R) GA) GA {
return IF.WithResource(
MonadChain[GR, GA, E, R, A],
MonadFold[GA, GA, E, A, ET.Either[E, A]],
MonadFold[GANY, GA, E, ANY, ET.Either[E, A]],
MonadMap[GANY, GA, E, ANY, A],
Left[GA, E, A],
)(F.Constant(onCreate), onRelease)
}

View File

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

View File

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

View File

@@ -18,275 +18,389 @@ package ioeither
import (
"time"
ET "github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/function"
"github.com/IBM/fp-go/v2/internal/chain"
"github.com/IBM/fp-go/v2/internal/eithert"
I "github.com/IBM/fp-go/v2/io"
IOG "github.com/IBM/fp-go/v2/io/generic"
G "github.com/IBM/fp-go/v2/ioeither/generic"
"github.com/IBM/fp-go/v2/internal/file"
"github.com/IBM/fp-go/v2/internal/fromeither"
"github.com/IBM/fp-go/v2/internal/fromio"
"github.com/IBM/fp-go/v2/internal/functor"
"github.com/IBM/fp-go/v2/io"
IOO "github.com/IBM/fp-go/v2/iooption"
L "github.com/IBM/fp-go/v2/lazy"
"github.com/IBM/fp-go/v2/lazy"
O "github.com/IBM/fp-go/v2/option"
R "github.com/IBM/fp-go/v2/reader"
)
// IOEither represents a synchronous computation that may fail
// refer to [https://andywhite.xyz/posts/2021-01-27-rte-foundations/#ioeitherlte-agt] for more details
type IOEither[E, A any] = I.IO[ET.Either[E, A]]
type (
// IOEither represents a synchronous computation that may fail
// refer to [https://andywhite.xyz/posts/2021-01-27-rte-foundations/#ioeitherlte-agt] for more details
IOEither[E, A any] = io.IO[either.Either[E, A]]
func MakeIO[E, A any](f IOEither[E, A]) IOEither[E, A] {
return f
}
Mapper[E, A, B any] = R.Reader[IOEither[E, A], IOEither[E, B]]
)
func Left[A, E any](l E) IOEither[E, A] {
return eithert.Left(IOG.MonadOf[IOEither[E, A], ET.Either[E, A]], l)
return eithert.Left(io.MonadOf[either.Either[E, A]], l)
}
func Right[E, A any](r A) IOEither[E, A] {
return eithert.Right(IOG.MonadOf[IOEither[E, A], ET.Either[E, A]], r)
return eithert.Right(io.MonadOf[either.Either[E, A]], r)
}
func Of[E, A any](r A) IOEither[E, A] {
return Right[E, A](r)
return Right[E](r)
}
func MonadOf[E, A any](r A) IOEither[E, A] {
return Of[E, A](r)
return Of[E](r)
}
func LeftIO[A, E any](ml I.IO[E]) IOEither[E, A] {
return G.LeftIO[IOEither[E, A]](ml)
func LeftIO[A, E any](ml io.IO[E]) IOEither[E, A] {
return eithert.LeftF(io.MonadMap[E, either.Either[E, A]], ml)
}
func RightIO[E, A any](mr I.IO[A]) IOEither[E, A] {
return G.RightIO[IOEither[E, A]](mr)
func RightIO[E, A any](mr io.IO[A]) IOEither[E, A] {
return eithert.RightF(io.MonadMap[A, either.Either[E, A]], mr)
}
func FromEither[E, A any](e ET.Either[E, A]) IOEither[E, A] {
return G.FromEither[IOEither[E, A]](e)
func FromEither[E, A any](e either.Either[E, A]) IOEither[E, A] {
return io.Of(e)
}
func FromOption[A, E any](onNone func() E) func(o O.Option[A]) IOEither[E, A] {
return G.FromOption[IOEither[E, A]](onNone)
return fromeither.FromOption(
FromEither[E, A],
onNone,
)
}
func FromIOOption[A, E any](onNone func() E) func(o IOO.IOOption[A]) IOEither[E, A] {
return G.FromIOOption[IOEither[E, A], IOO.IOOption[A]](onNone)
return io.Map(either.FromOption[A](onNone))
}
func ChainOptionK[A, B, E any](onNone func() E) func(func(A) O.Option[B]) func(IOEither[E, A]) IOEither[E, B] {
return G.ChainOptionK[IOEither[E, A], IOEither[E, B]](onNone)
return fromeither.ChainOptionK(
MonadChain[E, A, B],
FromEither[E, B],
onNone,
)
}
func MonadChainIOK[E, A, B any](ma IOEither[E, A], f func(A) I.IO[B]) IOEither[E, B] {
return G.MonadChainIOK[IOEither[E, A], IOEither[E, B]](ma, f)
func MonadChainIOK[E, A, B any](ma IOEither[E, A], f func(A) io.IO[B]) IOEither[E, B] {
return fromio.MonadChainIOK(
MonadChain[E, A, B],
FromIO[E, B],
ma,
f,
)
}
func ChainIOK[E, A, B any](f func(A) I.IO[B]) func(IOEither[E, A]) IOEither[E, B] {
return G.ChainIOK[IOEither[E, A], IOEither[E, B]](f)
func ChainIOK[E, A, B any](f func(A) io.IO[B]) func(IOEither[E, A]) IOEither[E, B] {
return fromio.ChainIOK(
Chain[E, A, B],
FromIO[E, B],
f,
)
}
func ChainLazyK[E, A, B any](f func(A) L.Lazy[B]) func(IOEither[E, A]) IOEither[E, B] {
return G.ChainIOK[IOEither[E, A], IOEither[E, B]](f)
func ChainLazyK[E, A, B any](f func(A) lazy.Lazy[B]) func(IOEither[E, A]) IOEither[E, B] {
return ChainIOK[E](f)
}
// FromIO creates an [IOEither] from an [IO] instance, invoking [IO] for each invocation of [IOEither]
func FromIO[E, A any](mr I.IO[A]) IOEither[E, A] {
return G.FromIO[IOEither[E, A]](mr)
func FromIO[E, A any](mr io.IO[A]) IOEither[E, A] {
return RightIO[E](mr)
}
// FromLazy creates an [IOEither] from a [Lazy] instance, invoking [Lazy] for each invocation of [IOEither]
func FromLazy[E, A any](mr L.Lazy[A]) IOEither[E, A] {
return G.FromIO[IOEither[E, A]](mr)
func FromLazy[E, A any](mr lazy.Lazy[A]) IOEither[E, A] {
return FromIO[E](mr)
}
func MonadMap[E, A, B any](fa IOEither[E, A], f func(A) B) IOEither[E, B] {
return G.MonadMap[IOEither[E, A], IOEither[E, B]](fa, f)
return eithert.MonadMap(io.MonadMap[either.Either[E, A], either.Either[E, B]], fa, f)
}
func Map[E, A, B any](f func(A) B) func(IOEither[E, A]) IOEither[E, B] {
return G.Map[IOEither[E, A], IOEither[E, B]](f)
func Map[E, A, B any](f func(A) B) Mapper[E, A, B] {
return eithert.Map(io.Map[either.Either[E, A], either.Either[E, B]], f)
}
func MonadMapTo[E, A, B any](fa IOEither[E, A], b B) IOEither[E, B] {
return G.MonadMapTo[IOEither[E, A], IOEither[E, B]](fa, b)
return MonadMap(fa, function.Constant1[A](b))
}
func MapTo[E, A, B any](b B) func(IOEither[E, A]) IOEither[E, B] {
return G.MapTo[IOEither[E, A], IOEither[E, B]](b)
func MapTo[E, A, B any](b B) Mapper[E, A, B] {
return Map[E](function.Constant1[A](b))
}
func MonadChain[E, A, B any](fa IOEither[E, A], f func(A) IOEither[E, B]) IOEither[E, B] {
return G.MonadChain(fa, f)
return eithert.MonadChain(io.MonadChain[either.Either[E, A], either.Either[E, B]], io.MonadOf[either.Either[E, B]], fa, f)
}
func Chain[E, A, B any](f func(A) IOEither[E, B]) func(IOEither[E, A]) IOEither[E, B] {
return G.Chain[IOEither[E, A]](f)
func Chain[E, A, B any](f func(A) IOEither[E, B]) Mapper[E, A, B] {
return eithert.Chain(io.Chain[either.Either[E, A], either.Either[E, B]], io.Of[either.Either[E, B]], f)
}
func MonadChainEitherK[E, A, B any](ma IOEither[E, A], f func(A) ET.Either[E, B]) IOEither[E, B] {
return G.MonadChainEitherK[IOEither[E, A], IOEither[E, B]](ma, f)
func MonadChainEitherK[E, A, B any](ma IOEither[E, A], f func(A) either.Either[E, B]) IOEither[E, B] {
return fromeither.MonadChainEitherK(
MonadChain[E, A, B],
FromEither[E, B],
ma,
f,
)
}
func ChainEitherK[E, A, B any](f func(A) ET.Either[E, B]) func(IOEither[E, A]) IOEither[E, B] {
return G.ChainEitherK[IOEither[E, A], IOEither[E, B]](f)
func ChainEitherK[E, A, B any](f func(A) either.Either[E, B]) func(IOEither[E, A]) IOEither[E, B] {
return fromeither.ChainEitherK(
Chain[E, A, B],
FromEither[E, B],
f,
)
}
func MonadAp[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEither[E, B] {
return G.MonadAp[IOEither[E, B]](mab, ma)
return eithert.MonadAp(
io.MonadAp[either.Either[E, A], either.Either[E, B]],
io.MonadMap[either.Either[E, func(A) B], func(either.Either[E, A]) either.Either[E, B]],
mab, ma)
}
// Ap is an alias of [ApPar]
func Ap[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
return G.Ap[IOEither[E, B], IOEither[E, func(A) B]](ma)
func Ap[B, E, A any](ma IOEither[E, A]) Mapper[E, func(A) B, B] {
return eithert.Ap(
io.Ap[either.Either[E, B], either.Either[E, A]],
io.Map[either.Either[E, func(A) B], func(either.Either[E, A]) either.Either[E, B]],
ma)
}
func MonadApPar[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEither[E, B] {
return G.MonadApPar[IOEither[E, B]](mab, ma)
return eithert.MonadAp(
io.MonadApPar[either.Either[E, A], either.Either[E, B]],
io.MonadMap[either.Either[E, func(A) B], func(either.Either[E, A]) either.Either[E, B]],
mab, ma)
}
// ApPar applies function and value in parallel
func ApPar[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
return G.ApPar[IOEither[E, B], IOEither[E, func(A) B]](ma)
func ApPar[B, E, A any](ma IOEither[E, A]) Mapper[E, func(A) B, B] {
return eithert.Ap(
io.ApPar[either.Either[E, B], either.Either[E, A]],
io.Map[either.Either[E, func(A) B], func(either.Either[E, A]) either.Either[E, B]],
ma)
}
func MonadApSeq[B, E, A any](mab IOEither[E, func(A) B], ma IOEither[E, A]) IOEither[E, B] {
return G.MonadApSeq[IOEither[E, B]](mab, ma)
return eithert.MonadAp(
io.MonadApSeq[either.Either[E, A], either.Either[E, B]],
io.MonadMap[either.Either[E, func(A) B], func(either.Either[E, A]) either.Either[E, B]],
mab, ma)
}
// ApSeq applies function and value sequentially
func ApSeq[B, E, A any](ma IOEither[E, A]) func(IOEither[E, func(A) B]) IOEither[E, B] {
return G.ApSeq[IOEither[E, B], IOEither[E, func(A) B]](ma)
return eithert.Ap(
io.ApSeq[either.Either[E, B], either.Either[E, A]],
io.Map[either.Either[E, func(A) B], func(either.Either[E, A]) either.Either[E, B]],
ma)
}
func Flatten[E, A any](mma IOEither[E, IOEither[E, A]]) IOEither[E, A] {
return G.Flatten(mma)
return MonadChain(mma, function.Identity[IOEither[E, A]])
}
func TryCatch[E, A any](f func() (A, error), onThrow func(error) E) IOEither[E, A] {
return G.TryCatch[IOEither[E, A]](f, onThrow)
return func() either.Either[E, A] {
a, err := f()
return either.TryCatch(a, err, onThrow)
}
}
func TryCatchError[A any](f func() (A, error)) IOEither[error, A] {
return G.TryCatchError[IOEither[error, A]](f)
return func() either.Either[error, A] {
return either.TryCatchError(f())
}
}
func Memoize[E, A any](ma IOEither[E, A]) IOEither[E, A] {
return G.Memoize(ma)
return io.Memoize(ma)
}
func MonadMapLeft[E1, E2, A any](fa IOEither[E1, A], f func(E1) E2) IOEither[E2, A] {
return G.MonadMapLeft[IOEither[E1, A], IOEither[E2, A]](fa, f)
return eithert.MonadMapLeft(
io.MonadMap[either.Either[E1, A], either.Either[E2, A]],
fa,
f,
)
}
func MapLeft[A, E1, E2 any](f func(E1) E2) func(IOEither[E1, A]) IOEither[E2, A] {
return G.MapLeft[IOEither[E1, A], IOEither[E2, A]](f)
return eithert.MapLeft(
io.Map[either.Either[E1, A], either.Either[E2, A]],
f,
)
}
func MonadBiMap[E1, E2, A, B any](fa IOEither[E1, A], f func(E1) E2, g func(A) B) IOEither[E2, B] {
return G.MonadBiMap[IOEither[E1, A], IOEither[E2, B]](fa, f, g)
return eithert.MonadBiMap(io.MonadMap[either.Either[E1, A], either.Either[E2, B]], fa, f, g)
}
// BiMap maps a pair of functions over the two type arguments of the bifunctor.
func BiMap[E1, E2, A, B any](f func(E1) E2, g func(A) B) func(IOEither[E1, A]) IOEither[E2, B] {
return G.BiMap[IOEither[E1, A], IOEither[E2, B]](f, g)
return eithert.BiMap(io.Map[either.Either[E1, A], either.Either[E2, B]], f, g)
}
// Fold converts an IOEither into an IO
func Fold[E, A, B any](onLeft func(E) I.IO[B], onRight func(A) I.IO[B]) func(IOEither[E, A]) I.IO[B] {
return G.Fold[IOEither[E, A]](onLeft, onRight)
func Fold[E, A, B any](onLeft func(E) io.IO[B], onRight func(A) io.IO[B]) func(IOEither[E, A]) io.IO[B] {
return eithert.MatchE(io.MonadChain[either.Either[E, A], B], onLeft, onRight)
}
// GetOrElse extracts the value or maps the error
func GetOrElse[E, A any](onLeft func(E) I.IO[A]) func(IOEither[E, A]) I.IO[A] {
return G.GetOrElse[IOEither[E, A]](onLeft)
func GetOrElse[E, A any](onLeft func(E) io.IO[A]) func(IOEither[E, A]) io.IO[A] {
return eithert.GetOrElse(io.MonadChain[either.Either[E, A], A], io.MonadOf[A], onLeft)
}
// MonadChainTo composes to the second monad ignoring the return value of the first
func MonadChainTo[A, E, B any](fa IOEither[E, A], fb IOEither[E, B]) IOEither[E, B] {
return G.MonadChainTo(fa, fb)
return MonadChain(fa, function.Constant1[A](fb))
}
// ChainTo composes to the second [IOEither] monad ignoring the return value of the first
func ChainTo[A, E, B any](fb IOEither[E, B]) func(IOEither[E, A]) IOEither[E, B] {
return G.ChainTo[IOEither[E, A]](fb)
func ChainTo[A, E, B any](fb IOEither[E, B]) Mapper[E, A, B] {
return Chain(function.Constant1[A](fb))
}
// MonadChainFirst runs the [IOEither] monad returned by the function but returns the result of the original monad
func MonadChainFirst[E, A, B any](ma IOEither[E, A], f func(A) IOEither[E, B]) IOEither[E, A] {
return G.MonadChainFirst(ma, f)
return chain.MonadChainFirst(
MonadChain[E, A, A],
MonadMap[E, B, A],
ma,
f,
)
}
// ChainFirst runs the [IOEither] monad returned by the function but returns the result of the original monad
func ChainFirst[E, A, B any](f func(A) IOEither[E, B]) func(IOEither[E, A]) IOEither[E, A] {
return G.ChainFirst[IOEither[E, A]](f)
func ChainFirst[E, A, B any](f func(A) IOEither[E, B]) Mapper[E, A, A] {
return chain.ChainFirst(
Chain[E, A, A],
Map[E, B, A],
f,
)
}
func MonadChainFirstEitherK[A, E, B any](ma IOEither[E, A], f func(A) ET.Either[E, B]) IOEither[E, A] {
return G.MonadChainFirstEitherK[IOEither[E, A]](ma, f)
func MonadChainFirstEitherK[A, E, B any](ma IOEither[E, A], f func(A) either.Either[E, B]) IOEither[E, A] {
return fromeither.MonadChainFirstEitherK(
MonadChain[E, A, A],
MonadMap[E, B, A],
FromEither[E, B],
ma,
f,
)
}
func ChainFirstEitherK[A, E, B any](f func(A) ET.Either[E, B]) func(ma IOEither[E, A]) IOEither[E, A] {
return G.ChainFirstEitherK[IOEither[E, A]](f)
func ChainFirstEitherK[A, E, B any](f func(A) either.Either[E, B]) Mapper[E, A, A] {
return fromeither.ChainFirstEitherK(
Chain[E, A, A],
Map[E, B, A],
FromEither[E, B],
f,
)
}
// MonadChainFirstIOK runs [IO] the monad returned by the function but returns the result of the original monad
func MonadChainFirstIOK[E, A, B any](ma IOEither[E, A], f func(A) I.IO[B]) IOEither[E, A] {
return G.MonadChainFirstIOK(ma, f)
func MonadChainFirstIOK[E, A, B any](ma IOEither[E, A], f func(A) io.IO[B]) IOEither[E, A] {
return fromio.MonadChainFirstIOK(
MonadChain[E, A, A],
MonadMap[E, B, A],
FromIO[E, B],
ma,
f,
)
}
// ChainFirstIOK runs the [IO] monad returned by the function but returns the result of the original monad
func ChainFirstIOK[E, A, B any](f func(A) I.IO[B]) func(IOEither[E, A]) IOEither[E, A] {
return G.ChainFirstIOK[IOEither[E, A]](f)
func ChainFirstIOK[E, A, B any](f func(A) io.IO[B]) func(IOEither[E, A]) IOEither[E, A] {
return fromio.ChainFirstIOK(
Chain[E, A, A],
Map[E, B, A],
FromIO[E, B],
f,
)
}
func MonadFold[E, A, B any](ma IOEither[E, A], onLeft func(E) io.IO[B], onRight func(A) io.IO[B]) io.IO[B] {
return eithert.FoldE(io.MonadChain[either.Either[E, A], B], ma, onLeft, onRight)
}
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
func WithResource[A, E, R, ANY any](onCreate IOEither[E, R], onRelease func(R) IOEither[E, ANY]) func(func(R) IOEither[E, A]) IOEither[E, A] {
return G.WithResource[IOEither[E, A]](onCreate, onRelease)
return file.WithResource(
MonadChain[E, R, A],
MonadFold[E, A, either.Either[E, A]],
MonadFold[E, ANY, either.Either[E, A]],
MonadMap[E, ANY, A],
Left[A, E],
)(function.Constant(onCreate), onRelease)
}
// Swap changes the order of type parameters
func Swap[E, A any](val IOEither[E, A]) IOEither[A, E] {
return G.Swap[IOEither[E, A], IOEither[A, E]](val)
return MonadFold(val, Right[A, E], Left[E, A])
}
// FromImpure converts a side effect without a return value into a side effect that returns any
func FromImpure[E any](f func()) IOEither[E, any] {
return G.FromImpure[IOEither[E, any]](f)
return function.Pipe2(
f,
io.FromImpure,
FromIO[E, any],
)
}
// Defer creates an IO by creating a brand new IO via a generator function, each time
func Defer[E, A any](gen L.Lazy[IOEither[E, A]]) IOEither[E, A] {
return G.Defer[IOEither[E, A]](gen)
func Defer[E, A any](gen lazy.Lazy[IOEither[E, A]]) IOEither[E, A] {
return io.Defer(gen)
}
// MonadAlt identifies an associative operation on a type constructor
func MonadAlt[E, A any](first IOEither[E, A], second L.Lazy[IOEither[E, A]]) IOEither[E, A] {
return G.MonadAlt(first, second)
func MonadAlt[E, A any](first IOEither[E, A], second lazy.Lazy[IOEither[E, A]]) IOEither[E, A] {
return eithert.MonadAlt(
io.Of[either.Either[E, A]],
io.MonadChain[either.Either[E, A], either.Either[E, A]],
first,
second,
)
}
// Alt identifies an associative operation on a type constructor
func Alt[E, A any](second L.Lazy[IOEither[E, A]]) func(IOEither[E, A]) IOEither[E, A] {
return G.Alt(second)
func Alt[E, A any](second lazy.Lazy[IOEither[E, A]]) Mapper[E, A, A] {
return function.Bind2nd(MonadAlt[E, A], second)
}
func MonadFlap[E, B, A any](fab IOEither[E, func(A) B], a A) IOEither[E, B] {
return G.MonadFlap[IOEither[E, func(A) B], IOEither[E, B]](fab, a)
return functor.MonadFlap(MonadMap[E, func(A) B, B], fab, a)
}
func Flap[E, B, A any](a A) func(IOEither[E, func(A) B]) IOEither[E, B] {
return G.Flap[IOEither[E, func(A) B], IOEither[E, B]](a)
func Flap[E, B, A any](a A) Mapper[E, func(A) B, B] {
return functor.Flap(Map[E, func(A) B, B], a)
}
// ToIOOption converts an [IOEither] to an [IOO.IOOption]
func ToIOOption[E, A any](ioe IOEither[E, A]) IOO.IOOption[A] {
return G.ToIOOption[IOO.IOOption[A]](ioe)
return function.Pipe1(
ioe,
io.Map(either.ToOption[E, A]),
)
}
// Delay creates an operation that passes in the value after some delay
func Delay[E, A any](delay time.Duration) func(IOEither[E, A]) IOEither[E, A] {
return G.Delay[IOEither[E, A]](delay)
func Delay[E, A any](delay time.Duration) Mapper[E, A, A] {
return io.Delay[either.Either[E, A]](delay)
}
// After creates an operation that passes after the given [time.Time]
func After[E, A any](timestamp time.Time) func(IOEither[E, A]) IOEither[E, A] {
return G.After[IOEither[E, A]](timestamp)
func After[E, A any](timestamp time.Time) Mapper[E, A, A] {
return io.After[either.Either[E, A]](timestamp)
}

View File

@@ -16,19 +16,28 @@
package ioeither
import (
G "github.com/IBM/fp-go/v2/ioeither/generic"
)
"encoding/json"
"log"
// LogJson converts the argument to pretty printed JSON and then logs it via the format string
// Can be used with [ChainFirst]
//
// Deprecated: use [LogJSON] instead
func LogJson[A any](prefix string) func(A) IOEither[error, any] {
return G.LogJson[IOEither[error, any], A](prefix)
}
"github.com/IBM/fp-go/v2/bytes"
"github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/function"
)
// LogJSON converts the argument to pretty printed JSON and then logs it via the format string
// Can be used with [ChainFirst]
func LogJSON[A any](prefix string) func(A) IOEither[error, any] {
return G.LogJSON[IOEither[error, any], A](prefix)
return func(a A) IOEither[error, any] {
// log this
return function.Pipe3(
either.TryCatchError(json.MarshalIndent(a, "", " ")),
either.Map[error](bytes.ToString),
FromEither[error, string],
Chain(func(data string) IOEither[error, any] {
return FromImpure[error](func() {
log.Printf(prefix, data)
})
}),
)
}
}

View File

@@ -19,20 +19,51 @@ 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"
G "github.com/IBM/fp-go/v2/ioeither/generic"
)
// Pointed returns the pointed operations for [IOEither]
type (
ioEitherPointed[E, A any] struct{}
ioEitherMonad[E, A, B any] struct{}
ioEitherFunctor[E, A, B any] struct{}
)
func (o *ioEitherPointed[E, A]) Of(a A) IOEither[E, A] {
return Of[E, A](a)
}
func (o *ioEitherMonad[E, A, B]) Of(a A) IOEither[E, A] {
return Of[E, A](a)
}
func (o *ioEitherMonad[E, A, B]) Map(f func(A) B) Mapper[E, A, B] {
return Map[E, A, B](f)
}
func (o *ioEitherMonad[E, A, B]) Chain(f func(A) IOEither[E, B]) Mapper[E, A, B] {
return Chain[E, A, B](f)
}
func (o *ioEitherMonad[E, A, B]) Ap(fa IOEither[E, A]) Mapper[E, func(A) B, B] {
return Ap[B, E, A](fa)
}
func (o *ioEitherFunctor[E, A, B]) Map(f func(A) B) Mapper[E, A, B] {
return Map[E, A, B](f)
}
// Pointed implements the pointed operations for [IOEither]
func Pointed[E, A any]() pointed.Pointed[A, IOEither[E, A]] {
return G.Pointed[E, A, IOEither[E, A]]()
return &ioEitherPointed[E, A]{}
}
// Functor returns the functor operations for [IOEither]
// Functor implements the monadic operations for [IOEither]
func Functor[E, A, B any]() functor.Functor[A, B, IOEither[E, A], IOEither[E, B]] {
return G.Functor[E, A, B, IOEither[E, A], IOEither[E, B]]()
return &ioEitherFunctor[E, A, B]{}
}
// Monad returns the monadic operations for [IOEither]
// Monad implements the monadic operations for [IOEither]
func Monad[E, A, B any]() monad.Monad[A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]] {
return G.Monad[E, A, B, IOEither[E, A], IOEither[E, B], IOEither[E, func(A) B]]()
return &ioEitherMonad[E, A, B]{}
}

View File

@@ -16,27 +16,45 @@
package ioeither
import (
G "github.com/IBM/fp-go/v2/ioeither/generic"
M "github.com/IBM/fp-go/v2/monoid"
"github.com/IBM/fp-go/v2/monoid"
)
type (
Monoid[E, A any] = monoid.Monoid[IOEither[E, A]]
)
// ApplicativeMonoid returns a [Monoid] that concatenates [IOEither] instances via their applicative
func ApplicativeMonoid[E, A any](
m M.Monoid[A],
) M.Monoid[IOEither[E, A]] {
return G.ApplicativeMonoid[IOEither[E, A], IOEither[E, func(A) A]](m)
m monoid.Monoid[A],
) Monoid[E, A] {
return monoid.ApplicativeMonoid(
MonadOf[E, A],
MonadMap[E, A, func(A) A],
MonadAp[A, E, A],
m,
)
}
// ApplicativeMonoid returns a [Monoid] that concatenates [IOEither] instances via their applicative
func ApplicativeMonoidSeq[E, A any](
m M.Monoid[A],
) M.Monoid[IOEither[E, A]] {
return G.ApplicativeMonoidSeq[IOEither[E, A], IOEither[E, func(A) A]](m)
m monoid.Monoid[A],
) Monoid[E, A] {
return monoid.ApplicativeMonoid(
MonadOf[E, A],
MonadMap[E, A, func(A) A],
MonadApSeq[A, E, A],
m,
)
}
// ApplicativeMonoid returns a [Monoid] that concatenates [IOEither] instances via their applicative
func ApplicativeMonoidPar[E, A any](
m M.Monoid[A],
) M.Monoid[IOEither[E, A]] {
return G.ApplicativeMonoid[IOEither[E, A], IOEither[E, func(A) A]](m)
m monoid.Monoid[A],
) Monoid[E, A] {
return monoid.ApplicativeMonoid(
MonadOf[E, A],
MonadMap[E, A, func(A) A],
MonadApPar[A, E, A],
m,
)
}

View File

@@ -16,11 +16,16 @@
package ioeither
import (
G "github.com/IBM/fp-go/v2/ioeither/generic"
S "github.com/IBM/fp-go/v2/semigroup"
"github.com/IBM/fp-go/v2/semigroup"
)
type (
Semigroup[E, A any] = semigroup.Semigroup[IOEither[E, A]]
)
// AltSemigroup is a [Semigroup] that tries the first item and then the second one using an alternative
func AltSemigroup[E, A any]() S.Semigroup[IOEither[E, A]] {
return G.AltSemigroup[IOEither[E, A]]()
func AltSemigroup[E, A any]() semigroup.Semigroup[IOEither[E, A]] {
return semigroup.AltSemigroup(
MonadAlt[E, A],
)
}

View File

@@ -18,11 +18,11 @@ package ioeither
import (
"context"
IO "github.com/IBM/fp-go/v2/io"
G "github.com/IBM/fp-go/v2/ioeither/generic"
"github.com/IBM/fp-go/v2/either"
"github.com/IBM/fp-go/v2/io"
)
// WithLock executes the provided IO operation in the scope of a lock
func WithLock[E, A any](lock IO.IO[context.CancelFunc]) func(fa IOEither[E, A]) IOEither[E, A] {
return G.WithLock[IOEither[E, A]](lock)
func WithLock[E, A any](lock io.IO[context.CancelFunc]) func(fa IOEither[E, A]) IOEither[E, A] {
return io.WithLock[either.Either[E, A]](lock)
}

View File

@@ -26,33 +26,33 @@ import (
// MakeReader creates a reader, i.e. a method that accepts a context and that returns a value
//
//go:deprecate
// Deprecated:
func MakeReader[GA ~func(R) A, R, A any](r GA) GA {
return r
}
// Ask reads the current context
//
//go:deprecate
// Deprecated:
func Ask[GR ~func(R) R, R any]() GR {
return MakeReader(F.Identity[R])
}
// Asks projects a value from the global context in a Reader
//
//go:deprecate
// Deprecated:
func Asks[GA ~func(R) A, R, A any](f GA) GA {
return MakeReader(f)
}
//go:deprecate
// Deprecated:
func AsksReader[GA ~func(R) A, R, A any](f func(R) GA) GA {
return MakeReader(func(r R) A {
return f(r)(r)
})
}
//go:deprecate
// Deprecated:
func MonadMap[GA ~func(E) A, GB ~func(E) B, E, A, B any](fa GA, f func(A) B) GB {
return MakeReader(F.Flow2(fa, f))
}
@@ -60,12 +60,12 @@ func MonadMap[GA ~func(E) A, GB ~func(E) B, E, A, B any](fa GA, f func(A) B) GB
// Map can be used to turn functions `func(A)B` into functions `(fa F[A])F[B]` whose argument and return types
// use the type constructor `F` to represent some computational context.
//
//go:deprecate
// Deprecated:
func Map[GA ~func(E) A, GB ~func(E) B, E, A, B any](f func(A) B) func(GA) GB {
return F.Bind2nd(MonadMap[GA, GB, E, A, B], f)
}
//go:deprecate
// Deprecated:
func MonadAp[GA ~func(R) A, GB ~func(R) B, GAB ~func(R) func(A) B, R, A, B any](fab GAB, fa GA) GB {
return MakeReader(func(r R) B {
return fab(r)(fa(r))
@@ -74,17 +74,17 @@ func MonadAp[GA ~func(R) A, GB ~func(R) B, GAB ~func(R) func(A) B, R, A, B any](
// Ap applies a function to an argument under a type constructor.
//
//go:deprecate
// Deprecated:
func Ap[GA ~func(R) A, GB ~func(R) B, GAB ~func(R) func(A) B, R, A, B any](fa GA) func(GAB) GB {
return F.Bind2nd(MonadAp[GA, GB, GAB, R, A, B], fa)
}
//go:deprecate
// Deprecated:
func Of[GA ~func(R) A, R, A any](a A) GA {
return F.Constant1[R](a)
}
//go:deprecate
// Deprecated:
func MonadChain[GA ~func(R) A, GB ~func(R) B, R, A, B any](ma GA, f func(A) GB) GB {
return MakeReader(func(r R) B {
return f(ma(r))(r)
@@ -93,38 +93,38 @@ func MonadChain[GA ~func(R) A, GB ~func(R) B, R, A, B any](ma GA, f func(A) GB)
// Chain composes computations in sequence, using the return value of one computation to determine the next computation.
//
//go:deprecate
// Deprecated:
func Chain[GA ~func(R) A, GB ~func(R) B, R, A, B any](f func(A) GB) func(GA) GB {
return F.Bind2nd(MonadChain[GA, GB, R, A, B], f)
}
//go:deprecate
// Deprecated:
func Flatten[GA ~func(R) A, GGA ~func(R) GA, R, A any](mma GGA) GA {
return MonadChain(mma, F.Identity[GA])
}
//go:deprecate
// Deprecated:
func Compose[AB ~func(A) B, BC ~func(B) C, AC ~func(A) C, A, B, C any](ab AB) func(BC) AC {
return func(bc BC) AC {
return F.Flow2(ab, bc)
}
}
//go:deprecate
// Deprecated:
func First[GAB ~func(A) B, GABC ~func(T.Tuple2[A, C]) T.Tuple2[B, C], A, B, C any](pab GAB) GABC {
return MakeReader(func(tac T.Tuple2[A, C]) T.Tuple2[B, C] {
return T.MakeTuple2(pab(tac.F1), tac.F2)
})
}
//go:deprecate
// Deprecated:
func Second[GBC ~func(B) C, GABC ~func(T.Tuple2[A, B]) T.Tuple2[A, C], A, B, C any](pbc GBC) GABC {
return MakeReader(func(tab T.Tuple2[A, B]) T.Tuple2[A, C] {
return T.MakeTuple2(tab.F1, pbc(tab.F2))
})
}
//go:deprecate
// Deprecated:
func Promap[GA ~func(E) A, GB ~func(D) B, E, A, D, B any](f func(D) E, g func(A) B) func(GA) GB {
return func(fea GA) GB {
return MakeReader(F.Flow3(f, fea, g))
@@ -134,7 +134,7 @@ func Promap[GA ~func(E) A, GB ~func(D) B, E, A, D, B any](f func(D) E, g func(A)
// Local changes the value of the local context during the execution of the action `ma` (similar to `Contravariant`'s
// `contramap`).
//
//go:deprecate
// Deprecated:
func Local[GA1 ~func(R1) A, GA2 ~func(R2) A, R2, R1, A any](f func(R2) R1) func(GA1) GA2 {
return func(r1 GA1) GA2 {
return F.Flow2(f, r1)
@@ -143,17 +143,17 @@ func Local[GA1 ~func(R1) A, GA2 ~func(R2) A, R2, R1, A any](f func(R2) R1) func(
// Read applies a context to a reader to obtain its value
//
//go:deprecate
// Deprecated:
func Read[GA ~func(E) A, E, A any](e E) func(GA) A {
return I.Ap[GA](e)
}
//go:deprecate
// Deprecated:
func MonadFlap[GAB ~func(R) func(A) B, GB ~func(R) B, R, A, B any](fab GAB, a A) GB {
return FC.MonadFlap(MonadMap[GAB, GB], fab, a)
}
//go:deprecate
// Deprecated:
func Flap[GAB ~func(R) func(A) B, GB ~func(R) B, R, A, B any](a A) func(GAB) GB {
return FC.Flap(Map[GAB, GB], a)
}

View File

@@ -28,7 +28,7 @@ type Reader[R, A any] = func(R) A
// MakeReader creates a reader, i.e. a method that accepts a context and that returns a value
//
//go:deprecate
// Deprecated:
func MakeReader[R, A any](r Reader[R, A]) Reader[R, A] {
return r
}