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

Constant

Constant functor for advanced functional patterns. Always returns the same value, ignoring transformations. Used primarily with optics and traversals.

01

Overview

Constant is a functor that ignores transformations and always holds the same value:

  • Phantom type: Type parameter A is not used
  • Immutable: Value never changes
  • Optics: Essential for traversals and folds
type_definition.go
package constant

// Constant ignores type parameter A
type Constant[C, A any] = C

When to Use

Use CaseExample
OpticsTraversals, folds, getters
AccumulationCollecting values during traversal
Phantom typesType-level programming
Advanced patternsApplicative functors
02

Core API

Constructors

FunctionSignatureDescription
Offunc Of[C, A any](value C) Constant[C, A]Create constant with phantom type
MakeOffunc MakeOf[C, A any]() func(C) Constant[C, A]Constructor factory

Transformations

FunctionSignatureDescription
Mapfunc Map[C, A, B any](f func(A) B) func(Constant[C, A]) Constant[C, B]No-op transformation (value unchanged)
Apfunc Ap[C, A, B any](fa Constant[C, A]) func(Constant[C, func(A) B]) Constant[C, B]Applicative apply (combines C values)

Extraction

FunctionSignatureDescription
Unwrapfunc Unwrap[C, A any](c Constant[C, A]) CExtract the constant value
03

Usage Examples

Basic Operations

basic.go
package main

import (
  "fmt"
  C "github.com/IBM/fp-go/v2/constant"
)

func main() {
  // Create constant with phantom type
  c := C.Of[string, int]("hello")
  // c is "hello", int type is phantom
  
  // Map does nothing (constant stays the same)
  mapped := C.Map[string, int, bool](func(n int) bool {
      return n > 0
  })(c)
  
  // Value is still "hello"
  fmt.Println(C.Unwrap(mapped)) // "hello"
}

With Monoids

monoid.go
package main

import (
  C "github.com/IBM/fp-go/v2/constant"
  M "github.com/IBM/fp-go/v2/monoid"
)

func main() {
  // Combine constants using monoid
  c1 := C.Of[string, int]("hello")
  c2 := C.Of[string, int](" world")
  
  // Use string monoid to combine
  combined := M.Concat(M.String)(
      C.Unwrap(c1),
      C.Unwrap(c2),
  )
  
  fmt.Println(combined) // "hello world"
}

Accumulation Pattern

accumulation.go
package main

import (
  C "github.com/IBM/fp-go/v2/constant"
  M "github.com/IBM/fp-go/v2/monoid"
)

type User struct {
  Name  string
  Email string
  Age   int
}

// Collect all string fields
func collectStrings(u User) C.Constant[[]string, User] {
  return C.Of[[]string, User]([]string{u.Name, u.Email})
}

func main() {
  users := []User{
      {Name: "Alice", Email: "alice@example.com", Age: 30},
      {Name: "Bob", Email: "bob@example.com", Age: 25},
  }
  
  // Accumulate all strings
  var allStrings []string
  for _, u := range users {
      c := collectStrings(u)
      allStrings = append(allStrings, C.Unwrap(c)...)
  }
  
  fmt.Println(allStrings)
  // ["Alice", "alice@example.com", "Bob", "bob@example.com"]
}

With Optics

optics.go
package main

import (
  C "github.com/IBM/fp-go/v2/constant"
  M "github.com/IBM/fp-go/v2/monoid"
)

type Config struct {
  Host string
  Port int
  SSL  bool
}

// Fold over structure, collecting values
func foldConfig(cfg Config) C.Constant[string, Config] {
  summary := fmt.Sprintf("Host: %s, Port: %d", cfg.Host, cfg.Port)
  return C.Of[string, Config](summary)
}

func main() {
  cfg := Config{Host: "localhost", Port: 8080, SSL: true}
  
  result := foldConfig(cfg)
  fmt.Println(C.Unwrap(result))
  // "Host: localhost, Port: 8080"
}
04

Common Patterns

Pattern 1: Traversal Accumulation

traversal.go
package main

import (
  C "github.com/IBM/fp-go/v2/constant"
  M "github.com/IBM/fp-go/v2/monoid"
)

// Traverse and accumulate
func sumFields(data []int) C.Constant[int, []int] {
  sum := 0
  for _, n := range data {
      sum += n
  }
  return C.Of[int, []int](sum)
}

func main() {
  data := []int{1, 2, 3, 4, 5}
  result := sumFields(data)
  
  fmt.Println(C.Unwrap(result)) // 15
}

Pattern 2: Type-Safe Getters

getters.go
package main

import (
  C "github.com/IBM/fp-go/v2/constant"
)

type Person struct {
  Name string
  Age  int
}

// Getter using Constant
func getName(p Person) C.Constant[string, Person] {
  return C.Of[string, Person](p.Name)
}

func getAge(p Person) C.Constant[int, Person] {
  return C.Of[int, Person](p.Age)
}

func main() {
  person := Person{Name: "Alice", Age: 30}
  
  name := C.Unwrap(getName(person))
  age := C.Unwrap(getAge(person))
  
  fmt.Printf("%s is %d years old
", name, age)
}

Pattern 3: Validation Accumulation

validation.go
package main

import (
  C "github.com/IBM/fp-go/v2/constant"
)

type ValidationError struct {
  Field   string
  Message string
}

func validateUser(u User) C.Constant[[]ValidationError, User] {
  var errors []ValidationError
  
  if u.Name == "" {
      errors = append(errors, ValidationError{
          Field:   "name",
          Message: "name is required",
      })
  }
  
  if u.Age < 18 {
      errors = append(errors, ValidationError{
          Field:   "age",
          Message: "must be 18 or older",
      })
  }
  
  return C.Of[[]ValidationError, User](errors)
}

Advanced Usage: Constant is primarily used in advanced functional programming patterns, particularly with optics (lenses, prisms, traversals). For most use cases, consider simpler types like Option, Result, or Either.