Documentation
¶
Overview ¶
Package predicate provides functional programming utilities for working with predicates.
A predicate is a function that takes a value and returns a boolean, commonly used for filtering, validation, and conditional logic. This package offers combinators for composing predicates using logical operations (And, Or, Not), transforming predicates via ContraMap, and combining multiple predicates using Semigroup and Monoid abstractions.
Key features:
- Boolean combinators: And, Or, Not
- ContraMap for transforming predicates
- Semigroup and Monoid instances for combining predicates
Example usage:
import P "github.com/IBM/fp-go/v2/predicate"
// Create predicates
isPositive := func(n int) bool { return n > 0 }
isEven := func(n int) bool { return n%2 == 0 }
// Combine predicates
isPositiveAndEven := F.Pipe1(isPositive, P.And(isEven))
isPositiveOrEven := F.Pipe1(isPositive, P.Or(isEven))
isNotPositive := P.Not(isPositive)
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Kleisli ¶
func IsEqual ¶
IsEqual creates a Kleisli arrow that tests if two values are equal using a custom equality function.
This function takes an Eq instance (which defines how to compare values of type A) and returns a curried function that can be used to create predicates for equality testing.
Parameters:
- pred: An Eq[A] instance that defines equality for type A
Returns:
- A Kleisli[A, A] that takes a value and returns a predicate testing equality with that value
Example:
type Person struct { Name string; Age int }
personEq := eq.MakeEq(func(a, b Person) bool {
return a.Name == b.Name && a.Age == b.Age
})
isEqualToPerson := IsEqual(personEq)
alice := Person{Name: "Alice", Age: 30}
isAlice := isEqualToPerson(alice)
isAlice(Person{Name: "Alice", Age: 30}) // true
isAlice(Person{Name: "Bob", Age: 30}) // false
func IsStrictEqual ¶
func IsStrictEqual[A comparable]() Kleisli[A, A]
IsStrictEqual creates a Kleisli arrow that tests if two values are equal using Go's == operator.
This is a convenience function for comparable types that uses strict equality (==) for comparison. It's equivalent to IsEqual with an Eq instance based on ==.
Returns:
- A Kleisli[A, A] that takes a value and returns a predicate testing strict equality
Example:
isEqualTo5 := IsStrictEqual[int]()(5)
isEqualTo5(5) // true
isEqualTo5(10) // false
isEqualToHello := IsStrictEqual[string]()("hello")
isEqualToHello("hello") // true
isEqualToHello("world") // false
type Monoid ¶
Monoid represents a monoid instance for predicates, extending Semigroup with an identity element (empty predicate).
func MonoidAll ¶
func MonoidAll[A any]() Monoid[A]
MonoidAll creates a monoid that combines predicates using logical AND (&&).
This extends SemigroupAll with an identity element: a predicate that always returns true. The identity element satisfies the property that combining it with any predicate p yields p. This is useful for folding/reducing a collection of predicates where an empty collection should result in a predicate that always returns true.
Returns:
- A Monoid[A] that combines predicates with AND logic and has true as identity
Example:
m := MonoidAll[int]()
predicates := []Predicate[int]{
func(n int) bool { return n > 0 },
func(n int) bool { return n < 100 },
}
combined := A.Reduce(m.Empty(), m.Concat)(predicates)
combined(50) // true (both conditions)
combined(-5) // false (not > 0)
combined(150) // false (not < 100)
func MonoidAny ¶
func MonoidAny[A any]() Monoid[A]
MonoidAny creates a monoid that combines predicates using logical OR (||).
This extends SemigroupAny with an identity element: a predicate that always returns false. The identity element satisfies the property that combining it with any predicate p yields p. This is useful for folding/reducing a collection of predicates where an empty collection should result in a predicate that always returns false.
Returns:
- A Monoid[A] that combines predicates with OR logic and has false as identity
Example:
m := MonoidAny[int]()
predicates := []Predicate[int]{
func(n int) bool { return n > 10 },
func(n int) bool { return n < 0 },
}
combined := A.Reduce(m.Empty(), m.Concat)(predicates)
combined(15) // true (> 10)
combined(-5) // true (< 0)
combined(5) // false (neither)
type Operator ¶
Operator represents a function that transforms a Predicate[A] into a Predicate[B]. This is useful for composing and transforming predicates.
func And ¶
And creates an operator that combines two predicates using logical AND (&&).
The resulting predicate returns true only if both the first and second predicates return true. This function is curried, taking the second predicate first and returning an operator that takes the first predicate.
Example:
isPositive := func(n int) bool { return n > 0 }
isEven := func(n int) bool { return n%2 == 0 }
isPositiveAndEven := F.Pipe1(isPositive, And(isEven))
isPositiveAndEven(4) // true
isPositiveAndEven(-2) // false
isPositiveAndEven(3) // false
Example ¶
package main
import (
"fmt"
F "github.com/IBM/fp-go/v2/function"
"github.com/IBM/fp-go/v2/predicate"
)
func main() {
isPositive := func(n int) bool { return n > 0 }
isEven := func(n int) bool { return n%2 == 0 }
isPositiveAndEven := F.Pipe1(isPositive, predicate.And(isEven))
fmt.Println(isPositiveAndEven(4))
fmt.Println(isPositiveAndEven(-2))
fmt.Println(isPositiveAndEven(3))
}
Output: true false false
func ContraMap ¶
func ContraMap[A, B any](f func(B) A) Operator[A, B]
ContraMap creates a new predicate by transforming the input before applying an existing predicate.
This is a contravariant functor operation that allows you to adapt a predicate for type A to work with type B by providing a function that converts B to A. The resulting predicate first applies the mapping function f to transform the input, then applies the original predicate.
This is particularly useful when you have a predicate for one type and want to reuse it for a related type without rewriting the predicate logic.
Parameters:
- f: A function that converts values of type B to type A
Returns:
- An Operator that transforms a Predicate[A] into a Predicate[B]
Example:
type Person struct { Age int }
isAdult := func(age int) bool { return age >= 18 }
getAge := func(p Person) int { return p.Age }
isPersonAdult := F.Pipe1(isAdult, ContraMap(getAge))
isPersonAdult(Person{Age: 25}) // true
isPersonAdult(Person{Age: 15}) // false
Example ¶
package main
import (
"fmt"
F "github.com/IBM/fp-go/v2/function"
"github.com/IBM/fp-go/v2/predicate"
)
func main() {
type Person struct{ Age int }
isAdult := func(age int) bool { return age >= 18 }
getAge := func(p Person) int { return p.Age }
isPersonAdult := F.Pipe1(isAdult, predicate.ContraMap(getAge))
fmt.Println(isPersonAdult(Person{Age: 25}))
fmt.Println(isPersonAdult(Person{Age: 15}))
}
Output: true false
func Or ¶
Or creates an operator that combines two predicates using logical OR (||).
The resulting predicate returns true if either the first or second predicate returns true. This function is curried, taking the second predicate first and returning an operator that takes the first predicate.
Example:
isPositive := func(n int) bool { return n > 0 }
isEven := func(n int) bool { return n%2 == 0 }
isPositiveOrEven := F.Pipe1(isPositive, Or(isEven))
isPositiveOrEven(4) // true
isPositiveOrEven(-2) // true
isPositiveOrEven(3) // true
isPositiveOrEven(-3) // false
Example ¶
package main
import (
"fmt"
F "github.com/IBM/fp-go/v2/function"
"github.com/IBM/fp-go/v2/predicate"
)
func main() {
isPositive := func(n int) bool { return n > 0 }
isEven := func(n int) bool { return n%2 == 0 }
isPositiveOrEven := F.Pipe1(isPositive, predicate.Or(isEven))
fmt.Println(isPositiveOrEven(4))
fmt.Println(isPositiveOrEven(-2))
fmt.Println(isPositiveOrEven(3))
fmt.Println(isPositiveOrEven(-3))
}
Output: true true true false
type Predicate ¶
Predicate represents a function that tests a value of type A and returns a boolean. It is commonly used for filtering, validation, and conditional logic.
func IsNonZero ¶
func IsNonZero[A comparable]() Predicate[A]
IsNonZero creates a predicate that tests if a value is not equal to the zero value for its type.
This is the negation of IsZero, returning true for any non-zero value.
Returns:
- A Predicate[A] that returns true if the value is not the zero value for type A
Example:
isNonZeroInt := IsNonZero[int]()
isNonZeroInt(0) // false
isNonZeroInt(5) // true
isNonZeroInt(-3) // true
isNonZeroString := IsNonZero[string]()
isNonZeroString("") // false
isNonZeroString("hello") // true
isNonZeroPtr := IsNonZero[*int]()
isNonZeroPtr(nil) // false
isNonZeroPtr(new(int)) // true
func IsZero ¶
func IsZero[A comparable]() Predicate[A]
IsZero creates a predicate that tests if a value equals the zero value for its type.
The zero value is the default value for a type in Go (e.g., 0 for int, "" for string, false for bool, nil for pointers, etc.).
Returns:
- A Predicate[A] that returns true if the value is the zero value for type A
Example:
isZeroInt := IsZero[int]()
isZeroInt(0) // true
isZeroInt(5) // false
isZeroString := IsZero[string]()
isZeroString("") // true
isZeroString("hello") // false
isZeroBool := IsZero[bool]()
isZeroBool(false) // true
isZeroBool(true) // false
func Not ¶
Not negates a predicate, returning a new predicate that returns the opposite boolean value.
Given a predicate that returns true for some input, Not returns a predicate that returns false for the same input, and vice versa.
Example:
isPositive := func(n int) bool { return n > 0 }
isNotPositive := Not(isPositive)
isNotPositive(5) // false
isNotPositive(-3) // true
Example ¶
package main
import (
"fmt"
"github.com/IBM/fp-go/v2/predicate"
)
func main() {
isPositive := func(n int) bool { return n > 0 }
isNotPositive := predicate.Not(isPositive)
fmt.Println(isNotPositive(5))
fmt.Println(isNotPositive(-3))
}
Output: false true
type Semigroup ¶
Semigroup represents a semigroup instance for predicates, providing a way to combine two predicates into one using an associative operation.
func SemigroupAll ¶
SemigroupAll creates a semigroup that combines predicates using logical AND (&&).
When two predicates are combined with this semigroup, the resulting predicate returns true only if both of the original predicates return true. This implements the associative operation for conjunction.
Returns:
- A Semigroup[A] that combines predicates with AND logic
Example:
s := SemigroupAll[int]()
isPositive := func(n int) bool { return n > 0 }
isEven := func(n int) bool { return n%2 == 0 }
isPositiveAndEven := s.Concat(isPositive, isEven)
isPositiveAndEven(4) // true (both)
isPositiveAndEven(3) // false (not even)
isPositiveAndEven(-2) // false (not positive)
isPositiveAndEven(-3) // false (neither)
func SemigroupAny ¶
SemigroupAny creates a semigroup that combines predicates using logical OR (||).
When two predicates are combined with this semigroup, the resulting predicate returns true if either of the original predicates returns true. This implements the associative operation for disjunction.
Returns:
- A Semigroup[A] that combines predicates with OR logic
Example:
s := SemigroupAny[int]()
isPositive := func(n int) bool { return n > 0 }
isEven := func(n int) bool { return n%2 == 0 }
isPositiveOrEven := s.Concat(isPositive, isEven)
isPositiveOrEven(4) // true (even)
isPositiveOrEven(3) // true (positive)
isPositiveOrEven(-2) // true (even)
isPositiveOrEven(-3) // false (neither)