Infers.Rep Library Reference

Synopsis

namespace Infers.Rep
type Rep =
  inherit Rules
  new: unit -> Rep
  static member Rep: unit -> Rep<'t>
  static member Union: Rep<'t> * Union<'t> -> Union<'t>
  static member Product: Rep<'t> * Product<'t> -> Product<'t>
  static member Record: Rep<'t> * Record<'t> -> Record<'t>
  static member Tuple: Rep<'t> * Tuple<'t> -> Tuple<'t>
  static member Prim: Rep<'t> * Prim<'t> -> Prim<'t>
  static member Enum: Rep<'t> * Enum<'t> -> Enum<'t>
  static member Enum: Rep<'t> * Enum<'u,'t> -> Enum<'u,'t>
  static member Subtyped: Rep<'t> * Subtyped<'t> -> Subtyped<'t>
  static member Struct: Rep<'t> * Struct<'t> -> Struct<'t>
  static member Class: Rep<'t> * Class<'t> -> Class<'t>
  static member Interface: Rep<'t> * Interface<'t> -> Interface<'t>
  static member AnyCase: AsChoices<'s,'t> * Case<'p,'o,'t> -> Case<'p,'o,'t>
  static member AsChoices: Rep<'t> * AsChoices<'s,'t> -> AsChoices<'s,'t>
  static member AsPairs: AsPairs<'p,'t,'t> -> AsPairs<'p,'t>
  static member AsPairs: Rep<'t> * AsPairs<'p,'o,'t> -> AsPairs<'p,'o,'t>
  static member AsPairs: AsChoices<'p,'t> * Case<'p,'p,'t> -> AsPairs<'p,'p,'t>
  static member AsElem: Labelled<'e,'r,'o,'t> -> Elem<'e,'r,'o,'t>
  static member AsElem: Item<'e,'r,'t> -> Elem<'e,'r,'t,'t>
  static member AsLabelled: Field<'e,'r,'t> -> Labelled<'e,'r,'t,'t>
  static member AsLabelled: Label<'e,'r,'o,'t> -> Labelled<'e,'r,'o,'t>
type Empty = struct end
[<Struct>] 
type Pair<'e,'r> =
  val mutable Elem: 'e
  val mutable Rest: 'r
  new: 'e * 'r -> Pair<'e,'r>
[<AutoOpen>]
module Pair =
  val (|Pair|): Pair<'e,'r> -> 'e * 'r
[<AbstractClass>] 
type AsChoices<'t> =
  inherit Rules
  new: unit -> AsChoices<'t>
  val Arity: int
  abstract Tag: 't -> int
[<AbstractClass>] 
type AsChoices<'s,'t> =
  inherit AsChoices<'t>
  new: unit -> AsChoices<'s,'t>
[<AbstractClass>] 
type Rep<'t> =
  inherit Rules
  new: unit -> Rep<'t>
[<AbstractClass>] 
type Prim<'t> =
  inherit Rep<'t>
  new: unit -> Prim<'t>
[<AbstractClass>] 
type Enum<'t> =
  inherit Rep<'t>
  new: unit -> Enum<'t>
[<AbstractClass>] 
type Enum<'u,'t> =
  inherit Enum<'t>
  new: unit -> Enum<'u,'t>
[<AbstractClass>] 
type Subtyped<'t> =
  inherit Rep<'t>
  new: unit -> Subtyped<'t>
[<AbstractClass>] 
type Struct<'t> =
  inherit Subtyped<'t>
  new: unit -> Struct<'t>
[<AbstractClass>] 
type Class<'t> =
  inherit Subtyped<'t>
  new: unit -> Class<'t>
[<AbstractClass>] 
type Interface<'t> =
  inherit Subtyped<'t>
  new: unit -> Interface<'t>
[<AbstractClass>] 
type Product<'t> =
  inherit Rep<'t>
  new: unit -> Product<'t>
[<AbstractClass>] 
type Elem<'e,'t> =
  new: unit -> Elem<'e,'t>
  val Index: int
  abstract Get: 't -> 'e
[<AbstractClass>] 
type Elem<'e,'r,'o,'t> =
  inherit Elem<'e,'t>
  new: unit -> Elem<'e,'r,'o,'t>
[<AbstractClass>] 
type Labelled<'e,'r,'o,'t> =
  inherit Elem<'e,'r,'o,'t>
  new: unit -> Labelled<'e,'r,'o,'t>
  val Name: string
