mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-23 22:14:53 +02:00
310 lines
11 KiB
Go
310 lines
11 KiB
Go
// Copyright (c) 2024 - 2025 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 statereaderioresult
|
|
|
|
import (
|
|
"context"
|
|
|
|
RIORES "github.com/IBM/fp-go/v2/context/readerioresult"
|
|
"github.com/IBM/fp-go/v2/function"
|
|
"github.com/IBM/fp-go/v2/internal/statet"
|
|
RIOR "github.com/IBM/fp-go/v2/readerioresult"
|
|
"github.com/IBM/fp-go/v2/result"
|
|
)
|
|
|
|
// Left creates a StateReaderIOResult that represents a failed computation with the given error.
|
|
// The error value is immediately available and does not depend on state or context.
|
|
//
|
|
// Example:
|
|
//
|
|
// result := statereaderioresult.Left[AppState, string](errors.New("validation failed"))
|
|
// // Returns a failed computation that ignores state and context
|
|
func Left[S, A any](e error) StateReaderIOResult[S, A] {
|
|
return function.Constant1[S](RIORES.Left[Pair[S, A]](e))
|
|
}
|
|
|
|
// Right creates a StateReaderIOResult that represents a successful computation with the given value.
|
|
// The value is wrapped and the state is passed through unchanged.
|
|
//
|
|
// Example:
|
|
//
|
|
// result := statereaderioresult.Right[AppState](42)
|
|
// // Returns a successful computation containing 42
|
|
func Right[S, A any](a A) StateReaderIOResult[S, A] {
|
|
return statet.Of[StateReaderIOResult[S, A]](RIORES.Of[Pair[S, A]], a)
|
|
}
|
|
|
|
// Of creates a StateReaderIOResult that represents a successful computation with the given value.
|
|
// This is the monadic return/pure operation for StateReaderIOResult.
|
|
// Equivalent to [Right].
|
|
//
|
|
// Example:
|
|
//
|
|
// result := statereaderioresult.Of[AppState](42)
|
|
// // Returns a successful computation containing 42
|
|
func Of[S, A any](a A) StateReaderIOResult[S, A] {
|
|
return Right[S](a)
|
|
}
|
|
|
|
// MonadMap transforms the success value of a StateReaderIOResult using the provided function.
|
|
// If the computation fails, the error is propagated unchanged.
|
|
// The state is threaded through the computation.
|
|
// This is the functor map operation.
|
|
//
|
|
// Example:
|
|
//
|
|
// result := statereaderioresult.MonadMap(
|
|
// statereaderioresult.Of[AppState](21),
|
|
// func(x int) int { return x * 2 },
|
|
// ) // Result contains 42
|
|
func MonadMap[S, A, B any](fa StateReaderIOResult[S, A], f func(A) B) StateReaderIOResult[S, B] {
|
|
return statet.MonadMap[StateReaderIOResult[S, A], StateReaderIOResult[S, B]](
|
|
RIORES.MonadMap[Pair[S, A], Pair[S, B]],
|
|
fa,
|
|
f,
|
|
)
|
|
}
|
|
|
|
// Map is the curried version of [MonadMap].
|
|
// Returns a function that transforms a StateReaderIOResult.
|
|
//
|
|
// Example:
|
|
//
|
|
// double := statereaderioresult.Map[AppState](func(x int) int { return x * 2 })
|
|
// result := function.Pipe1(statereaderioresult.Of[AppState](21), double)
|
|
func Map[S, A, B any](f func(A) B) Operator[S, A, B] {
|
|
return statet.Map[StateReaderIOResult[S, A], StateReaderIOResult[S, B]](
|
|
RIORES.Map[Pair[S, A], Pair[S, B]],
|
|
f,
|
|
)
|
|
}
|
|
|
|
// MonadChain sequences two computations, passing the result of the first to a function
|
|
// that produces the second computation. This is the monadic bind operation.
|
|
// The state is threaded through both computations.
|
|
//
|
|
// Example:
|
|
//
|
|
// result := statereaderioresult.MonadChain(
|
|
// statereaderioresult.Of[AppState](5),
|
|
// func(x int) statereaderioresult.StateReaderIOResult[AppState, string] {
|
|
// return statereaderioresult.Of[AppState](fmt.Sprintf("value: %d", x))
|
|
// },
|
|
// )
|
|
func MonadChain[S, A, B any](fa StateReaderIOResult[S, A], f Kleisli[S, A, B]) StateReaderIOResult[S, B] {
|
|
return statet.MonadChain(
|
|
RIORES.MonadChain[Pair[S, A], Pair[S, B]],
|
|
fa,
|
|
f,
|
|
)
|
|
}
|
|
|
|
// Chain is the curried version of [MonadChain].
|
|
// Returns a function that sequences computations.
|
|
//
|
|
// Example:
|
|
//
|
|
// stringify := statereaderioresult.Chain[AppState](func(x int) statereaderioresult.StateReaderIOResult[AppState, string] {
|
|
// return statereaderioresult.Of[AppState](fmt.Sprintf("%d", x))
|
|
// })
|
|
// result := function.Pipe1(statereaderioresult.Of[AppState](42), stringify)
|
|
func Chain[S, A, B any](f Kleisli[S, A, B]) Operator[S, A, B] {
|
|
return statet.Chain[StateReaderIOResult[S, A]](
|
|
RIORES.Chain[Pair[S, A], Pair[S, B]],
|
|
f,
|
|
)
|
|
}
|
|
|
|
// MonadAp applies a function wrapped in a StateReaderIOResult to a value wrapped in a StateReaderIOResult.
|
|
// If either the function or the value fails, the error is propagated.
|
|
// The state is threaded through both computations sequentially.
|
|
// This is the applicative apply operation.
|
|
//
|
|
// Example:
|
|
//
|
|
// fab := statereaderioresult.Of[AppState](func(x int) int { return x * 2 })
|
|
// fa := statereaderioresult.Of[AppState](21)
|
|
// result := statereaderioresult.MonadAp(fab, fa) // Result contains 42
|
|
func MonadAp[B, S, A any](fab StateReaderIOResult[S, func(A) B], fa StateReaderIOResult[S, A]) StateReaderIOResult[S, B] {
|
|
return statet.MonadAp[StateReaderIOResult[S, A], StateReaderIOResult[S, B]](
|
|
RIORES.MonadMap[Pair[S, A], Pair[S, B]],
|
|
RIORES.MonadChain[Pair[S, func(A) B], Pair[S, B]],
|
|
fab,
|
|
fa,
|
|
)
|
|
}
|
|
|
|
// Ap is the curried version of [MonadAp].
|
|
// Returns a function that applies a wrapped function to the given wrapped value.
|
|
func Ap[B, S, A any](fa StateReaderIOResult[S, A]) Operator[S, func(A) B, B] {
|
|
return statet.Ap[StateReaderIOResult[S, A], StateReaderIOResult[S, B], StateReaderIOResult[S, func(A) B]](
|
|
RIORES.Map[Pair[S, A], Pair[S, B]],
|
|
RIORES.Chain[Pair[S, func(A) B], Pair[S, B]],
|
|
fa,
|
|
)
|
|
}
|
|
|
|
// FromReaderIOResult lifts a ReaderIOResult into a StateReaderIOResult.
|
|
// The state is passed through unchanged.
|
|
//
|
|
// Example:
|
|
//
|
|
// riores := readerioresult.Of(42)
|
|
// result := statereaderioresult.FromReaderIOResult[AppState](riores)
|
|
func FromReaderIOResult[S, A any](fa ReaderIOResult[A]) StateReaderIOResult[S, A] {
|
|
return statet.FromF[StateReaderIOResult[S, A]](
|
|
RIORES.MonadMap[A],
|
|
fa,
|
|
)
|
|
}
|
|
|
|
// FromIOResult lifts an IOResult into a StateReaderIOResult.
|
|
// The state is passed through unchanged and the context is ignored.
|
|
func FromIOResult[S, A any](fa IOResult[A]) StateReaderIOResult[S, A] {
|
|
return FromReaderIOResult[S](RIORES.FromIOResult(fa))
|
|
}
|
|
|
|
// FromState lifts a State computation into a StateReaderIOResult.
|
|
// The computation cannot fail (uses the error type).
|
|
func FromState[S, A any](sa State[S, A]) StateReaderIOResult[S, A] {
|
|
return statet.FromState[StateReaderIOResult[S, A]](RIORES.Of[Pair[S, A]], sa)
|
|
}
|
|
|
|
// FromIO lifts an IO computation into a StateReaderIOResult.
|
|
// The state is passed through unchanged and the context is ignored.
|
|
func FromIO[S, A any](fa IO[A]) StateReaderIOResult[S, A] {
|
|
return FromReaderIOResult[S](RIORES.FromIO(fa))
|
|
}
|
|
|
|
// FromResult lifts a Result into a StateReaderIOResult.
|
|
// The state is passed through unchanged and the context is ignored.
|
|
//
|
|
// Example:
|
|
//
|
|
// result := statereaderioresult.FromResult[AppState](result.Of(42))
|
|
func FromResult[S, A any](ma Result[A]) StateReaderIOResult[S, A] {
|
|
return result.Fold(Left[S, A], Right[S, A])(ma)
|
|
}
|
|
|
|
// Combinators
|
|
|
|
// Local runs a computation with a modified context.
|
|
// The function f transforms the context before passing it to the computation.
|
|
//
|
|
// Example:
|
|
//
|
|
// // Modify context before running computation
|
|
// withTimeout := statereaderioresult.Local[AppState](
|
|
// func(ctx context.Context) context.Context {
|
|
// ctx, _ = context.WithTimeout(ctx, 60*time.Second)
|
|
// return ctx
|
|
// }
|
|
// )
|
|
// result := withTimeout(computation)
|
|
func Local[S, A any](f func(context.Context) context.Context) func(StateReaderIOResult[S, A]) StateReaderIOResult[S, A] {
|
|
return func(ma StateReaderIOResult[S, A]) StateReaderIOResult[S, A] {
|
|
return function.Flow2(ma, RIOR.Local[Pair[S, A]](f))
|
|
}
|
|
}
|
|
|
|
// Asks creates a computation that derives a value from the context.
|
|
// The function receives the context and returns a StateReaderIOResult.
|
|
//
|
|
// Example:
|
|
//
|
|
// getValue := statereaderioresult.Asks[AppState, string](
|
|
// func(ctx context.Context) statereaderioresult.StateReaderIOResult[AppState, string] {
|
|
// return statereaderioresult.Of[AppState](ctx.Value("key").(string))
|
|
// },
|
|
// )
|
|
func Asks[S, A any](f func(context.Context) StateReaderIOResult[S, A]) StateReaderIOResult[S, A] {
|
|
return func(s S) ReaderIOResult[Pair[S, A]] {
|
|
return func(ctx context.Context) IOResult[Pair[S, A]] {
|
|
return f(ctx)(s)(ctx)
|
|
}
|
|
}
|
|
}
|
|
|
|
// FromResultK lifts a Result-returning function into a Kleisli arrow for StateReaderIOResult.
|
|
//
|
|
// Example:
|
|
//
|
|
// validate := func(x int) result.Result[int] {
|
|
// if x > 0 { return result.Of(x) }
|
|
// return result.Error[int](errors.New("negative"))
|
|
// }
|
|
// kleisli := statereaderioresult.FromResultK[AppState](validate)
|
|
func FromResultK[S, A, B any](f func(A) Result[B]) Kleisli[S, A, B] {
|
|
return function.Flow2(
|
|
f,
|
|
FromResult[S, B],
|
|
)
|
|
}
|
|
|
|
// FromIOK lifts an IO-returning function into a Kleisli arrow for StateReaderIOResult.
|
|
func FromIOK[S, A, B any](f func(A) IO[B]) Kleisli[S, A, B] {
|
|
return function.Flow2(
|
|
f,
|
|
FromIO[S, B],
|
|
)
|
|
}
|
|
|
|
// FromIOResultK lifts an IOResult-returning function into a Kleisli arrow for StateReaderIOResult.
|
|
func FromIOResultK[S, A, B any](f func(A) IOResult[B]) Kleisli[S, A, B] {
|
|
return function.Flow2(
|
|
f,
|
|
FromIOResult[S, B],
|
|
)
|
|
}
|
|
|
|
// FromReaderIOResultK lifts a ReaderIOResult-returning function into a Kleisli arrow for StateReaderIOResult.
|
|
func FromReaderIOResultK[S, A, B any](f func(A) ReaderIOResult[B]) Kleisli[S, A, B] {
|
|
return function.Flow2(
|
|
f,
|
|
FromReaderIOResult[S, B],
|
|
)
|
|
}
|
|
|
|
// MonadChainReaderIOResultK chains a StateReaderIOResult with a ReaderIOResult-returning function.
|
|
func MonadChainReaderIOResultK[S, A, B any](ma StateReaderIOResult[S, A], f func(A) ReaderIOResult[B]) StateReaderIOResult[S, B] {
|
|
return MonadChain(ma, FromReaderIOResultK[S](f))
|
|
}
|
|
|
|
// ChainReaderIOResultK is the curried version of [MonadChainReaderIOResultK].
|
|
func ChainReaderIOResultK[S, A, B any](f func(A) ReaderIOResult[B]) Operator[S, A, B] {
|
|
return Chain(FromReaderIOResultK[S](f))
|
|
}
|
|
|
|
// MonadChainIOResultK chains a StateReaderIOResult with an IOResult-returning function.
|
|
func MonadChainIOResultK[S, A, B any](ma StateReaderIOResult[S, A], f func(A) IOResult[B]) StateReaderIOResult[S, B] {
|
|
return MonadChain(ma, FromIOResultK[S](f))
|
|
}
|
|
|
|
// ChainIOResultK is the curried version of [MonadChainIOResultK].
|
|
func ChainIOResultK[S, A, B any](f func(A) IOResult[B]) Operator[S, A, B] {
|
|
return Chain(FromIOResultK[S](f))
|
|
}
|
|
|
|
// MonadChainResultK chains a StateReaderIOResult with a Result-returning function.
|
|
func MonadChainResultK[S, A, B any](ma StateReaderIOResult[S, A], f func(A) Result[B]) StateReaderIOResult[S, B] {
|
|
return MonadChain(ma, FromResultK[S](f))
|
|
}
|
|
|
|
// ChainResultK is the curried version of [MonadChainResultK].
|
|
func ChainResultK[S, A, B any](f func(A) Result[B]) Operator[S, A, B] {
|
|
return Chain(FromResultK[S](f))
|
|
}
|