predicate

package
v2.3.95 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

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 := N.MoreThan(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

func Fold added in v2.3.93

func Fold[A, B any](onFalse, onTrue func(A) B) func(Predicate[A]) func(A) B

Fold evaluates a predicate against a value and maps the boolean result to a value of type B.

Given two mapping functions and a predicate, Fold returns a function that, when applied to a value of type A, tests it with the predicate and calls onTrue if the predicate returns true, or onFalse if it returns false. Both branches receive the original input value, so contextual information is preserved regardless of which branch is taken.

Type Parameters:

  • A: The input type tested by the predicate
  • B: The output type produced by both branch functions

Parameters:

  • onFalse: Called with the input value when the predicate returns false
  • onTrue: Called with the input value when the predicate returns true

Returns:

  • A function that takes a Predicate[A] and returns a function from A to B

Relation to option.Fold:

predicate.Fold and option.Fold are two specialisations of the same categorical pattern — eliminating a two-case sum type into a common result type B.

A Predicate[A] is morally equivalent to a function A → bool, where bool is the smallest two-case sum type {false, true}. Because bool carries no payload beyond the branch tag, both handlers must receive A to preserve context:

predicate.Fold :: (A → B) → (A → B) → (A → bool) → A → B

option.Option[A] is a richer two-case sum type {None, Some(A)}. Here the Some constructor already carries the payload, so only the onSome branch needs A; onNone is a thunk:

option.Fold :: (() → B) → (A → B) → Option[A] → B

The link between the two is option.FromPredicate, which converts a Predicate[A] into an Option[A]-producing function. Using it, predicate.Fold can always be expressed in terms of option.Fold and FromPredicate:

predicate.Fold(onFalse, onTrue)(p)(a)
  == option.Fold(func() B { return onFalse(a) }, onTrue)(option.FromPredicate(p)(a))

Conversely, option.Fold cannot in general be expressed via predicate.Fold because option.None carries no A value for the onFalse branch to inspect.

See Also:

  • Predicate: The boolean-valued function type used as the condition
  • option.Fold: The richer analogue that eliminates an Option[A]
  • option.FromPredicate: Converts a Predicate[A] into a Kleisli[A, A] over Option
Example (Basic)

ExampleFold_basic demonstrates eliminating a predicate into a string label.

Both branch functions receive the tested value because the bool tag alone carries no payload — compare with option.ExampleFold where the None branch is a thunk.

package main

import (
	"fmt"

	F "github.com/IBM/fp-go/v2/function"
	N "github.com/IBM/fp-go/v2/number"
	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	isPositive := N.MoreThan(0)
	classify := F.Pipe1(isPositive, predicate.Fold(
		func(n int) string { return "not positive" },
		func(n int) string { return "positive" },
	))
	fmt.Println(classify(5))
	fmt.Println(classify(0))
	fmt.Println(classify(-3))
}
Output:
positive
not positive
not positive
Example (WithValue)

ExampleFold_withValue shows that both branches always receive A, allowing the original value to be used in the result regardless of which branch is taken. This mirrors option.Fold's onSome branch, but predicate.Fold must also pass A to onFalse because the bool tag carries no payload of its own.

package main

import (
	"fmt"

	F "github.com/IBM/fp-go/v2/function"
	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	isEven := func(n int) bool { return n%2 == 0 }
	describe := F.Pipe1(isEven, predicate.Fold(
		func(n int) string { return fmt.Sprintf("%d is odd", n) },
		func(n int) string { return fmt.Sprintf("%d is even", n) },
	))
	fmt.Println(describe(4))
	fmt.Println(describe(7))
}
Output:
4 is even
7 is odd

Types

type Kleisli

type Kleisli[A, B any] = func(A) Predicate[B]

Kleisli represents a function that takes a value of type A and returns a Predicate[B]. This is a Kleisli arrow in the context of predicates, allowing for the creation of parameterized predicates. It's particularly useful for building predicates that depend on some input value, such as equality testing or comparison operations.

Type Parameters:

  • A: The input type for the Kleisli arrow
  • B: The type that the resulting predicate will test

Common uses:

  • IsEqual: Takes a value and returns a predicate testing equality with that value
  • IsStrictEqual: Takes a value and returns a predicate testing strict equality
  • Custom parameterized predicates that depend on configuration or context

See Also:

  • IsEqual: Returns a Kleisli[A, A] for custom equality testing
  • IsStrictEqual: Returns a Kleisli[A, A] for strict equality testing
  • Operator: A specialized Kleisli for transforming predicates

func IsEqual

func IsEqual[A any](pred eq.Eq[A]) Kleisli[A, A]

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

type Monoid[A any] = monoid.Monoid[Predicate[A]]

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]{
    N.MoreThan(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

type Operator[A, B any] = Kleisli[Predicate[A], B]

Operator represents a function that transforms a Predicate[A] into a Predicate[B]. This is useful for composing and transforming predicates.

func And

func And[A any](second Predicate[A]) Operator[A, A]

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 := N.MoreThan(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"
	N "github.com/IBM/fp-go/v2/number"
	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	isPositive := N.MoreThan(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

func Or[A any](second Predicate[A]) Operator[A, A]

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 := N.MoreThan(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"
	N "github.com/IBM/fp-go/v2/number"
	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	isPositive := N.MoreThan(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

type Predicate[A any] = func(A) bool

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 Always added in v2.3.52

func Always[T any]() Predicate[T]

Always creates a predicate that always returns true for any input value.

This is the identity element for the MonoidAll semigroup and represents a predicate that accepts all values. It's useful as a base case when building complex predicates or as a default predicate.

Returns:

  • A Predicate[T] that always returns true

See Also:

  • Never: Creates a predicate that always returns false
  • MonoidAll: Uses Always as its identity element
Example
package main

import (
	"fmt"

	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	alwaysTrue := predicate.Always[int]()
	fmt.Println(alwaysTrue(42))
	fmt.Println(alwaysTrue(-10))
	fmt.Println(alwaysTrue(0))
}
Output:
true
true
true
Example (WithAnd)
package main

import (
	"fmt"

	F "github.com/IBM/fp-go/v2/function"
	N "github.com/IBM/fp-go/v2/number"
	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	isPositive := N.MoreThan(0)
	// Always AND isPositive == isPositive
	combined := F.Pipe1(predicate.Always[int](), predicate.And(isPositive))
	fmt.Println(combined(5))
	fmt.Println(combined(-5))
}
Output:
true
false

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 Never added in v2.3.52

func Never[T any]() Predicate[T]

Never creates a predicate that always returns false for any input value.

This is the identity element for the MonoidAny semigroup and represents a predicate that rejects all values. It's useful as a base case when building complex predicates or as a default predicate.

Returns:

  • A Predicate[T] that always returns false

See Also:

  • Always: Creates a predicate that always returns true
  • MonoidAny: Uses Never as its identity element
Example
package main

import (
	"fmt"

	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	neverTrue := predicate.Never[int]()
	fmt.Println(neverTrue(42))
	fmt.Println(neverTrue(-10))
	fmt.Println(neverTrue(0))
}
Output:
false
false
false
Example (WithOr)
package main

import (
	"fmt"

	F "github.com/IBM/fp-go/v2/function"
	N "github.com/IBM/fp-go/v2/number"
	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	isPositive := N.MoreThan(0)
	// Never OR isPositive == isPositive
	combined := F.Pipe1(predicate.Never[int](), predicate.Or(isPositive))
	fmt.Println(combined(5))
	fmt.Println(combined(-5))
}
Output:
true
false

func Not

func Not[A any](predicate Predicate[A]) Predicate[A]

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 := N.MoreThan(0)
isNotPositive := Not(isPositive)
isNotPositive(5)  // false
isNotPositive(-3) // true
Example
package main

import (
	"fmt"

	N "github.com/IBM/fp-go/v2/number"
	"github.com/IBM/fp-go/v2/predicate"
)

func main() {
	isPositive := N.MoreThan(0)
	isNotPositive := predicate.Not(isPositive)
	fmt.Println(isNotPositive(5))
	fmt.Println(isNotPositive(-3))
}
Output:
false
true

type Semigroup

type Semigroup[A any] = semigroup.Semigroup[Predicate[A]]

Semigroup represents a semigroup instance for predicates, providing a way to combine two predicates into one using an associative operation.

func SemigroupAll

func SemigroupAll[A any]() Semigroup[A]

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 := N.MoreThan(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

func SemigroupAny[A any]() Semigroup[A]

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 := N.MoreThan(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)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL