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

Magma

Binary operations without constraints. The most basic algebraic structure - just a way to combine two values.


Core API

FunctionSignatureDescription
MakeMagmafunc MakeMagma[A any](func(A, A) A) Magma[A]Create magma from function

Usage Examples

Basic Usage

basic.go
import Mg "github.com/IBM/fp-go/v2/magma"

// Create magma for averaging
avgMagma := Mg.MakeMagma(func(a, b float64) float64 {
  return (a + b) / 2
})

result := avgMagma.Concat(10, 20)
// 15.0

Conflict Resolution Strategies

strategies.go
// Last-wins strategy
lastWins := Mg.MakeMagma(func(a, b T) T {
  return b
})

// First-wins strategy
firstWins := Mg.MakeMagma(func(a, b T) T {
  return a
})

// Max strategy
maxMagma := Mg.MakeMagma(func(a, b int) int {
  if a > b { return a }
  return b
})

// Min strategy
minMagma := Mg.MakeMagma(func(a, b int) int {
  if a < b { return a }
  return b
})

Custom Merging

merge.go
type User struct {
  ID        int
  Name      string
  UpdatedAt time.Time
}

// Merge users (keep most recent)
userMagma := Mg.MakeMagma(func(a, b User) User {
  if a.UpdatedAt.After(b.UpdatedAt) {
      return a
  }
  return b
})

merged := userMagma.Concat(oldUser, newUser)
// Returns the user with the later UpdatedAt

Array Merging

arrays.go
// Concatenate arrays
appendMagma := Mg.MakeMagma(func(a, b []int) []int {
  return append(a, b...)
})

result := appendMagma.Concat([]int{1, 2}, []int{3, 4})
// []int{1, 2, 3, 4}

// Union (deduplicate)
unionMagma := Mg.MakeMagma(func(a, b []int) []int {
  seen := make(map[int]bool)
  result := make([]int, 0)
  
  for _, v := range append(a, b...) {
      if !seen[v] {
          seen[v] = true
          result = append(result, v)
      }
  }
  return result
})

Record Conversion

record.go
import R "github.com/IBM/fp-go/v2/record"

// Use with FromArray for duplicate key handling
entries := []T.Tuple2[string, int]{
  T.MakeTuple2("a", 1),
  T.MakeTuple2("b", 2),
  T.MakeTuple2("a", 10),  // Duplicate
}

// Sum duplicates
sumMagma := Mg.MakeMagma(func(x, y int) int { return x + y })
m := R.FromArray(sumMagma)(entries)
// map[string]int{"a": 11, "b": 2}

Common Patterns

Configuration Merging

config.go
type Config struct {
  Host    string
  Port    int
  Timeout int
}

// Merge configs (right wins for non-zero values)
configMagma := Mg.MakeMagma(func(a, b Config) Config {
  return Config{
      Host:    if b.Host != "" { b.Host } else { a.Host },
      Port:    if b.Port != 0 { b.Port } else { a.Port },
      Timeout: if b.Timeout != 0 { b.Timeout } else { a.Timeout },
  }
})

Magma vs Semigroup: Magma doesn't require associativity. Use Magma when the order of operations matters (like averaging), and Semigroup when it doesn't (like addition).

Use Cases: Magma is perfect for:

  • Conflict resolution strategies
  • Custom merge logic
  • Non-associative operations
  • Building blocks for more complex structures