hseq

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: May 12, 2024 License: MIT Imports: 3 Imported by: 7

README

Heterogenous Sequence of Types (hseq)

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

type T struct { /* ... */ } ⇒ hseq.Seq[T]

It is extension over reflection reflect.StructField but with compile and runtime type safeness even product types have equivalent set of members

type A struct { string }
type B struct { string }

// hseq.Seq[A] != hseq.Seq[B]

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

  • Building an optics abstraction requires definition of Lens[T, A]. The hseq module simplifies the type safe implementation allowing to lift any type A from the product T.
  • Building Domain Specific Language might require exposure of type safe utilities over subset of product attributes.
  • Implement generic and type safe witness of type T (e.g. pair T, A).

Getting Started

// hseq.Seq[T] is equivalent presentation of type T
// both represents product type T
type T struct { /* ... */ }

// make instance of heterogenous sequence
var seq = hseq.New[T]()

The heterogenous sequence is an ordered list of types derived from the product type. Absence of macros in Golang, does not allow us to make a compile type definition of heterogenous sequence. It is a runtime reflection but annotated with original type T, which makes it compile type safe. The sequence consists of hseq.Type[T], which uniquely identify typed member of original product type. The module provides two helper functions ForType/ForName, which lookup heterogenous sequence.

type T struct {
  A A
  B B
}

var (
  // lookup sequence using type hint A
  a = hseq.ForType[T, A](seq)
  // lookup sequence using name hint "B"
  b = hseq.ForName[T](seq, "B")
)

So far, examples above made nothing but unfold (decompose) the product type on individual components. Then, the module implements hseq.FMap1 ... hseq.FMap9 functions to construct type safe representation of the product type A × B × ... × I where the type safe witness is casted per element forming pair T, A.

var a, b = hseq.Map2[T, A, B](seq, /* ... */)

Quick Example

The most simplest example that shows the applicability of hseq abstraction is building generic getter - the function that focuses on struct attribute.

// Getter type just defines a generic function: T ⇒ A  
type Getter[T, A any] struct{ hseq.Type[T] }

func (field Getter[T, A]) Value(s T) A {
	f := reflect.ValueOf(s).FieldByName(field.Name)
	return f.Interface().(A)
}

// Creates type safe instance of Getter 
func NewGetter[T, A any](s hseq.Type[T]) Getter[T, A] {
	hseq.AssertStrict[T, A](s)
	return Getter[T, A]{s}
}

// For given product type Someone
type Someone struct {
  Name string
  Age  int
}

// Getters are defined. 
var name, age = hseq.FMap2(
	hseq.New[Someone](),
	newGetter[Someone, string],
  newGetter[Someone, int]
)

// While Getter is generic but instances are type safe.
// Compiler fails if name is used with other type than Someone and string
name.Value(/* ... */)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Assert

func Assert[T, A any](t Type[T]) (string, reflect.Kind)

Assert equality of type

func AssertStrict

func AssertStrict[T, A any](t Type[T]) (string, reflect.Kind)

Assert strict equality of type

func FMap

func FMap[T, A any](seq Seq[T], f func(Type[T]) A) []A

Transform heterogenous sequence to something else

func FMap1

func FMap1[T, A any](
	ts Seq[T],
	fa func(Type[T]) A,
) A

func FMap2

func FMap2[T, A, B any](
	ts Seq[T],
	fa func(Type[T]) A,
	fb func(Type[T]) B,
) (A, B)

func FMap3

func FMap3[T, A, B, C any](
	ts Seq[T],
	fa func(Type[T]) A,
	fb func(Type[T]) B,
	fc func(Type[T]) C,
) (A, B, C)

func FMap4

func FMap4[T, A, B, C, D any](
	ts Seq[T],
	fa func(Type[T]) A,
	fb func(Type[T]) B,
	fc func(Type[T]) C,
	fd func(Type[T]) D,
) (A, B, C, D)

func FMap5

