1
0
mirror of https://github.com/IBM/fp-go.git synced 2025-11-23 22:14:53 +02:00
Files
fp-go/v2/readerresult/monoid.go
Dr. Carsten Leue 4909ad5473 fix: add missing monoid
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
2025-11-21 10:22:50 +01:00

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,
)
}