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
fromS
and immediately putA
with no modifications back intoS
, we must get back exactlyS
. - PutGet If putting
A
insideS
yields a newS
, then theA
obtained fromS
is exactlyA
. - 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
- basic lense usage
- abstract shape of types, see problem statement Abstract over Golang structure fields using optics for details.
- abstract shape of types (advanced)
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
Documentation
¶
Index ¶
- Constants
- func ForProduct2[T, A, B any](attr ...string) (Lens[T, A], Lens[T, B])
- func ForProduct3[T, A, B, C any](attr ...string) (Lens[T, A], Lens[T, B], Lens[T, C])
- func ForProduct4[T, A, B, C, D any](attr ...string) (Lens[T, A], Lens[T, B], Lens[T, C], Lens[T, D])
- 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])
- 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])
- 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], ...)
- 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], ...)
- 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], ...)
- func ForSpectrum2[T, A, B any](attr ...string) (Reflector[A], Reflector[B])
- func ForSpectrum3[T, A, B, C any](attr ...string) (Reflector[A], Reflector[B], Reflector[C])
- func ForSpectrum4[T, A, B, C, D any](attr ...string) (Reflector[A], Reflector[B], Reflector[C], Reflector[D])
- func ForSpectrum5[T, A, B, C, D, E any](attr ...string) (Reflector[A], Reflector[B], Reflector[C], Reflector[D], Reflector[E])
- func ForSpectrum6[T, A, B, C, D, E, F any](attr ...string) (Reflector[A], Reflector[B], Reflector[C], Reflector[D], Reflector[E], ...)
- func ForSpectrum7[T, A, B, C, D, E, F, G any](attr ...string) (Reflector[A], Reflector[B], Reflector[C], Reflector[D], Reflector[E], ...)
- func ForSpectrum8[T, A, B, C, D, E, F, G, H any](attr ...string) (Reflector[A], Reflector[B], Reflector[C], Reflector[D], Reflector[E], ...)
- 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], ...)
- type Byte
- type Float
- type Int
- type Isomorphism
- type Lens
- func BiMap[S, A, B any](lens Lens[S, A], fmap func(A) B, cmap func(B) A) Lens[S, B]
- func BiMapB[S any, A, B Byte](attr ...string) Lens[S, B]
- func BiMapF[S any, A, B Float](attr ...string) Lens[S, B]
- func BiMapI[S any, A, B Int](attr ...string) Lens[S, B]
- func BiMapS[S any, A, B String](attr ...string) Lens[S, B]
- func ForProduct1[T, A any](attr ...string) Lens[T, A]
- func Getter[S, A, B any](lens Lens[S, A], f func(A) B) Lens[S, B]
- func Join[S, A, B any](a Lens[S, A], b Lens[A, B]) Lens[S, B]
- func NewLens[S, A any](t hseq.Type[S]) Lens[S, A]
- func NewLensM[S interface{ ... }, K comparable, A any](key K) Lens[S, A]
- func Setter[S, A, B any](lens Lens[S, A], f func(B) A) Lens[S, B]
- type Lens2
- type Lens3
- type Lens4
- type Lens5
- type Lens6
- type Lens7
- type Lens8
- type Lens9
- type Reflector
- type String
Constants ¶
const Version = "optics/v0.14.0"
Variables ¶
This section is empty.
Functions ¶
func ForProduct2 ¶
ForProduct2 unfold 2 attribute of type T
func ForProduct3 ¶
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
ForSpectrum2 unfold 2 attribute of type T
func ForSpectrum3 ¶ added in v0.11.2
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
Types ¶
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
Transformer lens is a structure-preserving mapping between two categories A, B.
func BiMapB ¶ added in v0.13.1
Automatic transformer for []byte superset, preserve mapping between two categories A, B, where both rooted to []byte
func BiMapF ¶ added in v0.13.1
Automatic transformer for float32 superset, preserve mapping between two categories A, B, where both rooted to float
func BiMapI ¶ added in v0.13.1
Automatic transformer for int superset, preserve mapping between two categories A, B, where both rooted to int
func BiMapS ¶ added in v0.13.1
Automatic transformer for string superset, preserve mapping between two categories A, B, where both rooted to strings
func ForProduct1 ¶
ForProduct1 unfold 1 attribute of type T
func Getter ¶ added in v0.13.0
Getter composes lense with transform function, making read-only lense
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
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
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
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
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
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
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
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
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
type Reflector ¶
Reflector is a Reflector over value of any type. It fails runtime if client submits invalid type.
func ForSpectrum1 ¶ added in v0.11.2
ForSpectrum1 unfold 1 attribute of type T