func FMap5[T, A, B, C, D, E any](
	ts Seq[T],
	fa func(Type[T]) A,
	fb func(Type[T]) B,
	fc func(Type[T]) C,
	fd func(Type[T]) D,
	fe func(Type[T]) E,
) (A, B, C, D, E)

func FMap6

func FMap6[T, A, B, C, D, E, F any](
	ts Seq[T],
	fa func(Type[T]) A,
	fb func(Type[T]) B,
	fc func(Type[T]) C,
	fd func(Type[T]) D,
	fe func(Type[T]) E,
	ff func(Type[T]) F,
) (A, B, C, D, E, F)

func FMap7

func FMap7[T, A, B, C, D, E, F, G any](
	ts Seq[T],
	fa func(Type[T]) A,
	fb func(Type[T]) B,
	fc func(Type[T]) C,
	fd func(Type[T]) D,
	fe func(Type[T]) E,
	ff func(Type[T]) F,
	fg func(Type[T]) G,
) (A, B, C, D, E, F, G)

func FMap8

func FMap8[T, A, B, C, D, E, F, G, H any](
	ts Seq[T],
	fa func(Type[T]) A,
	fb func(Type[T]) B,
	fc func(Type[T]) C,
	fd func(Type[T]) D,
	fe func(Type[T]) E,
	ff func(Type[T]) F,
	fg func(Type[T]) G,
	fh func(Type[T]) H,
) (A, B, C, D, E, F, G, H)

func FMap9

func FMap9[T, A, B, C, D, E, F, G, H, I any](
	ts Seq[T],
	fa func(Type[T]) A,
	fb func(Type[T]) B,
	fc func(Type[T]) C,
	fd func(Type[T]) D,
	fe func(Type[T]) E,
	ff func(Type[T]) F,
	fg func(Type[T]) G,
	fh func(Type[T]) H,
	fi func(Type[T]) I,
) (A, B, C, D, E, F, G, H, I)

Types

type Seq

type Seq[T any] []Type[T]

Heterogenous projection of product type

func New

func New[T any](names ...string) Seq[T]

Unfold type T to heterogenous sequence using field names

func New1

func New1[T, A any]() Seq[T]

Unfold type T to heterogenous sequence

func New2

func New2[T, A, B any]() Seq[T]

Unfold type T to heterogenous sequence

func New3

func New3[T, A, B, C any]() Seq[T]

Unfold type T to heterogenous sequence

func New4

func New4[T, A, B, C, D any]() Seq[T]

Unfold type T to heterogenous sequence

func New5

func New5[T, A, B, C, D, E any]() Seq[T]

Unfold type T to heterogenous sequence

func New6

func New6[T, A, B, C, D, E, F any]() Seq[T]

Unfold type T to heterogenous sequence

func New7

func New7[T, A, B, C, D, E, F, G any]() Seq[T]

Unfold type T to heterogenous sequence

func New8

func New8[T, A, B, C, D, E, F, G, H any]() Seq[T]

Unfold type T to heterogenous sequence

func New9

func New9[T, A, B, C, D, E, F, G, H, I any]() Seq[T]

Unfold type T to heterogenous sequence

type Type

type Type[T any] struct {
	reflect.StructField

	RootOffs uintptr
	PureType reflect.Type
	ID       int
}

Type element of product type, a type safe wrapper of reflect.StructField Type safe wrapper prevents reflect.StructField to be used outside of original type T context.

func ForName

func ForName[T any](seq Seq[T], field string) Type[T]

Lookup type in heterogenous sequence by name of member

func ForNameMaybe added in v1.2.0

func ForNameMaybe[T any](seq Seq[T], field string) (Type[T], bool)

Lookup type in heterogenous sequence by name of member

func ForType

func ForType[A, T any](seq Seq[T]) Type[T]

Lookup type heterogenous sequence by "witness" type

func (Type[T]) FieldKey added in v1.2.0

func (t Type[T]) FieldKey() string

Unique identity of key associated with type

Jump to

Keyboard shortcuts

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