optics

package module
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Feb 5, 2025 License: MIT Imports: 4 Imported by: 9

README

Optics (optics)

Lenses resembles concept of getters and setters, which you can compose using functional concepts. In other words, "a lens is a first-class value that combines two operations: viewing (or getting) a subpart of a data structure, and updating (or setting) that part".

Lenses solves Golang challenge "abstraction over structure fields".

The lens is defined following approaches of Haskell library, and techniques references by [1]:

type Lens[S, A any] interface {
  Get(*S) A
  Put(*S, A) *S
}

The module implements Well behaving lenses so that it satisfies three laws:

  • GetPut If we get focused element A from S and immediately put A with no modifications back into S, we must get back exactly S.
  • PutGet If putting A inside S yields a new S, then the A obtained from S is exactly A.
  • PutPut A sequence of two puts is just the effect of the second, the first is completely overwritten. This law is applicable to every well behaving lenses.

Ω-lenses Lens fails if focus is not exists. Ω-lenses (Prism) are capable to recover a create a new container `Ss from nothing. The Ω-lenses are usable for practical application to construct nested data type but they are not well behaving. Ω-lenses (Prism) are not supported yet by the module.

The module unfolds product type (e.g. structs) into sequence of lenses, while preserving the original type witness.

type S struct { /* ... */ } ⇒ optics.Lens[S, A] × ... × Lens[S, X any]

The module is an enabler for building generic algorithms over equivalent types avoiding repetition.

Getting Started

// Given a product type S : A × ... × X
type S struct {
  A A
  ...
  X X
}

// build instance of lenses
var a, x = optics.ForProduct2[S, A, X]()

The lenses is type safe getters and setters derived from the product type. Absence of macros in Golang, does not allow us to make a compile type definition of lenses. It is a runtime instance but annotated with original type S, which makes it compile type safe. The lens optics.Lens[S, A] uniquely identify typed member of original product type. It usage in other context causes compile time error. The module provides helper function ForProduct1 ... ForProduct9 to automatically derive lense from the struct.

type T struct {
  A A
  B B
  C B
}

var (
  // build lense using only type hint A
  a = optics.ForProduct1[T, A]()
  // build lense using type and name hint "B" 
  b = optics.ForProduct1[T, B]("B")
)

Quick Example

The most simplest example that shows the applicability of optics abstraction is building generic algorithm that abstracts structure fields

// Declare type and its lenses (getters & setter)
type User struct {
  Name    string
  Updated time.Time
}

var userT = optics.ForProduct1[User, time.Time]()

type City struct {
  Name    string
  Updated time.Time
}

var cityT = optics.ForProduct1[City, time.Time]()

// Generic algorithm that modifies struct fields
func show[T any](updated optics.Lens[T, time.Time], v *T) {
  if t := updated.Get(v); t.IsZero() {
    updated.Put(v, time.Now())
  }

  b, _ := json.MarshalIndent(v, "", "  ")
  fmt.Println(string(b))
}

func main() {
  show(userT, &User{Name: "user"})
  show(cityT, &City{Name: "city"})
}

See runnable examples to play with the library

Changelog

  • optics/v0.10 and earlier uses reflect
  • optics/v0.11 and later uses unsafe pointers
  • optics/v0.12 isomorphism
  • optics/v0.13 auto bimap for superset category

References

  1. Combinators for Bi-Directional Tree Transformations: A Linguistic Approach to the View Update Problem

Documentation

Index

Constants

View Source
const Version = "optics/v0.14.0"

Variables

This section is empty.

Functions

func ForProduct2

func ForProduct2[T, A, B any](attr ...string) (
	Lens[T, A],
	Lens[T, B],
)

ForProduct2 unfold 2 attribute of type T

func ForProduct3

func ForProduct3[T, A, B, C any](attr ...string) (
	Lens[T, A],
	Lens[T, B],
	Lens[T, C],
)

ForProduct3 unfold 3 attribute of type T

func ForProduct4

func ForProduct4[T, A, B, C, D any](attr ...string) (
	Lens[T, A],
	Lens[T, B],
	Lens[T, C],
	Lens[T, D],
)

ForProduct4 unfold 4 attribute of type T

func ForProduct5

func ForProduct5[T, A, B, C, D, E any](attr ...string) (
	Lens[T, A],
	Lens[T, B],
	Lens[T, C],
	Lens[T, D],
	Lens[T, E],
)

ForProduct5 unfold 5 attribute of type T

func ForProduct6

func ForProduct6[T, A, B, C, D, E, F any](attr ...string) (
	Lens[T, A],
	Lens[T, B],
	Lens[T, C],
	Lens[T, D],
	Lens[T, E],
	Lens[T, F],
)

ForProduct6 unfold 6 attribute of type T

func ForProduct7

func ForProduct7[T, A, B, C, D, E, F, G any](attr ...string) (
	Lens[T, A],
	Lens[T, B],
	Lens[T, C],
	Lens[T, D],
	Lens[T, E],
	Lens[T, F],
	Lens[T, G],
)

ForProduct7 unfold 7 attribute of type T

func ForProduct8

func ForProduct8[T, A, B, C, D, E, F, G, H any](attr ...string) (
	Lens[T, A],
	Lens[T, B],
	Lens[T, C],
	Lens[T, D],
	Lens[T, E],
	Lens[T, F],
	Lens[T, G],
	Lens[T, H],
)

ForProduct8 unfold 8 attribute of type T

func ForProduct9

func ForProduct9[T, A, B, C, D, E, F, G, H, I any](attr ...string) (
	Lens[T, A],
	Lens[T, B],
	Lens[T, C],
	Lens[T, D],
	Lens[T, E],
	Lens[T, F],
	Lens[T, G],
	Lens[T, H],
	Lens[T, I],
)

ForProduct9 unfold 9 attribute of type T

func ForSpectrum2 added in v0.11.2

func ForSpectrum2[T, A, B any](attr ...string) (
	Reflector[A],
	Reflector[B],
)

ForSpectrum2 unfold 2 attribute of type T

func ForSpectrum3 added in v0.11.2

func ForSpectrum3[T, A, B, C any](attr ...string) (
	Reflector[A],
	Reflector[B],
	Reflector[C],
)

ForSpectrum3 unfold 3 attribute of type T

func ForSpectrum4 added in v0.11.2

func ForSpectrum4[T, A, B, C, D any](attr ...string) (
	Reflector[A],
	Reflector[B],
	Reflector[C],
	Reflector[D],
)

ForSpectrum4 unfold 4 attribute of type T

func ForSpectrum5 added in v0.11.2

func ForSpectrum5[T, A, B, C, D, E any](attr ...string) (
	Reflector[A],
	Reflector[B],
	Reflector[C],
	Reflector[D],
	Reflector[E],
)

ForSpectrum5 unfold 5 attribute of type T

func ForSpectrum6 added in v0.11.2

func ForSpectrum6[T, A, B, C, D, E, F any](attr ...string) (
	Reflector[A],
	Reflector[B],
	Reflector[C],
	Reflector[D],
	Reflector[E],
	Reflector[F],
)

ForSpectrum6 unfold 6 attribute of type T

func ForSpectrum7 added in v0.11.2

func ForSpectrum7[T, A, B, C, D, E, F, G any](attr ...string) (
	Reflector[A],
	Reflector[B],
	Reflector[C],
	Reflector[D],
	Reflector[E],
	Reflector[F],
	Reflector[G],
)

ForSpectrum7 unfold 7 attribute of type T

func ForSpectrum8 added in v0.11.2

func ForSpectrum8[T, A, B, C, D, E, F, G, H any](attr ...string) (
	Reflector[A],
	Reflector[B],
	Reflector[C],
	Reflector[D],
	Reflector[E],
	Reflector[F],
	Reflector[G],
	Reflector[H],
)

ForSpectrum8 unfold 8 attribute of type T

func ForSpectrum9 added in v0.11.2

func ForSpectrum9[T, A, B, C, D, E, F, G, H, I any](attr ...string) (
	Reflector[A],
	Reflector[B],
	Reflector[C],
	Reflector[D],
	Reflector[E],
	Reflector[F],
	Reflector[G],
	Reflector[H],
	Reflector[I],
)

ForSpectrum9 unfold 9 attribute of type T

Types

type Byte added in v0.13.1

type Byte interface {
	~[]byte
}

type Float added in v0.13.1

type Float interface {
	~float32 | ~float64
}

type Int added in v0.13.1

type Int interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64
}

type Isomorphism added in v0.12.0

type Isomorphism[S, T any] interface {
	Forward(*S, *T)
	Inverse(*T, *S)
}

An isomorphism is a structure-preserving mapping between two structures of the same shape that can be reversed by an inverse mapping.

func Iso added in v0.12.0

func Iso[S, T, A any](
	sa Lens[S, A],
	ta Lens[T, A],
) Isomorphism[S, T]

Building Isomorphism from joining lenses

func Morphism

func Morphism[S, T any](seq ...Isomorphism[S, T]) Isomorphism[S, T]

Build a structure-preserving mapping between two structures

type Lens

type Lens[S, A any] interface {
	Get(*S) A
	Put(*S, A) *S
}

Lens resembles concept of getters and setters, which you can compose using functional concepts. In other words, this is combinator data transformation for pure functional data structure.

Lens allows to abstract a "shape" of the structure rather than type itself.

func BiMap added in v0.13.0

func BiMap[S, A, B any](
	lens Lens[S, A],
	fmap func(A) B,
	cmap func(B) A,
) Lens[S, B]

Transformer lens is a structure-preserving mapping between two categories A, B.

func BiMapB added in v0.13.1

func BiMapB[S any, A, B Byte](attr ...string) Lens[S, B]

Automatic transformer for []byte superset, preserve mapping between two categories A, B, where both rooted to []byte

func BiMapF added in v0.13.1

func BiMapF[S any, A, B Float](attr ...string) Lens[S, B]

Automatic transformer for float32 superset, preserve mapping between two categories A, B, where both rooted to float

func BiMapI added in v0.13.1

func BiMapI[S any, A, B Int](attr ...string) Lens[S, B]

Automatic transformer for int superset, preserve mapping between two categories A, B, where both rooted to int

func BiMapS added in v0.13.1

func BiMapS[S any, A, B String](attr ...string) Lens[S, B]

Automatic transformer for string superset, preserve mapping between two categories A, B, where both rooted to strings

func ForProduct1

func ForProduct1[T, A any](attr ...string) Lens[T, A]

ForProduct1 unfold 1 attribute of type T

func Getter added in v0.13.0

func Getter[S, A, B any](lens Lens[S, A], f func(A) B) Lens[S, B]

Getter composes lense with transform function, making read-only lense

func Join added in v0.13.0

func Join[S, A, B any](a Lens[S, A], b Lens[A, B]) Lens[S, B]

func NewLens

func NewLens[S, A any](t hseq.Type[S]) Lens[S, A]

NewLens instantiates a typed Lens[S, A] for hseq.Type[S]

func NewLensM added in v0.13.0

func NewLensM[S interface{ ~map[K]A }, K comparable, A any](key K) Lens[S, A]

NewLens instantiates a typed Lens[S, A] for map[K]A

func Setter added in v0.13.0

func Setter[S, A, B any](lens Lens[S, A], f func(B) A) Lens[S, B]

Setter composes lense with inverse transformer, making write-only lense

type Lens2 added in v0.11.0

type Lens2[S, A, B any] interface {
	Get(*S) (A, B)
	Put(*S, A, B) *S
}

Rank 2 Shape: Product Lens A × B

func ForShape2 added in v0.11.0

func ForShape2[T, A, B any](attr ...string) Lens2[T, A, B]

Rank 2 Shape: Product Lens A × B

type Lens3 added in v0.11.0

type Lens3[S, A, B, C any] interface {
	Get(*S) (A, B, C)
	Put(*S, A, B, C) *S
}

Rank 3 Shape: Product Lens A × B × C

func ForShape3 added in v0.11.0

func ForShape3[T, A, B, C any](attr ...string) Lens3[T, A, B, C]

Rank 3 Shape: Product Lens A × B × C

type Lens4 added in v0.11.0

type Lens4[S, A, B, C, D any] interface {
	Get(*S) (A, B, C, D)
	Put(*S, A, B, C, D) *S
}

Rank 4 Shape: Product Lens A × B × C × D

func ForShape4 added in v0.11.0

func ForShape4[T, A, B, C, D any](attr ...string) Lens4[T, A, B, C, D]

Rank 4 Shape: Product Lens A × B × C × D

type Lens5 added in v0.11.0

type Lens5[S, A, B, C, D, E any] interface {
	Get(*S) (A, B, C, D, E)
	Put(*S, A, B, C, D, E) *S
}

Rank 5 Shape: Product Lens A × B × C × D × E

func ForShape5 added in v0.11.0

func ForShape5[T, A, B, C, D, E any](attr ...string) Lens5[T, A, B, C, D, E]

Rank 5 Shape: Product Lens A × B × C × D × E

type Lens6 added in v0.11.0

type Lens6[S, A, B, C, D, E, F any] interface {
	Get(*S) (A, B, C, D, E, F)
	Put(*S, A, B, C, D, E, F) *S
}

Rank 6 Shape: Product Lens A × B × C × D × E × F

func ForShape6 added in v0.11.0

func ForShape6[T, A, B, C, D, E, F any](attr ...string) Lens6[T, A, B, C, D, E, F]

Rank 6 Shape: Product Lens A × B × C × D × E × F

type Lens7 added in v0.11.0

type Lens7[S, A, B, C, D, E, F, G any] interface {
	Get(*S) (A, B, C, D, E, F, G)
	Put(*S, A, B, C, D, E, F, G) *S
}

Rank 7 Shape: Product Lens A × B × C × D × E × F × G

func ForShape7 added in v0.11.0

func ForShape7[T, A, B, C, D, E, F, G any](attr ...string) Lens7[T, A, B, C, D, E, F, G]

Rank 7 Shape: Product Lens A × B × C × D × E × F × G

type Lens8 added in v0.11.0

type Lens8[S, A, B, C, D, E, F, G, H any] interface {
	Get(*S) (A, B, C, D, E, F, G, H)
	Put(*S, A, B, C, D, E, F, G, H) *S
}

Rank 8 Shape: Product Lens A × B × C × D × E × F × G × H

func ForShape8 added in v0.11.0

func ForShape8[T, A, B, C, D, E, F, G, H any](attr ...string) Lens8[T, A, B, C, D, E, F, G, H]

Rank 8 Shape: Product Lens A × B × C × D × E × F × G × H

type Lens9 added in v0.11.0

type Lens9[S, A, B, C, D, E, F, G, H, I any] interface {
	Get(*S) (A, B, C, D, E, F, G, H, I)
	Put(*S, A, B, C, D, E, F, G, H, I) *S
}

Rank 9 Shape: Product Lens A × B × C × D × E × F × G × H × I

func ForShape9 added in v0.11.0

func ForShape9[T, A, B, C, D, E, F, G, H, I any](attr ...string) Lens9[T, A, B, C, D, E, F, G, H, I]

Rank 9 Shape: Product Lens A × B × C × D × E × F × G × H × I

type Reflector

type Reflector[A any] interface {
	Gett(any) A
	Putt(any, A) any
}

Reflector is a Reflector over value of any type. It fails runtime if client submits invalid type.

func ForSpectrum1 added in v0.11.2

func ForSpectrum1[T, A any](attr ...string) Reflector[A]

ForSpectrum1 unfold 1 attribute of type T

func NewReflector added in v0.11.2

func NewReflector[S, A any](t hseq.Type[S]) Reflector[A]

NewReflector instantiates a typed Reflector[S, A] for hseq.Type[S]

type String added in v0.13.1

type String interface {
	~string
}

Directories

Path Synopsis
examples module

Jump to

Keyboard shortcuts

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