[<AbstractClass>] 
type Tuple<'t> =
  inherit Product<'t>
  new: unit -> Tuple<'t>
[<AbstractClass>] 
type Item<'e,'r,'t> =
  inherit Elem<'e,'r,'t,'t>
  new: unit -> Item<'e,'r,'t>
[<AbstractClass>] 
type Record<'t> =
  inherit Product<'t>
  new: unit -> Record<'t>
[<AbstractClass>] 
type Field<'e,'r,'t> =
  inherit Labelled<'e,'r,'t,'t>
  new: unit -> Field<'e,'r,'t>
  val IsMutable: bool
  abstract Set: 't * 'e -> unit
[<AbstractClass>] 
type AsPairs<'p,'t> =
  inherit Rules
  new: unit -> AsPairs<'p,'t>
  val Arity: int
  val IsMutable: bool
  abstract Extract: from: 't * into: byref<'p> -> unit
  abstract Create: from: byref<'p> -> 't
  abstract Overwrite: Record<'t> * into: 't * from: byref<'p> -> unit
  abstract ToPairs: 't -> 'p
  abstract OfPairs: 'p -> 't
  abstract Default: Record<'t> -> 't
[<AbstractClass>] 
type AsPairs<'p,'o,'t> =
  inherit AsPairs<'p,'t>
  new: unit -> AsPairs<'p,'o,'t>
[<AbstractClass>] 
type Union<'t> =
  inherit Rep<'t>
  new: unit -> Union<'t>
[<AbstractClass>] 
type Case<'p,'o,'t> =
  inherit AsPairs<'p,'o,'t>
  new: unit -> Case<'p,'o,'t>
  val Name: string
  val Tag: int
[<AbstractClass>] 
type Label<'e,'r,'o,'t> =
  inherit Labelled<'e,'r,'o,'t>
  new: unit -> Label<'e,'r,'o,'t>

Description

namespace Infers.Rep

Infers.Rep is a library providing inference rules for polytypic or datatype generic programming with the Infers library.

Infers.Rep uses reflection and run-time code generation to build type representations for various F# types. Those type representations can be accessed using Infers by writing rules over the structure of types. The type representations provided by Infers.Rep make it possible to manipulate values of the represented types efficiently: after the type representation has been created, no further use of slow reflection, boxing or other kinds of auxiliary memory allocations are required.

type Rep =

Inference rules for generic type representations.

type Empty = struct end

Represents an empty product as a special case for union cases.

[<Struct>] 
type Pair<'e,'r> =

Represents a pair of the types 'e and 'r.

Note that the idea behind using a struct type is to make it possible to construct and deconstruct products without performing any heap allocations. When used carefully, avoiding copying and making sure structs are stack allocated or directly embedded within objects, this can lead to significantly better performance than with heap allocated products. However, naive use results in both heap allocations and copying, which can lead to worse performance than with heap allocated products.

Note that while it is in no way enforced, the idea is that in a nested product the Elem field is the current singleton element and Rest is the remainder of the nested produced. For example, the nested product of the type

char * int * float * bool

would be

Pair<char, Pair<int, Pair<float, bool>>>

The Rep rules generate products in this manner and it is important to understand this in order to write rules guided by nested pairs.

val mutable Elem: 'e

The current element.

val mutable Rest: 'r

The remainder of the product.

new: 'e * 'r -> Pair<'e,'r>

Constructs a pair.

[<AutoOpen>]
module Pair =
val (|Pair|): Pair<'e,'r> -> 'e * 'r

Active pattern for convenient (but slow) matching of pair structs.

[<AbstractClass>] 
type AsChoices<'t> =

Base class for AsChoices<'s,'t> that does not include the 's type parameter to allow it to be ignored.

val Arity: int

The number of cases the union type 't has.

abstract Tag: 't -> int

Returns the integer tag of the given union value.

[<AbstractClass>] 
type AsChoices<'s,'t> =

Representation of the type 't as nested choices of type 's.

An AsChoices<'s,'t> class generated by Infers.Rep also contains a rule of the form

_: Case<'p,'o,'t>

where 'p is a representation of the case as nested pairs and 'o is a nested choice that identifies the particular case.

[<AbstractClass>] 
type Rep<'t> =

Base class for type representations.

[<AbstractClass>] 
type Prim<'t> =

Representation for primitive types.

[<AbstractClass>] 
type Enum<'t> =

Representation for enumerated types.

[<AbstractClass>] 
type Enum<'u,'t> =

Representation for enumerated type 't whose underlying type is 'u.

