Skip to main content
Version: v2.2.82 (latest)
v2 · Utilities

Semigroup Combining Values

A semigroup is a type with an associative binary operation that combines two values of the same type.


Overview

A Semigroup is an algebraic structure consisting of a set and an associative binary operation. The key property is associativity: (a • b) • c = a • (b • c).

Key Properties:

  • Associative: Order of operations doesn't matter
  • Closed: Combining two values produces another value of the same type
  • Type-safe: Enforced through Go's type system

Basic Usage

semigroup_basic.go
import S "github.com/IBM/fp-go/semigroup"

// Create a string concatenation semigroup
stringSemigroup := S.MakeSemigroup(func(a, b string) string {
  return a + b
})

result := stringSemigroup.Concat("Hello", " World")
// "Hello World"

// Associativity holds
s1 := stringSemigroup.Concat(
  stringSemigroup.Concat("a", "b"),
  "c",
)
s2 := stringSemigroup.Concat(
  "a",
  stringSemigroup.Concat("b", "c"),
)
// s1 == s2 == "abc"

Built-in Semigroups

fp-go provides several built-in semigroups for common types:

semigroup_builtin.go
import (
  N "github.com/IBM/fp-go/number"
  S "github.com/IBM/fp-go/string"
)

// Number addition semigroup
sum := N.SemigroupSum.Concat(1, 2)  // 3

// Number multiplication semigroup
product := N.SemigroupProduct.Concat(3, 4)  // 12

// String concatenation semigroup
text := S.Semigroup.Concat("Hello", " World")  // "Hello World"

// Min/Max semigroups
min := N.SemigroupMin.Concat(5, 3)  // 3
max := N.SemigroupMax.Concat(5, 3)  // 5

Custom Semigroups

Create semigroups for your own types:

semigroup_custom.go
type Config struct {
  Timeout int
  Retries int
  Debug   bool
}

// Last-wins merge strategy
configSemigroup := S.MakeSemigroup(func(a, b Config) Config {
  return Config{
      Timeout: b.Timeout,
      Retries: b.Retries,
      Debug:   b.Debug,
  }
})

defaults := Config{Timeout: 30, Retries: 3, Debug: false}
userConfig := Config{Timeout: 60, Retries: 5, Debug: true}

merged := configSemigroup.Concat(defaults, userConfig)
// Config{Timeout: 60, Retries: 5, Debug: true}

// Field-wise merge strategy
fieldwiseSemigroup := S.MakeSemigroup(func(a, b Config) Config {
  return Config{
      Timeout: max(a.Timeout, b.Timeout),
      Retries: max(a.Retries, b.Retries),
      Debug:   a.Debug || b.Debug,
  }
})

Combining Multiple Values

Use semigroups to combine multiple values:

semigroup_multiple.go
import (
  A "github.com/IBM/fp-go/array"
  S "github.com/IBM/fp-go/semigroup"
)

// Combine array of strings
stringSemigroup := S.MakeSemigroup(func(a, b string) string {
  return a + b
})

words := []string{"Hello", " ", "functional", " ", "world"}
result := A.Reduce(
  func(acc, word string) string {
      return stringSemigroup.Concat(acc, word)
  },
  "",
)(words)
// "Hello functional world"

// Combine array of numbers
numbers := []int{1, 2, 3, 4, 5}
sum := A.Reduce(
  func(acc, n int) int {
      return N.SemigroupSum.Concat(acc, n)
  },
  0,
)(numbers)
// 15

API Reference

FunctionTypeDescription
MakeSemigroup[A](func(A, A) A) -> Semigroup[A]Creates a semigroup from a binary operation
Concat(A, A) -> ACombines two values associatively

Built-in Semigroups:

SemigroupPackageOperation
SemigroupSumnumberAddition
SemigroupProductnumberMultiplication
SemigroupMinnumberMinimum
SemigroupMaxnumberMaximum
SemigroupstringConcatenation

Related Concepts

Algebraic Hierarchy:

  • MagmaSemigroupMonoidGroup
  • Semigroup adds associativity to Magma
  • Monoid adds identity element to Semigroup

See Also:

  • Monoid - Semigroup with identity element
  • Magma - Binary operation without associativity requirement