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

Tuple Pairs & Groups

Tuples provide a way to group multiple values together. The tuple package provides utilities for creating and manipulating tuples.


Overview

A Tuple is a fixed-size collection of values that can have different types. The most common is Tuple2 (also called a pair), which holds two values.

Key Features:

  • Type-safe grouping of values
  • Immutable by design
  • Useful for function returns and data pairing
  • Supports mapping and transformation operations

Creating Tuples

tuple_create.go
import T "github.com/IBM/fp-go/tuple"

// Create a tuple (pair)
pair := T.MakeTuple2("Alice", 30)
// Tuple2[string, int]{Head: "Alice", Tail: 30}

// Access elements
name := pair.Head   // "Alice" (first element)
age := pair.Tail    // 30 (second element)

// Different types
mixed := T.MakeTuple2(42, "answer")
// Tuple2[int, string]{Head: 42, Tail: "answer"}

// Nested tuples
nested := T.MakeTuple2(
  T.MakeTuple2(1, 2),
  T.MakeTuple2(3, 4),
)
// Tuple2[Tuple2[int, int], Tuple2[int, int]]

Mapping First Element

Transform the first element of a tuple:

tuple_mapfst.go
import T "github.com/IBM/fp-go/tuple"

pair := T.MakeTuple2(5, "hello")

// Map first element (Head)
result := T.MapFst(func(n int) int {
  return n * 2
})(pair)
// Tuple2{Head: 10, Tail: "hello"}

// Chain transformations
result := T.MapFst(func(n int) string {
  return fmt.Sprintf("Number: %d", n)
})(pair)
// Tuple2{Head: "Number: 5", Tail: "hello"}

Mapping Second Element

Transform the second element of a tuple:

tuple_mapsnd.go
import T "github.com/IBM/fp-go/tuple"

pair := T.MakeTuple2("hello", 10)

// Map second element (Tail)
result := T.MapSnd(func(n int) int {
  return n * 2
})(pair)
// Tuple2{Head: "hello", Tail: 20}

// Change type
result := T.MapSnd(func(n int) string {
  return fmt.Sprintf("%d items", n)
})(pair)
// Tuple2{Head: "hello", Tail: "10 items"}

Mapping Both Elements

Transform both elements simultaneously:

tuple_bimap.go
import T "github.com/IBM/fp-go/tuple"

pair := T.MakeTuple2(5, 10)

// Map both elements
result := T.Bimap(
  func(a int) int { return a * 2 },
  func(b int) int { return b + 1 },
)(pair)
// Tuple2{Head: 10, Tail: 11}

// Change both types
result := T.Bimap(
  func(a int) string { return fmt.Sprintf("A=%d", a) },
  func(b int) bool { return b > 5 },
)(pair)
// Tuple2{Head: "A=5", Tail: true}

Swapping Elements

Reverse the order of tuple elements:

tuple_swap.go
import T "github.com/IBM/fp-go/tuple"

pair := T.MakeTuple2("hello", 42)
// Tuple2[string, int]{Head: "hello", Tail: 42}

swapped := T.Swap(pair)
// Tuple2[int, string]{Head: 42, Tail: "hello"}

// Swap is its own inverse
original := T.Swap(swapped)
// Back to Tuple2[string, int]{Head: "hello", Tail: 42}

Function Results

Return multiple values as tuples:

tuple_results.go
import T "github.com/IBM/fp-go/tuple"

// Return quotient and remainder
func divMod(a, b int) T.Tuple2[int, int] {
  return T.MakeTuple2(a/b, a%b)
}

result := divMod(17, 5)
quotient := result.Head   // 3
remainder := result.Tail  // 2

// Parse and validate
func parseAndValidate(s string) T.Tuple2[int, error] {
  val, err := strconv.Atoi(s)
  return T.MakeTuple2(val, err)
}

result := parseAndValidate("42")
value := result.Head  // 42
err := result.Tail    // nil

Key-Value Pairs

Use tuples for key-value associations:

tuple_keyvalue.go
import (
  R "github.com/IBM/fp-go/record"
  T "github.com/IBM/fp-go/tuple"
)

// Convert map to array of tuples
myMap := map[string]int{
  "apples":  5,
  "bananas": 3,
  "oranges": 7,
}

entries := R.ToEntries(myMap)
// []Tuple2[string, int]{
//   {Head: "apples", Tail: 5},
//   {Head: "bananas", Tail: 3},
//   {Head: "oranges", Tail: 7},
// }

// Process pairs
formatted := F.Pipe2(
  entries,
  A.Map(func(t T.Tuple2[string, int]) string {
      return fmt.Sprintf("%s: %d", t.Head, t.Tail)
  }),
)
// []string{"apples: 5", "bananas: 3", "oranges: 7"}

Zipping Arrays

Combine two arrays into tuples:

tuple_zip.go
import (
  A "github.com/IBM/fp-go/array"
  T "github.com/IBM/fp-go/tuple"
)

names := []string{"Alice", "Bob", "Charlie"}
ages := []int{30, 25, 35}

// Zip arrays into tuples
pairs := A.Zip(ages)(names)
// []Tuple2[string, int]{
//   {Head: "Alice", Tail: 30},
//   {Head: "Bob", Tail: 25},
//   {Head: "Charlie", Tail: 35},
// }

// Process zipped data
formatted := F.Pipe2(
  pairs,
  A.Map(func(t T.Tuple2[string, int]) string {
      return fmt.Sprintf("%s is %d years old", t.Head, t.Tail)
  }),
)
// []string{
//   "Alice is 30 years old",
//   "Bob is 25 years old",
//   "Charlie is 35 years old",
// }

Unzipping Tuples

Split array of tuples back into separate arrays:

tuple_unzip.go
import (
  A "github.com/IBM/fp-go/array"
  T "github.com/IBM/fp-go/tuple"
)

pairs := []T.Tuple2[string, int]{
  T.MakeTuple2("Alice", 30),
  T.MakeTuple2("Bob", 25),
  T.MakeTuple2("Charlie", 35),
}

// Unzip into separate arrays
result := A.Unzip(pairs)
names := result.Head  // []string{"Alice", "Bob", "Charlie"}
ages := result.Tail   // []int{30, 25, 35}

API Reference

FunctionTypeDescription
MakeTuple2[A, B](A, B) -> Tuple2[A, B]Creates a tuple from two values
MapFst[A, B, C](A -> C) -> Tuple2[A, B] -> Tuple2[C, B]Maps the first element
MapSnd[A, B, C](B -> C) -> Tuple2[A, B] -> Tuple2[A, C]Maps the second element
Bimap[A, B, C, D](A -> C, B -> D) -> Tuple2[A, B] -> Tuple2[C, D]Maps both elements
Swap[A, B]Tuple2[A, B] -> Tuple2[B, A]Swaps tuple elements

Type Definition:

type Tuple2[A, B any] struct {
Head A // First element
Tail B // Second element
}

Related Concepts

Common Use Cases:

  • Returning multiple values from functions
  • Key-value pairs and associations
  • Zipping and unzipping arrays
  • Intermediate data structures in transformations

See Also:

  • Array Zip - Combining arrays into tuples
  • Record - Key-value operations with maps