[<AbstractClass>] 
type Subtyped<'t> =

Representation for "subtyped" .Net types.

[<AbstractClass>] 
type Struct<'t> =

Representation for struct or value types.

[<AbstractClass>] 
type Class<'t> =

Representation for class types.

[<AbstractClass>] 
type Interface<'t> =

Representation for interface types.

[<AbstractClass>] 
type Product<'t> =

Type representation for the F# product type (tuple or record) 't.

A Product<'t> class generated by Infers.Rep also contains a rule of the form

_: AsPairs<'p,'t,'t>

where the type 'p is a representation of the product as nested pairs.

See also Union<'t>.

[<AbstractClass>] 
type Elem<'e,'t> =

Abstract representation of an element of type 'e of the product type 't.

val Index: int

The index of the element.

abstract Get: 't -> 'e

Returns the value of the element.

[<AbstractClass>] 
type Elem<'e,'r,'o,'t> =

Unique representation of an element of type 'e of the product type 't.

[<AbstractClass>] 
type Labelled<'e,'r,'o,'t> =

Representation of a possibly labelled element of type 'e.

val Name: string

The name of the label.

[<AbstractClass>] 
type Tuple<'t> =

Type representation for the F# tuple type 't.

[<AbstractClass>] 
type Item<'e,'r,'t> =

Representation of an element of type 'e of a tuple of type 't.

[<AbstractClass>] 
type Record<'t> =

Type representation for the F# record type 't.

[<AbstractClass>] 
type Field<'e,'r,'t> =

Representation of a field of type 'e of the record type 't.

val IsMutable: bool

Whether the field is mutable.

abstract Set: 't * 'e -> unit

Sets the value of the field assuming this is a mutable field.

[<AbstractClass>] 
type AsPairs<'p,'t> =

Base class for AsPairs<'p,'o,'t> that does not include the 'o type parameter to allow it to be ignored.

val Arity: int

The number of elements the product type has.

val IsMutable: bool

Whether the product type directly contains mutable fields.

abstract Extract: from: 't * into: byref<'p> -> unit

Copies the fields of the type 't to the generic product of type 'p.

abstract Create: from: byref<'p> -> 't

Creates a new instance of type 't from the nested pairs of type 'p.

abstract Overwrite: Record<'t> * into: 't * from: byref<'p> -> unit

Overwrites the fields of the record type 't with values from the nested pairs of type 'p. Along with Default this supports the generation of cyclic records.

abstract ToPairs: 't -> 'p

Convenience function to convert from product type to nested pairs.

abstract OfPairs: 'p -> 't

Convenience function to convert from nested pairs to product type.

abstract Default: Record<'t> -> 't

Convenience function to create a new default valued (all default values) object of the record type 't. Along with Overwrite this supports the generation of cyclic records.

[<AbstractClass>] 
type AsPairs<'p,'o,'t> =

Representation of the type 't as nested pairs of type 'p.

An AsPairs<'p,'o,'t> class generated by Infers.Rep also contains rules for accessing the elements of the product. Depending on the type 't those rules are of one of the following forms:

_:  Item<e,r,  t>                      :> Elem<e,r,t,t> :> Elem<e,t>
_: Label<e,r,o,t> :> Labelled<e,r,o,t> :> Elem<e,r,o,t> :> Elem<e,t>
_: Field<e,r,  t> :> Labelled<e,r,o,t> :> Elem<e,r,t,t> :> Elem<e,t>
[<AbstractClass>] 
type Union<'t> =

Type representation for the F# union type 't.

A Union<'t> class generated by Infers.Rep also contains a rule of the form

_: AsChoices<'s,'t>

where type 's is a representation of the union as nested binary choices.

Note that while union types are not considered as product types in Infers.Rep, one can view a union type with only a single case as a product. For example,

type foo = Bar of int * string * float

can be viewed as a product

AsPairs<Pair<int, Pair<string, float>>,
        Pair<int, Pair<string, float>>,
        foo>

and a rule for this is provided directly by Infers.Rep. If you need to handle product types and union types separately, say in a pretty printing generic, you should have the Union<_> and Product<_> predicates in your rules.

[<AbstractClass>] 
type Case<'p,'o,'t> =

Representation of a case of the F# union type 't.

val Name: string

The name of the case.

val Tag: int

The integer tag of the case.

[<AbstractClass>] 
type Label<'e,'r,'o,'t> =

Representation of a possibly labelled element of type 'e of a case of the F# union type 't.