Documentation
¶
Overview ¶
Package pair provides a strongly-typed data structure for holding two values with functional operations.
Overview ¶
A Pair is a data structure that holds exactly two values of potentially different types. Unlike tuples which are position-based, Pair provides semantic operations for working with "head" and "tail" (or "first" and "second") values, along with rich functional programming capabilities including Functor, Applicative, and Monad operations.
The Pair type:
type Pair[A, B any] struct {
h, t any // head and tail (internal)
}
Basic Usage ¶
Creating pairs:
// Create a pair from two values
p := pair.MakePair("hello", 42) // Pair[string, int]
// Create a pair with the same value in both positions
p := pair.Of(5) // Pair[int, int]{5, 5}
// Convert from tuple
t := tuple.MakeTuple2("world", 100)
p := pair.FromTuple(t) // Pair[string, int]
Accessing values:
p := pair.MakePair("hello", 42)
head := pair.Head(p) // "hello"
tail := pair.Tail(p) // 42
// Alternative names
first := pair.First(p) // "hello" (same as Head)
second := pair.Second(p) // 42 (same as Tail)
Transforming Pairs ¶
Map operations transform one or both values:
p := pair.MakePair(5, "hello")
// Map the tail (second) value
p2 := pair.MonadMapTail(p, func(s string) int {
return len(s)
}) // Pair[int, int]{5, 5}
// Map the head (first) value
p3 := pair.MonadMapHead(p, func(n int) string {
return fmt.Sprintf("%d", n)
}) // Pair[string, string]{"5", "hello"}
// Map both values
p4 := pair.MonadBiMap(p,
func(n int) string { return fmt.Sprintf("%d", n) },
func(s string) int { return len(s) },
) // Pair[string, int]{"5", 5}
Curried versions for composition:
import F "github.com/IBM/fp-go/v2/function"
// Create a mapper function
doubleHead := pair.MapHead[string](func(n int) int {
return n * 2
})
p := pair.MakePair(5, "hello")
result := doubleHead(p) // Pair[int, string]{10, "hello"}
// Compose multiple transformations
transform := F.Flow2(
pair.MapHead[string](N.Mul(2)),
pair.MapTail[int](func(s string) int { return len(s) }),
)
result := transform(p) // Pair[int, int]{10, 5}
Swapping ¶
Swap exchanges the head and tail values:
p := pair.MakePair("hello", 42)
swapped := pair.Swap(p) // Pair[int, string]{42, "hello"}
Monadic Operations ¶
Pair supports monadic operations on both head and tail, requiring a Semigroup for combining values:
import (
SG "github.com/IBM/fp-go/v2/semigroup"
N "github.com/IBM/fp-go/v2/number"
)
// Chain on the tail (requires semigroup for head)
intSum := N.SemigroupSum[int]()
p := pair.MakePair(5, "hello")
result := pair.MonadChainTail(intSum, p, func(s string) pair.Pair[int, int] {
return pair.MakePair(len(s), len(s) * 2)
}) // Pair[int, int]{10, 10} (5 + 5 from semigroup, 10 from function)
// Chain on the head (requires semigroup for tail)
strConcat := SG.MakeSemigroup(func(a, b string) string { return a + b })
p2 := pair.MakePair(5, "hello")
result2 := pair.MonadChainHead(strConcat, p2, func(n int) pair.Pair[string, string] {
return pair.MakePair(fmt.Sprintf("%d", n), "!")
}) // Pair[string, string]{"5", "hello!"}
Curried versions:
intSum := N.SemigroupSum[int]()
chain := pair.ChainTail(intSum, func(s string) pair.Pair[int, int] {
return pair.MakePair(len(s), len(s) * 2)
})
p := pair.MakePair(5, "hello")
result := chain(p) // Pair[int, int]{10, 10}
Applicative Operations ¶
Apply functions wrapped in pairs to values in pairs:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
// Function in a pair
pf := pair.MakePair(10, func(s string) int { return len(s) })
// Value in a pair
pv := pair.MakePair(5, "hello")
// Apply (on tail)
result := pair.MonadApTail(intSum, pf, pv)
// Pair[int, int]{15, 5} (10+5 from semigroup, len("hello") from function)
// Apply (on head)
strConcat := SG.MakeSemigroup(func(a, b string) string { return a + b })
pf2 := pair.MakePair(func(n int) string { return fmt.Sprintf("%d", n) }, "!")
pv2 := pair.MakePair(42, "hello")
result2 := pair.MonadApHead(strConcat, pf2, pv2)
// Pair[string, string]{"42", "!hello"}
Function Conversion ¶
Convert between regular functions and pair-taking functions:
// Regular function
add := func(a, b int) int { return a + b }
// Convert to pair-taking function
pairedAdd := pair.Paired(add)
result := pairedAdd(pair.MakePair(3, 4)) // 7
// Convert back
unpairedAdd := pair.Unpaired(pairedAdd)
result = unpairedAdd(3, 4) // 7
Merge curried functions:
// Curried function
add := func(b int) func(a int) int {
return func(a int) int { return a + b }
}
// Apply to pair
merge := pair.Merge(add)
result := merge(pair.MakePair(3, 4)) // 7 (applies 4 then 3)
Equality ¶
Compare pairs for equality:
import (
EQ "github.com/IBM/fp-go/v2/eq"
)
// Create equality for pairs
pairEq := pair.Eq(
EQ.FromStrictEquals[string](),
EQ.FromStrictEquals[int](),
)
p1 := pair.MakePair("hello", 42)
p2 := pair.MakePair("hello", 42)
p3 := pair.MakePair("world", 42)
pairEq.Equals(p1, p2) // true
pairEq.Equals(p1, p3) // false
For comparable types:
pairEq := pair.FromStrictEquals[string, int]()
p1 := pair.MakePair("hello", 42)
p2 := pair.MakePair("hello", 42)
pairEq.Equals(p1, p2) // true
Tuple Conversion ¶
Convert between Pair and Tuple2:
import "github.com/IBM/fp-go/v2/tuple"
// Pair to Tuple
p := pair.MakePair("hello", 42)
t := pair.ToTuple(p) // Tuple2[string, int]
// Tuple to Pair
t := tuple.MakeTuple2("world", 100)
p := pair.FromTuple(t) // Pair[string, int]
Type Class Instances ¶
Pair provides type class instances for functional programming:
Functor - Map over values:
import M "github.com/IBM/fp-go/v2/monoid"
// Functor for tail
functor := pair.FunctorTail[int, string, int]()
mapper := functor.Map(func(s string) int { return len(s) })
p := pair.MakePair(5, "hello")
result := mapper(p) // Pair[int, int]{5, 5}
Pointed - Wrap values:
import M "github.com/IBM/fp-go/v2/monoid"
// Pointed for tail (requires monoid for head)
intSum := M.MonoidSum[int]()
pointed := pair.PointedTail[string](intSum)
p := pointed.Of("hello") // Pair[int, string]{0, "hello"}
Applicative - Apply wrapped functions:
import M "github.com/IBM/fp-go/v2/monoid"
intSum := M.MonoidSum[int]()
applicative := pair.ApplicativeTail[string, int, int](intSum)
// Create a pair with a function
pf := applicative.Of(func(s string) int { return len(s) })
// Apply to a value
pv := pair.MakePair(5, "hello")
result := applicative.Ap(pv)(pf) // Pair[int, int]{5, 5}
Monad - Chain operations:
import M "github.com/IBM/fp-go/v2/monoid"
intSum := M.MonoidSum[int]()
monad := pair.MonadTail[string, int, int](intSum)
p := monad.Of("hello")
result := monad.Chain(func(s string) pair.Pair[int, int] {
return pair.MakePair(len(s), len(s) * 2)
})(p) // Pair[int, int]{5, 10}
Practical Examples ¶
Example 1: Accumulating Results with Context
import (
N "github.com/IBM/fp-go/v2/number"
F "github.com/IBM/fp-go/v2/function"
)
// Process items while accumulating a count
intSum := N.SemigroupSum[int]()
processItem := func(item string) pair.Pair[int, string] {
return pair.MakePair(1, strings.ToUpper(item))
}
items := []string{"hello", "world", "foo"}
initial := pair.MakePair(0, "")
result := F.Pipe2(
items,
A.Map(processItem),
A.Reduce(func(acc, curr pair.Pair[int, string]) pair.Pair[int, string] {
return pair.MonadBiMap(
pair.MakePair(
pair.First(acc) + pair.First(curr),
pair.Second(acc) + " " + pair.Second(curr),
),
F.Identity[int],
strings.TrimSpace,
)
}, initial),
)
// Result: Pair[int, string]{3, "HELLO WORLD FOO"}
Example 2: Tracking Computation Steps
type Log []string
logConcat := SG.MakeSemigroup(func(a, b Log) Log {
return append(a, b...)
})
compute := func(n int) pair.Pair[Log, int] {
return pair.MakePair(
Log{fmt.Sprintf("computed %d", n)},
n * 2,
)
}
p := pair.MakePair(Log{"start"}, 5)
result := pair.MonadChainTail(logConcat, p, compute)
// Pair[Log, int]{
// []string{"start", "computed 5"},
// 10
// }
Example 3: Writer Monad Pattern
import M "github.com/IBM/fp-go/v2/monoid"
// Use pair as a writer monad
stringMonoid := M.MakeMonoid(
func(a, b string) string { return a + b },
"",
)
monad := pair.MonadTail[string, string, int](stringMonoid)
// Log and compute
logAndDouble := func(n int) pair.Pair[string, int] {
return pair.MakePair(
fmt.Sprintf("doubled %d; ", n),
n * 2,
)
}
logAndAdd := func(n int) pair.Pair[string, int] {
return pair.MakePair(
fmt.Sprintf("added 10; ", n),
n + 10,
)
}
result := F.Pipe2(
monad.Of(5),
monad.Chain(logAndDouble),
monad.Chain(logAndAdd),
)
// Pair[string, int]{"doubled 5; added 10; ", 20}
Function Reference ¶
Creation:
- MakePair[A, B any](A, B) Pair[A, B] - Create a pair from two values
- Of[A any](A) Pair[A, A] - Create a pair with same value in both positions
- FromTuple[A, B any](Tuple2[A, B]) Pair[A, B] - Convert tuple to pair
- ToTuple[A, B any](Pair[A, B]) Tuple2[A, B] - Convert pair to tuple
Access:
- Head[A, B any](Pair[A, B]) A - Get the head (first) value
- Tail[A, B any](Pair[A, B]) B - Get the tail (second) value
- First[A, B any](Pair[A, B]) A - Get the first value (alias for Head)
- Second[A, B any](Pair[A, B]) B - Get the second value (alias for Tail)
Transformations:
- MonadMapHead[B, A, A1 any](Pair[A, B], func(A) A1) Pair[A1, B] - Map head value
- MonadMapTail[A, B, B1 any](Pair[A, B], func(B) B1) Pair[A, B1] - Map tail value
- MonadMap[B, A, A1 any](Pair[A, B], func(A) A1) Pair[A1, B] - Map head value (alias)
- MonadBiMap[A, B, A1, B1 any](Pair[A, B], func(A) A1, func(B) B1) Pair[A1, B1] - Map both values
- MapHead[B, A, A1 any](func(A) A1) func(Pair[A, B]) Pair[A1, B] - Curried map head
- MapTail[A, B, B1 any](func(B) B1) func(Pair[A, B]) Pair[A, B1] - Curried map tail
- Map[A, B, B1 any](func(B) B1) func(Pair[A, B]) Pair[A, B1] - Curried map tail (alias)
- BiMap[A, B, A1, B1 any](func(A) A1, func(B) B1) func(Pair[A, B]) Pair[A1, B1] - Curried bimap
- Swap[A, B any](Pair[A, B]) Pair[B, A] - Swap head and tail
Monadic Operations:
- MonadChainHead[B, A, A1 any](Semigroup[B], Pair[A, B], func(A) Pair[A1, B]) Pair[A1, B]
- MonadChainTail[A, B, B1 any](Semigroup[A], Pair[A, B], func(B) Pair[A, B1]) Pair[A, B1]
- MonadChain[A, B, B1 any](Semigroup[A], Pair[A, B], func(B) Pair[A, B1]) Pair[A, B1]
- ChainHead[B, A, A1 any](Semigroup[B], func(A) Pair[A1, B]) func(Pair[A, B]) Pair[A1, B]
- ChainTail[A, B, B1 any](Semigroup[A], func(B) Pair[A, B1]) func(Pair[A, B]) Pair[A, B1]
- Chain[A, B, B1 any](Semigroup[A], func(B) Pair[A, B1]) func(Pair[A, B]) Pair[A, B1]
Applicative Operations:
- MonadApHead[B, A, A1 any](Semigroup[B], Pair[func(A) A1, B], Pair[A, B]) Pair[A1, B]
- MonadApTail[A, B, B1 any](Semigroup[A], Pair[A, func(B) B1], Pair[A, B]) Pair[A, B1]
- MonadAp[A, B, B1 any](Semigroup[A], Pair[A, func(B) B1], Pair[A, B]) Pair[A, B1]
- ApHead[B, A, A1 any](Semigroup[B], Pair[A, B]) func(Pair[func(A) A1, B]) Pair[A1, B]
- ApTail[A, B, B1 any](Semigroup[A], Pair[A, B]) func(Pair[A, func(B) B1]) Pair[A, B1]
- Ap[A, B, B1 any](Semigroup[A], Pair[A, B]) func(Pair[A, func(B) B1]) Pair[A, B1]
Function Conversion:
- Paired[F ~func(T1, T2) R, T1, T2, R any](F) func(Pair[T1, T2]) R
- Unpaired[F ~func(Pair[T1, T2]) R, T1, T2, R any](F) func(T1, T2) R
- Merge[F ~func(B) func(A) R, A, B, R any](F) func(Pair[A, B]) R
Equality:
- Eq[A, B any](Eq[A], Eq[B]) Eq[Pair[A, B]] - Create equality for pairs
- FromStrictEquals[A, B comparable]() Eq[Pair[A, B]] - Equality for comparable types
Type Classes:
- MonadHead[A, B, A1 any](Monoid[B]) Monad[A, A1, Pair[A, B], Pair[A1, B], Pair[func(A) A1, B]]
- MonadTail[B, A, B1 any](Monoid[A]) Monad[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
- Monad[B, A, B1 any](Monoid[A]) Monad[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
- PointedHead[A, B any](Monoid[B]) Pointed[A, Pair[A, B]]
- PointedTail[B, A any](Monoid[A]) Pointed[B, Pair[A, B]]
- Pointed[B, A any](Monoid[A]) Pointed[B, Pair[A, B]]
- FunctorHead[A, B, A1 any]() Functor[A, A1, Pair[A, B], Pair[A1, B]]
- FunctorTail[B, A, B1 any]() Functor[B, B1, Pair[A, B], Pair[A, B1]]
- Functor[B, A, B1 any]() Functor[B, B1, Pair[A, B], Pair[A, B1]]
- ApplicativeHead[A, B, A1 any](Monoid[B]) Applicative[A, A1, Pair[A, B], Pair[A1, B], Pair[func(A) A1, B]]
- ApplicativeTail[B, A, B1 any](Monoid[A]) Applicative[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
- Applicative[B, A, B1 any](Monoid[A]) Applicative[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
Related Packages ¶
- github.com/IBM/fp-go/v2/tuple - Position-based heterogeneous tuples
- github.com/IBM/fp-go/v2/semigroup - Associative binary operations
- github.com/IBM/fp-go/v2/monoid - Semigroups with identity
- github.com/IBM/fp-go/v2/eq - Equality type class
- github.com/IBM/fp-go/v2/function - Function composition utilities
Index ¶
- func ApHead[B, A, A1 any](sg Semigroup[B], fa Pair[A, B]) func(Pair[func(A) A1, B]) Pair[A1, B]
- func Applicative[B, A, B1 any](m monoid.Monoid[A]) applicative.Applicative[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
- func ApplicativeHead[A, B, A1 any](m monoid.Monoid[B]) applicative.Applicative[A, A1, Pair[A, B], Pair[A1, B], Pair[func(A) A1, B]]
- func ApplicativeTail[B, A, B1 any](m monoid.Monoid[A]) applicative.Applicative[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
- func BiMap[A, B, A1, B1 any](f func(A) A1, g func(B) B1) func(Pair[A, B]) Pair[A1, B1]
- func ChainHead[B, A, A1 any](sg Semigroup[B], f func(A) Pair[A1, B]) func(Pair[A, B]) Pair[A1, B]
- func Eq[A, B any](a eq.Eq[A], b eq.Eq[B]) eq.Eq[Pair[A, B]]
- func First[A, B any](fa Pair[A, B]) A
- func FromStrictEquals[A, B comparable]() eq.Eq[Pair[A, B]]
- func Functor[B, A, B1 any]() functor.Functor[B, B1, Pair[A, B], Pair[A, B1]]
- func FunctorHead[A, B, A1 any]() functor.Functor[A, A1, Pair[A, B], Pair[A1, B]]
- func FunctorTail[B, A, B1 any]() functor.Functor[B, B1, Pair[A, B], Pair[A, B1]]
- func Head[A, B any](fa Pair[A, B]) A
- func MapHead[B, A, A1 any](f func(A) A1) func(Pair[A, B]) Pair[A1, B]
- func Merge[F ~func(B) func(A) R, A, B, R any](f F) func(Pair[A, B]) R
- func Monad[B, A, B1 any](m monoid.Monoid[A]) monad.Monad[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
- func MonadHead[A, B, A1 any](m monoid.Monoid[B]) monad.Monad[A, A1, Pair[A, B], Pair[A1, B], Pair[func(A) A1, B]]
- func MonadSequence[L, A, HKTA, HKTPA any](mmap func(HKTA, Kleisli[L, A, A]) HKTPA, fas Pair[L, HKTA]) HKTPA
- func MonadTail[B, A, B1 any](m monoid.Monoid[A]) monad.Monad[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
- func MonadTraverse[L, A, HKTA, HKTPA any](mmap func(HKTA, Kleisli[L, A, A]) HKTPA, f func(A) HKTA, fas Pair[L, A]) HKTPA
- func Paired[F ~func(T1, T2) R, T1, T2, R any](f F) func(Pair[T1, T2]) R
- func Pointed[B, A any](m monoid.Monoid[A]) pointed.Pointed[B, Pair[A, B]]
- func PointedHead[A, B any](m monoid.Monoid[B]) pointed.Pointed[A, Pair[A, B]]
- func PointedTail[B, A any](m monoid.Monoid[A]) pointed.Pointed[B, Pair[A, B]]
- func Second[A, B any](fa Pair[A, B]) B
- func Sequence[L, A, HKTA, HKTPA any](mmap func(Kleisli[L, A, A]) func(HKTA) HKTPA) func(Pair[L, HKTA]) HKTPA
- func Tail[A, B any](fa Pair[A, B]) B
- func Traverse[L, A, HKTA, HKTPA any](mmap func(Kleisli[L, A, A]) func(HKTA) HKTPA) func(func(A) HKTA) func(Pair[L, A]) HKTPA
- func Unpaired[F ~func(Pair[T1, T2]) R, T1, T2, R any](f F) func(T1, T2) R
- type Kleisli
- type Operator
- func Ap[A, B, B1 any](sg Semigroup[A], fa Pair[A, B]) Operator[A, func(B) B1, B1]
- func ApTail[A, B, B1 any](sg Semigroup[A], fb Pair[A, B]) Operator[A, func(B) B1, B1]
- func Chain[A, B, B1 any](sg Semigroup[A], f Kleisli[A, B, B1]) Operator[A, B, B1]
- func ChainTail[A, B, B1 any](sg Semigroup[A], f Kleisli[A, B, B1]) Operator[A, B, B1]
- func Map[A, B, B1 any](f func(B) B1) Operator[A, B, B1]
- func MapTail[A, B, B1 any](f func(B) B1) Operator[A, B, B1]
- type Pair
- func FromTuple[A, B any](t Tuple2[A, B]) Pair[A, B]
- func MakePair[A, B any](a A, b B) Pair[A, B]
- func MonadAp[A, B, B1 any](sg Semigroup[A], faa Pair[A, func(B) B1], fa Pair[A, B]) Pair[A, B1]
- func MonadApHead[B, A, A1 any](sg Semigroup[B], faa Pair[func(A) A1, B], fa Pair[A, B]) Pair[A1, B]
- func MonadApTail[A, B, B1 any](sg Semigroup[A], fbb Pair[A, func(B) B1], fb Pair[A, B]) Pair[A, B1]
- func MonadBiMap[A, B, A1, B1 any](fa Pair[A, B], f func(A) A1, g func(B) B1) Pair[A1, B1]
- func MonadChain[A, B, B1 any](sg Semigroup[A], fa Pair[A, B], f Kleisli[A, B, B1]) Pair[A, B1]
- func MonadChainHead[B, A, A1 any](sg Semigroup[B], fa Pair[A, B], f func(A) Pair[A1, B]) Pair[A1, B]
- func MonadChainTail[A, B, B1 any](sg Semigroup[A], fb Pair[A, B], f Kleisli[A, B, B1]) Pair[A, B1]
- func MonadMap[A, B, B1 any](fa Pair[A, B], f func(B) B1) Pair[A, B1]
- func MonadMapHead[B, A, A1 any](fa Pair[A, B], f func(A) A1) Pair[A1, B]
- func MonadMapTail[A, B, B1 any](fa Pair[A, B], f func(B) B1) Pair[A, B1]
- func Of[A any](value A) Pair[A, A]
- func Swap[A, B any](fa Pair[A, B]) Pair[B, A]
- type Semigroup
- type Tuple2
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApHead ¶
ApHead returns a function that applies a function in a pair to a value in a pair, operating on head values. This is the curried version of MonadApHead.
Example:
import SG "github.com/IBM/fp-go/v2/semigroup"
strConcat := SG.MakeSemigroup(func(a, b string) string { return a + b })
pv := pair.MakePair(42, "hello")
ap := pair.ApHead(strConcat, pv)
pf := pair.MakePair(func(n int) string { return fmt.Sprintf("%d", n) }, "!")
result := ap(pf) // Pair[string, string]{"42", "!hello"}
func Applicative ¶
func Applicative[B, A, B1 any](m monoid.Monoid[A]) applicative.Applicative[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
Applicative implements the applicative operations for Pair operating on the tail value (alias for ApplicativeTail). This is the default applicative instance for Pair.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
intSum := M.MonoidSum[int]()
applicative := pair.Applicative[string, int, int](intSum)
pf := applicative.Of(func(s string) int { return len(s) })
pv := pair.MakePair(5, "hello")
result := applicative.Ap(pv)(pf) // Pair[int, int]{5, 5}
func ApplicativeHead ¶
func ApplicativeHead[A, B, A1 any](m monoid.Monoid[B]) applicative.Applicative[A, A1, Pair[A, B], Pair[A1, B], Pair[func(A) A1, B]]
ApplicativeHead implements the applicative operations for Pair operating on the head value. Requires a monoid for the tail type to provide an identity element for the Of operation and a semigroup for combining tail values in the Ap operation.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
stringMonoid := M.MakeMonoid(
func(a, b string) string { return a + b },
"",
)
applicative := pair.ApplicativeHead[int, string, string](stringMonoid)
pf := applicative.Of(func(n int) string { return fmt.Sprintf("%d", n) })
pv := pair.MakePair(42, "!")
result := applicative.Ap(pv)(pf) // Pair[string, string]{"42", "!"}
func ApplicativeTail ¶
func ApplicativeTail[B, A, B1 any](m monoid.Monoid[A]) applicative.Applicative[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
ApplicativeTail implements the applicative operations for Pair operating on the tail value. Requires a monoid for the head type to provide an identity element for the Of operation and a semigroup for combining head values in the Ap operation.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
intSum := M.MonoidSum[int]()
applicative := pair.ApplicativeTail[string, int, int](intSum)
pf := applicative.Of(func(s string) int { return len(s) })
pv := pair.MakePair(5, "hello")
result := applicative.Ap(pv)(pf) // Pair[int, int]{5, 5}
func BiMap ¶
func BiMap[A, B, A1, B1 any](f func(A) A1, g func(B) B1) func(Pair[A, B]) Pair[A1, B1]
BiMap returns a function that maps over both values of a pair. This is the curried version of MonadBiMap.
Example:
mapper := pair.BiMap(
func(n int) string { return fmt.Sprintf("%d", n) },
func(s string) int { return len(s) },
)
p := pair.MakePair(5, "hello")
p2 := mapper(p) // Pair[string, int]{"5", 5}
Example ¶
package main
import (
"fmt"
N "github.com/IBM/fp-go/v2/number"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
result := pair.BiMap(
func(s string) string { return s + "!" },
N.Mul(2),
)(p)
fmt.Println(result)
}
Output: Pair[string, int](hello!, 84)
func ChainHead ¶
ChainHead returns a function that chains over the head value. This is the curried version of MonadChainHead.
Example:
import SG "github.com/IBM/fp-go/v2/semigroup"
strConcat := SG.MakeSemigroup(func(a, b string) string { return a + b })
chain := pair.ChainHead(strConcat, func(n int) pair.Pair[string, string] {
return pair.MakePair(fmt.Sprintf("%d", n), "!")
})
p := pair.MakePair(5, "hello")
p2 := chain(p) // Pair[string, string]{"5", "hello!"}
func Eq ¶
Eq constructs an equality predicate for Pair from equality predicates for both components. Two pairs are considered equal if both their head values are equal and their tail values are equal.
Example:
import EQ "github.com/IBM/fp-go/v2/eq"
pairEq := pair.Eq(
EQ.FromStrictEquals[string](),
EQ.FromStrictEquals[int](),
)
p1 := pair.MakePair("hello", 42)
p2 := pair.MakePair("hello", 42)
p3 := pair.MakePair("world", 42)
pairEq.Equals(p1, p2) // true
pairEq.Equals(p1, p3) // false
func First ¶
func First[A, B any](fa Pair[A, B]) A
First returns the first value of the pair (alias for Head).
Example:
p := pair.MakePair("hello", 42)
f := pair.First(p) // "hello"
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
f := pair.First(p)
fmt.Println(f)
}
Output: hello
func FromStrictEquals ¶
func FromStrictEquals[A, B comparable]() eq.Eq[Pair[A, B]]
FromStrictEquals constructs an eq.Eq for Pair using the built-in equality operator (==) for both components. This is only available when both type parameters are comparable.
Example:
pairEq := pair.FromStrictEquals[string, int]()
p1 := pair.MakePair("hello", 42)
p2 := pair.MakePair("hello", 42)
pairEq.Equals(p1, p2) // true
func Functor ¶
Functor implements the functor operations for Pair operating on the tail value (alias for FunctorTail). This is the default functor instance for Pair.
Example:
functor := pair.Functor[string, int, int]()
mapper := functor.Map(func(s string) int { return len(s) })
p := pair.MakePair(5, "hello")
p2 := mapper(p) // Pair[int, int]{5, 5}
func FunctorHead ¶
FunctorHead implements the functor operations for Pair operating on the head value.
Example:
functor := pair.FunctorHead[int, string, string]()
mapper := functor.Map(func(n int) string { return fmt.Sprintf("%d", n) })
p := pair.MakePair(42, "hello")
p2 := mapper(p) // Pair[string, string]{"42", "hello"}
func FunctorTail ¶
FunctorTail implements the functor operations for Pair operating on the tail value.
Example:
functor := pair.FunctorTail[string, int, int]()
mapper := functor.Map(func(s string) int { return len(s) })
p := pair.MakePair(5, "hello")
p2 := mapper(p) // Pair[int, int]{5, 5}
func Head ¶
func Head[A, B any](fa Pair[A, B]) A
Head returns the head (first) value of the pair.
Example:
p := pair.MakePair("hello", 42)
h := pair.Head(p) // "hello"
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
h := pair.Head(p)
fmt.Println(h)
}
Output: hello
func MapHead ¶
func MapHead[B, A, A1 any](f func(A) A1) func(Pair[A, B]) Pair[A1, B]
MapHead returns a function that maps over the head value of a pair. This is the curried version of MonadMapHead.
Example:
mapper := pair.MapHead[string](func(n int) string {
return fmt.Sprintf("%d", n)
})
p := pair.MakePair(5, "hello")
p2 := mapper(p) // Pair[string, string]{"5", "hello"}
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
upper := pair.MapHead[int](func(s string) string { return s + "!" })(p)
fmt.Println(upper)
}
Output: Pair[string, int](hello!, 42)
func Merge ¶
func Merge[F ~func(B) func(A) R, A, B, R any](f F) func(Pair[A, B]) R
Merge applies a curried function to a pair by applying the tail value first, then the head value.
Example:
add := func(b int) func(a int) int {
return func(a int) int { return a + b }
}
merge := pair.Merge(add)
result := merge(pair.MakePair(3, 4)) // 7 (applies 4 then 3)
func Monad ¶
func Monad[B, A, B1 any](m monoid.Monoid[A]) monad.Monad[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
Monad implements the monadic operations for Pair operating on the tail value (alias for MonadTail). This is the default monad instance for Pair.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
intSum := M.MonoidSum[int]()
monad := pair.Monad[string, int, int](intSum)
p := monad.Of("hello") // Pair[int, string]{0, "hello"}
func MonadHead ¶
func MonadHead[A, B, A1 any](m monoid.Monoid[B]) monad.Monad[A, A1, Pair[A, B], Pair[A1, B], Pair[func(A) A1, B]]
MonadHead implements the monadic operations for Pair operating on the head value. Requires a monoid for the tail type to provide an identity element for the Of operation and a semigroup for combining tail values in Chain and Ap operations.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
stringMonoid := M.MakeMonoid(
func(a, b string) string { return a + b },
"",
)
monad := pair.MonadHead[int, string, int](stringMonoid)
p := monad.Of(42) // Pair[int, string]{42, ""}
func MonadSequence ¶
func MonadSequence[L, A, HKTA, HKTPA any]( mmap func(HKTA, Kleisli[L, A, A]) HKTPA, fas Pair[L, HKTA], ) HKTPA
func MonadTail ¶
func MonadTail[B, A, B1 any](m monoid.Monoid[A]) monad.Monad[B, B1, Pair[A, B], Pair[A, B1], Pair[A, func(B) B1]]
MonadTail implements the monadic operations for Pair operating on the tail value. Requires a monoid for the head type to provide an identity element for the Of operation and a semigroup for combining head values in Chain and Ap operations.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
intSum := M.MonoidSum[int]()
monad := pair.MonadTail[string, int, int](intSum)
p := monad.Of("hello") // Pair[int, string]{0, "hello"}
func MonadTraverse ¶
func MonadTraverse[L, A, HKTA, HKTPA any]( mmap func(HKTA, Kleisli[L, A, A]) HKTPA, f func(A) HKTA, fas Pair[L, A], ) HKTPA
func Paired ¶
func Paired[F ~func(T1, T2) R, T1, T2, R any](f F) func(Pair[T1, T2]) R
Paired converts a function with 2 parameters into a function taking a Pair. The inverse function is Unpaired.
Example:
add := func(a, b int) int { return a + b }
pairedAdd := pair.Paired(add)
result := pairedAdd(pair.MakePair(3, 4)) // 7
func Pointed ¶
Pointed implements the pointed operations for Pair operating on the tail value (alias for PointedTail). This is the default pointed instance for Pair.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
intSum := M.MonoidSum[int]()
pointed := pair.Pointed[string, int](intSum)
p := pointed.Of("hello") // Pair[int, string]{0, "hello"}
func PointedHead ¶
PointedHead implements the pointed operations for Pair operating on the head value. Requires a monoid for the tail type to provide an identity element.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
stringMonoid := M.MakeMonoid(
func(a, b string) string { return a + b },
"",
)
pointed := pair.PointedHead[int, string](stringMonoid)
p := pointed.Of(42) // Pair[int, string]{42, ""}
func PointedTail ¶
PointedTail implements the pointed operations for Pair operating on the tail value. Requires a monoid for the head type to provide an identity element.
Example:
import M "github.com/IBM/fp-go/v2/monoid"
intSum := M.MonoidSum[int]()
pointed := pair.PointedTail[string, int](intSum)
p := pointed.Of("hello") // Pair[int, string]{0, "hello"}
func Second ¶
func Second[A, B any](fa Pair[A, B]) B
Second returns the second value of the pair (alias for Tail).
Example:
p := pair.MakePair("hello", 42)
s := pair.Second(p) // 42
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
s := pair.Second(p)
fmt.Println(s)
}
Output: 42
func Sequence ¶
func Sequence[L, A, HKTA, HKTPA any]( mmap func(Kleisli[L, A, A]) func(HKTA) HKTPA, ) func(Pair[L, HKTA]) HKTPA
func Tail ¶
func Tail[A, B any](fa Pair[A, B]) B
Tail returns the tail (second) value of the pair.
Example:
p := pair.MakePair("hello", 42)
t := pair.Tail(p) // 42
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
t := pair.Tail(p)
fmt.Println(t)
}
Output: 42
func Traverse ¶
func Traverse[L, A, HKTA, HKTPA any]( mmap func(Kleisli[L, A, A]) func(HKTA) HKTPA, ) func(func(A) HKTA) func(Pair[L, A]) HKTPA
func Unpaired ¶
func Unpaired[F ~func(Pair[T1, T2]) R, T1, T2, R any](f F) func(T1, T2) R
Unpaired converts a function with a Pair parameter into a function with 2 parameters. The inverse function is Paired.
Example:
pairedAdd := func(p pair.Pair[int, int]) int {
return pair.Head(p) + pair.Tail(p)
}
add := pair.Unpaired(pairedAdd)
result := add(3, 4) // 7
Types ¶
type Kleisli ¶
Kleisli represents a Kleisli arrow for Pair. It is a function that takes a value of type R1 and returns a Pair[L, R2].
Kleisli arrows are used for monadic composition, allowing you to chain operations that produce Pairs. They are particularly useful with Chain and ChainTail operations.
Example:
// A Kleisli arrow that takes a string and returns a Pair
lengthPair := func(s string) pair.Pair[int, string] {
return pair.MakePair(len(s), s + "!")
}
// Type: Kleisli[int, string, string]
func FromHead ¶
func FromHead[B, A any](a A) Kleisli[A, B, B]
FromHead creates a function that constructs a Pair from a given head value. It returns a function that takes a tail value and combines it with the head to create a Pair.
This is useful for functional composition where you want to partially apply the head value and later provide the tail value.
Example:
makePair := pair.FromHead[int]("hello")
p := makePair(42) // Pair[string, int]{"hello", 42}
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
makePair := pair.FromHead[int]("hello")
p := makePair(42)
fmt.Println(p)
}
Output: Pair[string, int](hello, 42)
func FromTail ¶
func FromTail[A, B any](b B) Kleisli[A, A, B]
FromTail creates a function that constructs a Pair from a given tail value. It returns a function that takes a head value and combines it with the tail to create a Pair.
This is useful for functional composition where you want to partially apply the tail value and later provide the head value.
Example:
makePair := pair.FromTail[string](42)
p := makePair("hello") // Pair[string, int]{"hello", 42}
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
makePair := pair.FromTail[string](42)
p := makePair("hello")
fmt.Println(p)
}
Output: Pair[string, int](hello, 42)
type Operator ¶
Operator represents an endomorphism on Pair that transforms the tail value. It is a function that takes a Pair[L, R1] and returns a Pair[L, R2], preserving the head type L while potentially transforming the tail from R1 to R2.
Operators are commonly used as the return type of curried functions like Map, Chain, and Ap, enabling function composition and point-free style programming.
Example:
// An operator that maps the tail value
toLengths := pair.Map[string](func(s string) int {
return len(s)
})
// Type: Operator[string, string, int]
// Usage: p2 := toLengths(pair.MakePair("key", "value"))
func Ap ¶
Ap returns a function that applies a function in a pair to a value in a pair, operating on tail values (alias for ApTail).
Example:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
pv := pair.MakePair(5, "hello")
ap := pair.Ap(intSum, pv)
pf := pair.MakePair(10, func(s string) int { return len(s) })
result := ap(pf) // Pair[int, int]{15, 5}
func ApTail ¶
ApTail returns a function that applies a function in a pair to a value in a pair, operating on tail values. This is the curried version of MonadApTail.
Example:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
pv := pair.MakePair(5, "hello")
ap := pair.ApTail(intSum, pv)
pf := pair.MakePair(10, func(s string) int { return len(s) })
result := ap(pf) // Pair[int, int]{15, 5}
func Chain ¶
Chain returns a function that chains over the tail value (alias for ChainTail).
Example:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
chain := pair.Chain(intSum, func(s string) pair.Pair[int, int] {
return pair.MakePair(len(s), len(s) * 2)
})
p := pair.MakePair(5, "hello")
p2 := chain(p) // Pair[int, int]{10, 10}
func ChainTail ¶
ChainTail returns a function that chains over the tail value. This is the curried version of MonadChainTail.
Example:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
chain := pair.ChainTail(intSum, func(s string) pair.Pair[int, int] {
return pair.MakePair(len(s), len(s) * 2)
})
p := pair.MakePair(5, "hello")
p2 := chain(p) // Pair[int, int]{10, 10}
func Map ¶
func Map[A, B, B1 any](f func(B) B1) Operator[A, B, B1]
Map returns a function that maps over the tail value of a pair (alias for MapTail). This is the curried version of MonadMapTail.
Example:
mapper := pair.Map[int](func(s string) int { return len(s) })
p := pair.MakePair(5, "hello")
p2 := mapper(p) // Pair[int, int]{5, 5}
Example ¶
package main
import (
"fmt"
N "github.com/IBM/fp-go/v2/number"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
doubled := pair.Map[string](N.Mul(2))(p)
fmt.Println(doubled)
}
Output: Pair[string, int](hello, 84)
func MapTail ¶
func MapTail[A, B, B1 any](f func(B) B1) Operator[A, B, B1]
MapTail returns a function that maps over the tail value of a pair. This is the curried version of MonadMapTail.
Example:
mapper := pair.MapTail[int](func(s string) int { return len(s) })
p := pair.MakePair(5, "hello")
p2 := mapper(p) // Pair[int, int]{5, 5}
type Pair ¶
type Pair[L, R any] struct { // contains filtered or unexported fields }
Pair defines a data structure that holds two strongly typed values. The first value is called the "head" or "left" (L), and the second is called the "tail" or "right" (R).
Pair provides a foundation for functional programming patterns, supporting operations like mapping, chaining, and applicative application on either or both values.
Example:
p := pair.MakePair("hello", 42)
head := pair.Head(p) // "hello"
tail := pair.Tail(p) // 42
Example (Formatting_comparison) ¶
ExamplePair_formatting_comparison demonstrates different formatting options.
package main
import (
"fmt"
P "github.com/IBM/fp-go/v2/pair"
)
func main() {
type Config struct {
Host string
Port int
}
config := Config{Host: "localhost", Port: 8080}
p := P.MakePair(config, []string{"api", "web"})
fmt.Printf("String(): %s\n", p.String())
fmt.Printf("GoString(): %s\n", p.GoString())
fmt.Printf("%%v: %v\n", p)
fmt.Printf("%%#v: %#v\n", p)
}
Output: String(): Pair[pair_test.Config, []string]({localhost 8080}, [api web]) GoString(): pair.MakePair[pair_test.Config, []string](pair_test.Config{Host:"localhost", Port:8080}, []string{"api", "web"}) %v: Pair[pair_test.Config, []string]({localhost 8080}, [api web]) %#v: pair.MakePair[pair_test.Config, []string](pair_test.Config{Host:"localhost", Port:8080}, []string{"api", "web"})
Example (Formatting_nested) ¶
ExamplePair_formatting_nested demonstrates formatting nested pairs.
package main
import (
"fmt"
P "github.com/IBM/fp-go/v2/pair"
)
func main() {
inner := P.MakePair("inner", 10)
outer := P.MakePair(inner, "outer")
fmt.Printf("%%v: %v\n", outer)
fmt.Printf("%%#v: %#v\n", outer)
}
Output: %v: Pair[pair.Pair[string,int], string](Pair[string, int](inner, 10), outer) %#v: pair.MakePair[pair.Pair[string,int], string](pair.MakePair[string, int]("inner", 10), "outer")
Example (Formatting_with_maps) ¶
ExamplePair_formatting_with_maps demonstrates formatting pairs containing maps.
package main
import (
"fmt"
P "github.com/IBM/fp-go/v2/pair"
)
func main() {
metadata := map[string]string{
"version": "1.0",
"author": "Alice",
}
p := P.MakePair("config", metadata)
fmt.Printf("%%v: %v\n", p)
fmt.Printf("%%s: %s\n", p)
}
Output: %v: Pair[string, map[string]string](config, map[author:Alice version:1.0]) %s: Pair[string, map[string]string](config, map[author:Alice version:1.0])
func FromTuple ¶
func FromTuple[A, B any](t Tuple2[A, B]) Pair[A, B]
FromTuple creates a Pair from a Tuple2. The first element of the tuple becomes the head, and the second becomes the tail.
Example:
t := tuple.MakeTuple2("hello", 42)
p := pair.FromTuple(t) // Pair[string, int]{"hello", 42}
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
"github.com/IBM/fp-go/v2/tuple"
)
func main() {
t := tuple.MakeTuple2("hello", 42)
p := pair.FromTuple(t)
fmt.Println(p)
}
Output: Pair[string, int](hello, 42)
func MakePair ¶
func MakePair[A, B any](a A, b B) Pair[A, B]
MakePair creates a Pair from two values. The first value becomes the head, and the second becomes the tail.
Example:
p := pair.MakePair("hello", 42) // Pair[string, int]{"hello", 42}
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
fmt.Println(p)
}
Output: Pair[string, int](hello, 42)
func MonadAp ¶
MonadAp applies a function wrapped in a pair to a value wrapped in a pair, operating on the tail values (alias for MonadApTail).
Example:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
pf := pair.MakePair(10, func(s string) int { return len(s) })
pv := pair.MakePair(5, "hello")
result := pair.MonadAp(intSum, pf, pv) // Pair[int, int]{15, 5}
func MonadApHead ¶
MonadApHead applies a function wrapped in a pair to a value wrapped in a pair, operating on the head values and combining tail values using a semigroup.
Example:
import SG "github.com/IBM/fp-go/v2/semigroup"
strConcat := SG.MakeSemigroup(func(a, b string) string { return a + b })
pf := pair.MakePair(func(n int) string { return fmt.Sprintf("%d", n) }, "!")
pv := pair.MakePair(42, "hello")
result := pair.MonadApHead(strConcat, pf, pv) // Pair[string, string]{"42", "!hello"}
func MonadApTail ¶
MonadApTail applies a function wrapped in a pair to a value wrapped in a pair, operating on the tail values and combining head values using a semigroup.
Example:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
pf := pair.MakePair(10, func(s string) int { return len(s) })
pv := pair.MakePair(5, "hello")
result := pair.MonadApTail(intSum, pf, pv) // Pair[int, int]{15, 5}
func MonadBiMap ¶
func MonadBiMap[A, B, A1, B1 any](fa Pair[A, B], f func(A) A1, g func(B) B1) Pair[A1, B1]
MonadBiMap maps functions over both the head and tail values of the pair.
Example:
p := pair.MakePair(5, "hello")
p2 := pair.MonadBiMap(p,
func(n int) string { return fmt.Sprintf("%d", n) },
func(s string) int { return len(s) },
) // Pair[string, int]{"5", 5}
func MonadChain ¶
MonadChain chains a function over the tail value (alias for MonadChainTail).
Example:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
p := pair.MakePair(5, "hello")
p2 := pair.MonadChain(intSum, p, func(s string) pair.Pair[int, int] {
return pair.MakePair(len(s), len(s) * 2)
}) // Pair[int, int]{10, 10}
func MonadChainHead ¶
func MonadChainHead[B, A, A1 any](sg Semigroup[B], fa Pair[A, B], f func(A) Pair[A1, B]) Pair[A1, B]
MonadChainHead chains a function over the head value, combining tail values using a semigroup. The function receives the head value and returns a new pair. The tail values from both pairs are combined using the provided semigroup.
Example:
import SG "github.com/IBM/fp-go/v2/semigroup"
strConcat := SG.MakeSemigroup(func(a, b string) string { return a + b })
p := pair.MakePair(5, "hello")
p2 := pair.MonadChainHead(strConcat, p, func(n int) pair.Pair[string, string] {
return pair.MakePair(fmt.Sprintf("%d", n), "!")
}) // Pair[string, string]{"5", "hello!"}
func MonadChainTail ¶
MonadChainTail chains a function over the tail value, combining head values using a semigroup. The function receives the tail value and returns a new pair. The head values from both pairs are combined using the provided semigroup.
Example:
import N "github.com/IBM/fp-go/v2/number"
intSum := N.SemigroupSum[int]()
p := pair.MakePair(5, "hello")
p2 := pair.MonadChainTail(intSum, p, func(s string) pair.Pair[int, int] {
return pair.MakePair(len(s), len(s) * 2)
}) // Pair[int, int]{10, 10}
func MonadMapHead ¶
func MonadMapHead[B, A, A1 any](fa Pair[A, B], f func(A) A1) Pair[A1, B]
MonadMapHead maps a function over the head value of the pair, leaving the tail unchanged.
Example:
p := pair.MakePair(5, "hello")
p2 := pair.MonadMapHead(p, func(n int) string {
return fmt.Sprintf("%d", n)
}) // Pair[string, string]{"5", "hello"}
func MonadMapTail ¶
func MonadMapTail[A, B, B1 any](fa Pair[A, B], f func(B) B1) Pair[A, B1]
MonadMapTail maps a function over the tail value of the pair, leaving the head unchanged.
Example:
p := pair.MakePair(5, "hello")
p2 := pair.MonadMapTail(p, func(s string) int {
return len(s)
}) // Pair[int, int]{5, 5}
func Of ¶
func Of[A any](value A) Pair[A, A]
Of creates a Pair with the same value in both the head and tail positions.
Example:
p := pair.Of(42) // Pair[int, int]{42, 42}
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.Of(42)
fmt.Println(p)
}
Output: Pair[int, int](42, 42)
func Swap ¶
func Swap[A, B any](fa Pair[A, B]) Pair[B, A]
Swap swaps the head and tail values of a pair.
Example:
p := pair.MakePair("hello", 42)
swapped := pair.Swap(p) // Pair[int, string]{42, "hello"}
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
swapped := pair.Swap(p)
fmt.Println(swapped)
}
Output: Pair[int, string](42, hello)
func (Pair[L, R]) Format ¶
Format implements fmt.Formatter for Pair. Supports all standard format verbs:
- %s, %v, %+v: uses String() representation
- %#v: uses GoString() representation
- %q: quoted String() representation
- other verbs: uses String() representation
Example:
p := pair.MakePair("key", 42)
fmt.Printf("%s", p) // "Pair[string, int](key, 42)"
fmt.Printf("%v", p) // "Pair[string, int](key, 42)"
fmt.Printf("%#v", p) // "pair.MakePair[string, int]("key", 42)"
Example ¶
ExamplePair_Format demonstrates the fmt.Formatter interface implementation.
package main
import (
"fmt"
P "github.com/IBM/fp-go/v2/pair"
)
func main() {
p := P.MakePair("config", 8080)
// Different format verbs
fmt.Printf("%%s: %s\n", p)
fmt.Printf("%%v: %v\n", p)
fmt.Printf("%%+v: %+v\n", p)
fmt.Printf("%%#v: %#v\n", p)
}
Output: %s: Pair[string, int](config, 8080) %v: Pair[string, int](config, 8080) %+v: Pair[string, int](config, 8080) %#v: pair.MakePair[string, int]("config", 8080)
func (Pair[L, R]) GoString ¶
func (p Pair[L, R]) GoString() string
GoString implements fmt.GoStringer for Pair. Returns a Go-syntax representation of the Pair value.
Example:
pair.MakePair("key", 42).GoString() // "pair.MakePair[string, int]("key", 42)"
Example ¶
ExamplePair_GoString demonstrates the fmt.GoStringer interface implementation.
package main
import (
"errors"
"fmt"
P "github.com/IBM/fp-go/v2/pair"
)
func main() {
p1 := P.MakePair("key", 42)
p2 := P.MakePair(errors.New("error"), "value")
fmt.Printf("%#v\n", p1)
fmt.Printf("%#v\n", p2)
}
Output: pair.MakePair[string, int]("key", 42) pair.MakePair[error, string](&errors.errorString{s:"error"}, "value")
func (Pair[L, R]) LogValue ¶
LogValue implements slog.LogValuer for Pair. Returns a slog.Value that represents the Pair for structured logging. Returns a group value with "head" and "tail" keys.
Example:
logger := slog.Default()
p := pair.MakePair("key", 42)
logger.Info("pair value", "data", p)
// Logs: {"msg":"pair value","data":{"head":"key","tail":42}}
Example ¶
ExamplePair_LogValue demonstrates the slog.LogValuer interface implementation.
package main
import (
"errors"
"log/slog"
"os"
P "github.com/IBM/fp-go/v2/pair"
)
func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
// Remove time for consistent output
if a.Key == slog.TimeKey {
return slog.Attr{}
}
return a
},
}))
// Pair with string and int
p1 := P.MakePair("username", 42)
logger.Info("user data", "data", p1)
// Pair with error and string
p2 := P.MakePair(errors.New("connection failed"), "retry")
logger.Error("operation failed", "status", p2)
}
Output: level=INFO msg="user data" data.head=username data.tail=42 level=ERROR msg="operation failed" status.head="connection failed" status.tail=retry
Example (Structured) ¶
ExamplePair_LogValue_structured demonstrates structured logging with Pair.
package main
import (
"log/slog"
"os"
P "github.com/IBM/fp-go/v2/pair"
)
func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
return slog.Attr{}
}
return a
},
}))
// Simulate a key-value store operation
operation := func(key string, value int) P.Pair[string, int] {
return P.MakePair(key, value)
}
// Log successful operation
result1 := operation("counter", 42)
logger.Info("store operation", "key", "counter", "result", result1)
// Log another operation
result2 := operation("timeout", 30)
logger.Info("store operation", "key", "timeout", "result", result2)
}
Output: level=INFO msg="store operation" key=counter result.head=counter result.tail=42 level=INFO msg="store operation" key=timeout result.head=timeout result.tail=30
func (Pair[L, R]) String ¶
func (p Pair[L, R]) String() string
String prints some debug info for the object
Example ¶
ExamplePair_String demonstrates the fmt.Stringer interface implementation.
package main
import (
"fmt"
P "github.com/IBM/fp-go/v2/pair"
)
func main() {
p1 := P.MakePair("username", 42)
p2 := P.MakePair(100, "active")
fmt.Println(p1.String())
fmt.Println(p2.String())
}
Output: Pair[string, int](username, 42) Pair[int, string](100, active)
type Semigroup ¶
Semigroup is a type alias for semigroup.Semigroup. A Semigroup represents an algebraic structure with an associative binary operation. It is used in various Pair operations to combine values when chaining or applying operations that need to merge the head or tail values.
Example:
import N "github.com/IBM/fp-go/v2/number" intSum := N.SemigroupSum[int]() // Combines integers by addition
type Tuple2 ¶
Tuple2 is a type alias for tuple.Tuple2. It represents a 2-tuple with two values. Pairs can be converted to and from Tuple2 using the FromTuple and ToTuple functions.
Example:
t := tuple.MakeTuple2("hello", 42)
p := pair.FromTuple(t) // Convert Tuple2 to Pair
func ToTuple ¶
func ToTuple[A, B any](t Pair[A, B]) Tuple2[A, B]
ToTuple creates a Tuple2 from a Pair. The head becomes the first element, and the tail becomes the second element.
Example:
p := pair.MakePair("hello", 42)
t := pair.ToTuple(p) // Tuple2[string, int]{"hello", 42}
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/pair"
)
func main() {
p := pair.MakePair("hello", 42)
t := pair.ToTuple(p)
fmt.Println(t)
}
Output: Tuple2[string, int](hello, 42)