mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-23 22:14:53 +02:00
fix: bind docs
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -21,14 +21,56 @@ import (
|
||||
F "github.com/IBM/fp-go/v2/internal/functor"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// X int
|
||||
// Y int
|
||||
// }
|
||||
// result := generic.Do[[]State, State](State{})
|
||||
func Do[GS ~[]S, S any](
|
||||
empty S,
|
||||
) GS {
|
||||
return Of[GS](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
// For arrays, this produces the cartesian product where later steps can use values from earlier steps.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// X int
|
||||
// Y int
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// generic.Do[[]State, State](State{}),
|
||||
// generic.Bind[[]State, []State, []int, State, State, int](
|
||||
// func(x int) func(State) State {
|
||||
// return func(s State) State { s.X = x; return s }
|
||||
// },
|
||||
// func(s State) []int {
|
||||
// return []int{1, 2, 3}
|
||||
// },
|
||||
// ),
|
||||
// generic.Bind[[]State, []State, []int, State, State, int](
|
||||
// func(y int) func(State) State {
|
||||
// return func(s State) State { s.Y = y; return s }
|
||||
// },
|
||||
// func(s State) []int {
|
||||
// // This can access s.X from the previous step
|
||||
// return []int{s.X * 10, s.X * 20}
|
||||
// },
|
||||
// ),
|
||||
// ) // Produces: {1,10}, {1,20}, {2,20}, {2,40}, {3,30}, {3,60}
|
||||
func Bind[GS1 ~[]S1, GS2 ~[]S2, GT ~[]T, S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) GT,
|
||||
|
||||
@@ -21,14 +21,63 @@ import (
|
||||
G "github.com/IBM/fp-go/v2/readereither/generic"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// UserID string
|
||||
// TenantID string
|
||||
// }
|
||||
// result := readereither.Do(State{})
|
||||
func Do[S any](
|
||||
empty S,
|
||||
) ReaderEither[S] {
|
||||
return G.Do[ReaderEither[S], context.Context, error, S](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps
|
||||
// and access the context.Context from the environment.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// UserID string
|
||||
// TenantID string
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// readereither.Do(State{}),
|
||||
// readereither.Bind(
|
||||
// func(uid string) func(State) State {
|
||||
// return func(s State) State { s.UserID = uid; return s }
|
||||
// },
|
||||
// func(s State) readereither.ReaderEither[string] {
|
||||
// return func(ctx context.Context) either.Either[error, string] {
|
||||
// if uid, ok := ctx.Value("userID").(string); ok {
|
||||
// return either.Right[error](uid)
|
||||
// }
|
||||
// return either.Left[string](errors.New("no userID"))
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// readereither.Bind(
|
||||
// func(tid string) func(State) State {
|
||||
// return func(s State) State { s.TenantID = tid; return s }
|
||||
// },
|
||||
// func(s State) readereither.ReaderEither[string] {
|
||||
// // This can access s.UserID from the previous step
|
||||
// return func(ctx context.Context) either.Either[error, string] {
|
||||
// return either.Right[error]("tenant-" + s.UserID)
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) ReaderEither[T],
|
||||
|
||||
@@ -21,14 +21,64 @@ import (
|
||||
"github.com/IBM/fp-go/v2/internal/functor"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Config Config
|
||||
// }
|
||||
// result := readerioeither.Do(State{})
|
||||
func Do[S any](
|
||||
empty S,
|
||||
) ReaderIOEither[S] {
|
||||
return Of(empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps
|
||||
// and access the context.Context from the environment.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Config Config
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// readerioeither.Do(State{}),
|
||||
// readerioeither.Bind(
|
||||
// func(user User) func(State) State {
|
||||
// return func(s State) State { s.User = user; return s }
|
||||
// },
|
||||
// func(s State) readerioeither.ReaderIOEither[User] {
|
||||
// return func(ctx context.Context) ioeither.IOEither[error, User] {
|
||||
// return ioeither.TryCatch(func() (User, error) {
|
||||
// return fetchUser(ctx)
|
||||
// })
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// readerioeither.Bind(
|
||||
// func(cfg Config) func(State) State {
|
||||
// return func(s State) State { s.Config = cfg; return s }
|
||||
// },
|
||||
// func(s State) readerioeither.ReaderIOEither[Config] {
|
||||
// // This can access s.User from the previous step
|
||||
// return func(ctx context.Context) ioeither.IOEither[error, Config] {
|
||||
// return ioeither.TryCatch(func() (Config, error) {
|
||||
// return fetchConfigForUser(ctx, s.User.ID)
|
||||
// })
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) ReaderIOEither[T],
|
||||
|
||||
@@ -21,14 +21,55 @@ import (
|
||||
F "github.com/IBM/fp-go/v2/internal/functor"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// X int
|
||||
// Y int
|
||||
// }
|
||||
// result := identity.Do(State{})
|
||||
func Do[S any](
|
||||
empty S,
|
||||
) S {
|
||||
return empty
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// X int
|
||||
// Y int
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// identity.Do(State{}),
|
||||
// identity.Bind(
|
||||
// func(x int) func(State) State {
|
||||
// return func(s State) State { s.X = x; return s }
|
||||
// },
|
||||
// func(s State) int {
|
||||
// return 42
|
||||
// },
|
||||
// ),
|
||||
// identity.Bind(
|
||||
// func(y int) func(State) State {
|
||||
// return func(s State) State { s.Y = y; return s }
|
||||
// },
|
||||
// func(s State) int {
|
||||
// // This can access s.X from the previous step
|
||||
// return s.X * 2
|
||||
// },
|
||||
// ),
|
||||
// ) // State{X: 42, Y: 84}
|
||||
func Bind[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) T,
|
||||
|
||||
@@ -21,14 +21,59 @@ import (
|
||||
"github.com/IBM/fp-go/v2/internal/functor"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Posts []Post
|
||||
// }
|
||||
// result := ioeither.Do[error](State{})
|
||||
func Do[E, S any](
|
||||
empty S,
|
||||
) IOEither[E, S] {
|
||||
return Of[E](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Posts []Post
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// ioeither.Do[error](State{}),
|
||||
// ioeither.Bind(
|
||||
// func(user User) func(State) State {
|
||||
// return func(s State) State { s.User = user; return s }
|
||||
// },
|
||||
// func(s State) ioeither.IOEither[error, User] {
|
||||
// return ioeither.TryCatch(func() (User, error) {
|
||||
// return fetchUser()
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// ioeither.Bind(
|
||||
// func(posts []Post) func(State) State {
|
||||
// return func(s State) State { s.Posts = posts; return s }
|
||||
// },
|
||||
// func(s State) ioeither.IOEither[error, []Post] {
|
||||
// // This can access s.User from the previous step
|
||||
// return ioeither.TryCatch(func() ([]Post, error) {
|
||||
// return fetchPostsForUser(s.User.ID)
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[E, S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) IOEither[E, T],
|
||||
|
||||
@@ -21,14 +21,55 @@ import (
|
||||
"github.com/IBM/fp-go/v2/internal/functor"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Name string
|
||||
// Age int
|
||||
// }
|
||||
// result := iooption.Do(State{})
|
||||
func Do[S any](
|
||||
empty S,
|
||||
) IOOption[S] {
|
||||
return Of(empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Name string
|
||||
// Age int
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// iooption.Do(State{}),
|
||||
// iooption.Bind(
|
||||
// func(name string) func(State) State {
|
||||
// return func(s State) State { s.Name = name; return s }
|
||||
// },
|
||||
// func(s State) iooption.IOOption[string] {
|
||||
// return iooption.FromIO(io.Of("Alice"))
|
||||
// },
|
||||
// ),
|
||||
// iooption.Bind(
|
||||
// func(age int) func(State) State {
|
||||
// return func(s State) State { s.Age = age; return s }
|
||||
// },
|
||||
// func(s State) iooption.IOOption[int] {
|
||||
// // This can access s.Name from the previous step
|
||||
// return iooption.FromIO(io.Of(len(s.Name) * 10))
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) IOOption[T],
|
||||
|
||||
@@ -19,14 +19,56 @@ import (
|
||||
G "github.com/IBM/fp-go/v2/iterator/stateless/generic"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// X int
|
||||
// Y int
|
||||
// }
|
||||
// result := stateless.Do(State{})
|
||||
func Do[S any](
|
||||
empty S,
|
||||
) Iterator[S] {
|
||||
return G.Do[Iterator[S]](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
// For iterators, this produces the cartesian product of all values.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// X int
|
||||
// Y int
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// stateless.Do(State{}),
|
||||
// stateless.Bind(
|
||||
// func(x int) func(State) State {
|
||||
// return func(s State) State { s.X = x; return s }
|
||||
// },
|
||||
// func(s State) stateless.Iterator[int] {
|
||||
// return stateless.Of(1, 2, 3)
|
||||
// },
|
||||
// ),
|
||||
// stateless.Bind(
|
||||
// func(y int) func(State) State {
|
||||
// return func(s State) State { s.Y = y; return s }
|
||||
// },
|
||||
// func(s State) stateless.Iterator[int] {
|
||||
// // This can access s.X from the previous step
|
||||
// return stateless.Of(s.X * 10, s.X * 20)
|
||||
// },
|
||||
// ),
|
||||
// ) // Produces: {1,10}, {1,20}, {2,20}, {2,40}, {3,30}, {3,60}
|
||||
func Bind[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) Iterator[T],
|
||||
|
||||
@@ -23,14 +23,56 @@ import (
|
||||
P "github.com/IBM/fp-go/v2/pair"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// X int
|
||||
// Y int
|
||||
// }
|
||||
// result := generic.Do[Iterator[State]](State{})
|
||||
func Do[GS ~func() O.Option[P.Pair[GS, S]], S any](
|
||||
empty S,
|
||||
) GS {
|
||||
return Of[GS](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
// For iterators, this produces the cartesian product where later steps can use values from earlier steps.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// X int
|
||||
// Y int
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// generic.Do[Iterator[State]](State{}),
|
||||
// generic.Bind[Iterator[State], Iterator[State], Iterator[int], State, State, int](
|
||||
// func(x int) func(State) State {
|
||||
// return func(s State) State { s.X = x; return s }
|
||||
// },
|
||||
// func(s State) Iterator[int] {
|
||||
// return generic.Of[Iterator[int]](1, 2, 3)
|
||||
// },
|
||||
// ),
|
||||
// generic.Bind[Iterator[State], Iterator[State], Iterator[int], State, State, int](
|
||||
// func(y int) func(State) State {
|
||||
// return func(s State) State { s.Y = y; return s }
|
||||
// },
|
||||
// func(s State) Iterator[int] {
|
||||
// // This can access s.X from the previous step
|
||||
// return generic.Of[Iterator[int]](s.X * 10, s.X * 20)
|
||||
// },
|
||||
// ),
|
||||
// ) // Produces: {1,10}, {1,20}, {2,20}, {2,40}, {3,30}, {3,60}
|
||||
func Bind[GS1 ~func() O.Option[P.Pair[GS1, S1]], GS2 ~func() O.Option[P.Pair[GS2, S2]], GA ~func() O.Option[P.Pair[GA, A]], S1, S2, A any](
|
||||
setter func(A) func(S1) S2,
|
||||
f func(S1) GA,
|
||||
|
||||
@@ -19,14 +19,55 @@ import (
|
||||
"github.com/IBM/fp-go/v2/io"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Config Config
|
||||
// Data Data
|
||||
// }
|
||||
// result := lazy.Do(State{})
|
||||
func Do[S any](
|
||||
empty S,
|
||||
) Lazy[S] {
|
||||
return io.Do(empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Config Config
|
||||
// Data Data
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// lazy.Do(State{}),
|
||||
// lazy.Bind(
|
||||
// func(cfg Config) func(State) State {
|
||||
// return func(s State) State { s.Config = cfg; return s }
|
||||
// },
|
||||
// func(s State) lazy.Lazy[Config] {
|
||||
// return lazy.MakeLazy(func() Config { return loadConfig() })
|
||||
// },
|
||||
// ),
|
||||
// lazy.Bind(
|
||||
// func(data Data) func(State) State {
|
||||
// return func(s State) State { s.Data = data; return s }
|
||||
// },
|
||||
// func(s State) lazy.Lazy[Data] {
|
||||
// // This can access s.Config from the previous step
|
||||
// return lazy.MakeLazy(func() Data { return loadData(s.Config) })
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) Lazy[T],
|
||||
|
||||
@@ -19,14 +19,68 @@ import (
|
||||
G "github.com/IBM/fp-go/v2/readereither/generic"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Config Config
|
||||
// }
|
||||
// type Env struct {
|
||||
// UserService UserService
|
||||
// ConfigService ConfigService
|
||||
// }
|
||||
// result := readereither.Do[Env, error](State{})
|
||||
func Do[R, E, S any](
|
||||
empty S,
|
||||
) ReaderEither[R, E, S] {
|
||||
return G.Do[ReaderEither[R, E, S], R, E, S](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps
|
||||
// and access the shared environment.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Config Config
|
||||
// }
|
||||
// type Env struct {
|
||||
// UserService UserService
|
||||
// ConfigService ConfigService
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// readereither.Do[Env, error](State{}),
|
||||
// readereither.Bind(
|
||||
// func(user User) func(State) State {
|
||||
// return func(s State) State { s.User = user; return s }
|
||||
// },
|
||||
// func(s State) readereither.ReaderEither[Env, error, User] {
|
||||
// return readereither.Asks(func(env Env) either.Either[error, User] {
|
||||
// return env.UserService.GetUser()
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// readereither.Bind(
|
||||
// func(cfg Config) func(State) State {
|
||||
// return func(s State) State { s.Config = cfg; return s }
|
||||
// },
|
||||
// func(s State) readereither.ReaderEither[Env, error, Config] {
|
||||
// // This can access s.User from the previous step
|
||||
// return readereither.Asks(func(env Env) either.Either[error, Config] {
|
||||
// return env.ConfigService.GetConfigForUser(s.User.ID)
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[R, E, S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) ReaderEither[R, E, T],
|
||||
|
||||
@@ -22,14 +22,68 @@ import (
|
||||
F "github.com/IBM/fp-go/v2/internal/functor"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Config Config
|
||||
// User User
|
||||
// }
|
||||
// type Env struct {
|
||||
// ConfigService ConfigService
|
||||
// UserService UserService
|
||||
// }
|
||||
// result := generic.Do[ReaderEither[Env, error, State], Env, error, State](State{})
|
||||
func Do[GS ~func(R) ET.Either[E, S], R, E, S any](
|
||||
empty S,
|
||||
) GS {
|
||||
return Of[GS, E, R, S](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps
|
||||
// and access the shared environment.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Config Config
|
||||
// User User
|
||||
// }
|
||||
// type Env struct {
|
||||
// ConfigService ConfigService
|
||||
// UserService UserService
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// generic.Do[ReaderEither[Env, error, State], Env, error, State](State{}),
|
||||
// generic.Bind[ReaderEither[Env, error, State], ReaderEither[Env, error, State], ReaderEither[Env, error, Config], Env, error, State, State, Config](
|
||||
// func(cfg Config) func(State) State {
|
||||
// return func(s State) State { s.Config = cfg; return s }
|
||||
// },
|
||||
// func(s State) ReaderEither[Env, error, Config] {
|
||||
// return func(env Env) either.Either[error, Config] {
|
||||
// return env.ConfigService.Load()
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// generic.Bind[ReaderEither[Env, error, State], ReaderEither[Env, error, State], ReaderEither[Env, error, User], Env, error, State, State, User](
|
||||
// func(user User) func(State) State {
|
||||
// return func(s State) State { s.User = user; return s }
|
||||
// },
|
||||
// func(s State) ReaderEither[Env, error, User] {
|
||||
// // This can access s.Config from the previous step
|
||||
// return func(env Env) either.Either[error, User] {
|
||||
// return env.UserService.GetUserForConfig(s.Config)
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[GS1 ~func(R) ET.Either[E, S1], GS2 ~func(R) ET.Either[E, S2], GT ~func(R) ET.Either[E, T], R, E, S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) GT,
|
||||
|
||||
@@ -21,14 +21,68 @@ import (
|
||||
"github.com/IBM/fp-go/v2/internal/functor"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Host string
|
||||
// Port int
|
||||
// }
|
||||
// type Config struct {
|
||||
// DefaultHost string
|
||||
// DefaultPort int
|
||||
// }
|
||||
// result := readerio.Do[Config](State{})
|
||||
func Do[R, S any](
|
||||
empty S,
|
||||
) ReaderIO[R, S] {
|
||||
return Of[R](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps
|
||||
// and access the shared environment.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Host string
|
||||
// Port int
|
||||
// }
|
||||
// type Config struct {
|
||||
// DefaultHost string
|
||||
// DefaultPort int
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// readerio.Do[Config](State{}),
|
||||
// readerio.Bind(
|
||||
// func(host string) func(State) State {
|
||||
// return func(s State) State { s.Host = host; return s }
|
||||
// },
|
||||
// func(s State) readerio.ReaderIO[Config, string] {
|
||||
// return readerio.Asks(func(c Config) io.IO[string] {
|
||||
// return io.Of(c.DefaultHost)
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// readerio.Bind(
|
||||
// func(port int) func(State) State {
|
||||
// return func(s State) State { s.Port = port; return s }
|
||||
// },
|
||||
// func(s State) readerio.ReaderIO[Config, int] {
|
||||
// // This can access s.Host from the previous step
|
||||
// return readerio.Asks(func(c Config) io.IO[int] {
|
||||
// return io.Of(c.DefaultPort)
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[R, S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) ReaderIO[R, T],
|
||||
|
||||
@@ -20,14 +20,68 @@ import (
|
||||
G "github.com/IBM/fp-go/v2/readerioeither/generic"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Posts []Post
|
||||
// }
|
||||
// type Env struct {
|
||||
// UserRepo UserRepository
|
||||
// PostRepo PostRepository
|
||||
// }
|
||||
// result := readerioeither.Do[Env, error](State{})
|
||||
func Do[R, E, S any](
|
||||
empty S,
|
||||
) ReaderIOEither[R, E, S] {
|
||||
return G.Do[ReaderIOEither[R, E, S], IOE.IOEither[E, S], R, E, S](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps
|
||||
// and access the shared environment.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Posts []Post
|
||||
// }
|
||||
// type Env struct {
|
||||
// UserRepo UserRepository
|
||||
// PostRepo PostRepository
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// readerioeither.Do[Env, error](State{}),
|
||||
// readerioeither.Bind(
|
||||
// func(user User) func(State) State {
|
||||
// return func(s State) State { s.User = user; return s }
|
||||
// },
|
||||
// func(s State) readerioeither.ReaderIOEither[Env, error, User] {
|
||||
// return readerioeither.Asks(func(env Env) ioeither.IOEither[error, User] {
|
||||
// return env.UserRepo.FindUser()
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// readerioeither.Bind(
|
||||
// func(posts []Post) func(State) State {
|
||||
// return func(s State) State { s.Posts = posts; return s }
|
||||
// },
|
||||
// func(s State) readerioeither.ReaderIOEither[Env, error, []Post] {
|
||||
// // This can access s.User from the previous step
|
||||
// return readerioeither.Asks(func(env Env) ioeither.IOEither[error, []Post] {
|
||||
// return env.PostRepo.FindPostsByUser(s.User.ID)
|
||||
// })
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[R, E, S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) ReaderIOEither[R, E, T],
|
||||
|
||||
@@ -22,14 +22,68 @@ import (
|
||||
F "github.com/IBM/fp-go/v2/internal/functor"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Config Config
|
||||
// }
|
||||
// type Env struct {
|
||||
// UserRepo UserRepository
|
||||
// ConfigRepo ConfigRepository
|
||||
// }
|
||||
// result := generic.Do[ReaderIOEither[Env, error, State], IOEither[error, State], Env, error, State](State{})
|
||||
func Do[GRS ~func(R) GS, GS ~func() either.Either[E, S], R, E, S any](
|
||||
empty S,
|
||||
) GRS {
|
||||
return Of[GRS, GS, R, E, S](empty)
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps
|
||||
// and access the shared environment.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// User User
|
||||
// Config Config
|
||||
// }
|
||||
// type Env struct {
|
||||
// UserRepo UserRepository
|
||||
// ConfigRepo ConfigRepository
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// generic.Do[ReaderIOEither[Env, error, State], IOEither[error, State], Env, error, State](State{}),
|
||||
// generic.Bind[ReaderIOEither[Env, error, State], ReaderIOEither[Env, error, State], ReaderIOEither[Env, error, User], IOEither[error, State], IOEither[error, State], IOEither[error, User], Env, error, State, State, User](
|
||||
// func(user User) func(State) State {
|
||||
// return func(s State) State { s.User = user; return s }
|
||||
// },
|
||||
// func(s State) ReaderIOEither[Env, error, User] {
|
||||
// return func(env Env) ioeither.IOEither[error, User] {
|
||||
// return env.UserRepo.FindUser()
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// generic.Bind[ReaderIOEither[Env, error, State], ReaderIOEither[Env, error, State], ReaderIOEither[Env, error, Config], IOEither[error, State], IOEither[error, State], IOEither[error, Config], Env, error, State, State, Config](
|
||||
// func(cfg Config) func(State) State {
|
||||
// return func(s State) State { s.Config = cfg; return s }
|
||||
// },
|
||||
// func(s State) ReaderIOEither[Env, error, Config] {
|
||||
// // This can access s.User from the previous step
|
||||
// return func(env Env) ioeither.IOEither[error, Config] {
|
||||
// return env.ConfigRepo.LoadConfigForUser(s.User.ID)
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[GRS1 ~func(R) GS1, GRS2 ~func(R) GS2, GRT ~func(R) GT, GS1 ~func() either.Either[E, S1], GS2 ~func() either.Either[E, S2], GT ~func() either.Either[E, T], R, E, S1, S2, T any](
|
||||
setter func(T) func(S1) S2,
|
||||
f func(S1) GRT,
|
||||
|
||||
@@ -20,12 +20,54 @@ import (
|
||||
G "github.com/IBM/fp-go/v2/record/generic"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Name string
|
||||
// Count int
|
||||
// }
|
||||
// result := record.Do[string, State]()
|
||||
func Do[K comparable, S any]() map[K]S {
|
||||
return G.Do[map[K]S, K, S]()
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
// For records, this merges values by key.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Name string
|
||||
// Count int
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// record.Do[string, State](),
|
||||
// record.Bind(monoid.Record[string, State]())(
|
||||
// func(name string) func(State) State {
|
||||
// return func(s State) State { s.Name = name; return s }
|
||||
// },
|
||||
// func(s State) map[string]string {
|
||||
// return map[string]string{"a": "Alice", "b": "Bob"}
|
||||
// },
|
||||
// ),
|
||||
// record.Bind(monoid.Record[string, State]())(
|
||||
// func(count int) func(State) State {
|
||||
// return func(s State) State { s.Count = count; return s }
|
||||
// },
|
||||
// func(s State) map[string]int {
|
||||
// // This can access s.Name from the previous step
|
||||
// return map[string]int{"a": len(s.Name), "b": len(s.Name) * 2}
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[S1, T any, K comparable, S2 any](m Mo.Monoid[map[K]S2]) func(setter func(T) func(S1) S2, f func(S1) map[K]T) func(map[K]S1) map[K]S2 {
|
||||
return G.Bind[map[K]S1, map[K]S2, map[K]T, K, S1, S2, T](m)
|
||||
}
|
||||
|
||||
@@ -22,12 +22,58 @@ import (
|
||||
Mo "github.com/IBM/fp-go/v2/monoid"
|
||||
)
|
||||
|
||||
// Bind creates an empty context of type [S] to be used with the [Bind] operation
|
||||
// Do creates an empty context of type [S] to be used with the [Bind] operation.
|
||||
// This is the starting point for do-notation style composition.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Name string
|
||||
// Count int
|
||||
// }
|
||||
// result := generic.Do[map[string]State, string, State]()
|
||||
func Do[GS ~map[K]S, K comparable, S any]() GS {
|
||||
return Empty[GS, K, S]()
|
||||
}
|
||||
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2]
|
||||
// Bind attaches the result of a computation to a context [S1] to produce a context [S2].
|
||||
// This enables sequential composition where each step can depend on the results of previous steps.
|
||||
// For records, this merges values by key where later steps can use values from earlier steps.
|
||||
//
|
||||
// The setter function takes the result of the computation and returns a function that
|
||||
// updates the context from S1 to S2.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// type State struct {
|
||||
// Name string
|
||||
// Count int
|
||||
// }
|
||||
//
|
||||
// result := F.Pipe2(
|
||||
// generic.Do[map[string]State, string, State](),
|
||||
// generic.Bind[map[string]State, map[string]State, map[string]string, string, State, State, string](
|
||||
// monoid.Record[string, State](),
|
||||
// )(
|
||||
// func(name string) func(State) State {
|
||||
// return func(s State) State { s.Name = name; return s }
|
||||
// },
|
||||
// func(s State) map[string]string {
|
||||
// return map[string]string{"a": "Alice", "b": "Bob"}
|
||||
// },
|
||||
// ),
|
||||
// generic.Bind[map[string]State, map[string]State, map[string]int, string, State, State, int](
|
||||
// monoid.Record[string, State](),
|
||||
// )(
|
||||
// func(count int) func(State) State {
|
||||
// return func(s State) State { s.Count = count; return s }
|
||||
// },
|
||||
// func(s State) map[string]int {
|
||||
// // This can access s.Name from the previous step
|
||||
// return map[string]int{"a": len(s.Name), "b": len(s.Name) * 2}
|
||||
// },
|
||||
// ),
|
||||
// )
|
||||
func Bind[GS1 ~map[K]S1, GS2 ~map[K]S2, GT ~map[K]T, K comparable, S1, S2, T any](m Mo.Monoid[GS2]) func(setter func(T) func(S1) S2, f func(S1) GT) func(GS1) GS2 {
|
||||
c := Chain[GS1, GS2, K, S1, S2](m)
|
||||
return func(setter func(T) func(S1) S2, f func(S1) GT) func(GS1) GS2 {
|
||||
|
||||
Reference in New Issue
Block a user