mirror of
https://github.com/IBM/fp-go.git
synced 2025-11-23 22:14:53 +02:00
105 lines
3.4 KiB
Go
105 lines
3.4 KiB
Go
// Copyright (c) 2023 - 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 readerresult
|
|
|
|
import (
|
|
M "github.com/IBM/fp-go/v2/monoid"
|
|
)
|
|
|
|
// AlternativeMonoid creates a Monoid for ReaderResult that combines both Alternative and Applicative behavior.
|
|
// It uses the provided monoid for the success values and falls back to alternative computations on failure.
|
|
//
|
|
// The empty element is Of(m.Empty()), and concat tries the first computation, falling back to the second
|
|
// if it fails, then combines successful values using the underlying monoid.
|
|
//
|
|
// Example:
|
|
//
|
|
// intAdd := monoid.MakeMonoid(0, func(a, b int) int { return a + b })
|
|
// rrMonoid := readerresult.AlternativeMonoid[Config](intAdd)
|
|
//
|
|
// rr1 := readerresult.Of[Config](5)
|
|
// rr2 := readerresult.Of[Config](3)
|
|
// combined := rrMonoid.Concat(rr1, rr2)
|
|
// // combined(cfg) returns result.Of(8)
|
|
//
|
|
//go:inline
|
|
func AlternativeMonoid[R, A any](m M.Monoid[A]) Monoid[R, A] {
|
|
return M.AlternativeMonoid(
|
|
Of[R, A],
|
|
MonadMap[R, A, func(A) A],
|
|
MonadAp[A, R, A],
|
|
MonadAlt[R, A],
|
|
m,
|
|
)
|
|
}
|
|
|
|
// AltMonoid creates a Monoid for ReaderResult based on the Alternative pattern.
|
|
// The empty element is the provided zero computation, and concat tries the first computation,
|
|
// falling back to the second if it fails.
|
|
//
|
|
// This is useful for combining computations where you want to try alternatives until one succeeds.
|
|
//
|
|
// Example:
|
|
//
|
|
// zero := func() readerresult.ReaderResult[Config, User] {
|
|
// return readerresult.Left[Config, User](errors.New("no user"))
|
|
// }
|
|
// userMonoid := readerresult.AltMonoid[Config](zero)
|
|
//
|
|
// primary := getPrimaryUser()
|
|
// backup := getBackupUser()
|
|
// combined := userMonoid.Concat(primary, backup)
|
|
// // Tries primary, falls back to backup if primary fails
|
|
//
|
|
//go:inline
|
|
func AltMonoid[R, A any](zero Lazy[ReaderResult[R, A]]) Monoid[R, A] {
|
|
return M.AltMonoid(
|
|
zero,
|
|
MonadAlt[R, A],
|
|
)
|
|
}
|
|
|
|
// ApplicativeMonoid creates a Monoid for ReaderResult based on Applicative functor composition.
|
|
// The empty element is Of(m.Empty()), and concat combines two computations using the underlying monoid.
|
|
// Both computations must succeed for the result to succeed.
|
|
//
|
|
// This is useful for accumulating results from multiple independent computations.
|
|
//
|
|
// Example:
|
|
//
|
|
// intAdd := monoid.MakeMonoid(0, func(a, b int) int { return a + b })
|
|
// rrMonoid := readerresult.ApplicativeMonoid[Config](intAdd)
|
|
//
|
|
// rr1 := readerresult.Of[Config](5)
|
|
// rr2 := readerresult.Of[Config](3)
|
|
// combined := rrMonoid.Concat(rr1, rr2)
|
|
// // combined(cfg) returns result.Of(8)
|
|
//
|
|
// // If either fails, the whole computation fails
|
|
// rr3 := readerresult.Left[Config, int](errors.New("error"))
|
|
// failed := rrMonoid.Concat(rr1, rr3)
|
|
// // failed(cfg) returns result.Left[int](error)
|
|
//
|
|
//go:inline
|
|
func ApplicativeMonoid[R, A any](m M.Monoid[A]) Monoid[R, A] {
|
|
return M.ApplicativeMonoid(
|
|
Of[R, A],
|
|
MonadMap[R, A, func(A) A],
|
|
MonadAp[A, R, A],
|
|
m,
|
|
)
|
|
}
|