Skip to content
REL
REFERENCE
Value Types

Value Types

Declaration :=
      Annotation* "value" "type" Id FormalParamsBracket* FormalParamsParen? ("=" Expr)?
   |  Annotation* "value" "type" Id FormalParamsBracket* FormalParamsParen? ("{" Expr "}")?

Value type declarations allow you to define your own types that are composed of other types. A value type has its own name and is distinct from every other type, even though its values are represented by tuples of primitive types. In some respects it is similar to a record or “struct” type in programming languages.

For example, you might want to declare the type of a point on a plane, which is represented by its Cartesian coordinates:

value type Point = Float, Float

The above declares the relation Point. Just like Int, this is an infinite relation, but you can use it to check whether a given value is of type Point.

The declaration also implicitly declares the constructor relation ^Point, which can be used to construct values of type Point:

// read query
 
value type Point = Float, Float
 
def origin = ^Point[0.0, 0.0]
 
def output(p) = origin(p) and Point(p)  // second conjunct just for illustration

The constructor relation ^Point is infinite, but if you have a value p of type Point then you can use it to retrieve the constituent values of p:

// read query
 
value type Point = Float, Float
 
def origin = ^Point[0.0, 0.0]
 
def output(x, y) {
    exists(p : origin(p) and ^Point(x, y, p))
}

The constituent types of a value type need not be primitive types. You can also use other value types, as long as the various value types are not defined recursively in terms of each other:

// read query
 
entity type E = String
value  type V = Int, Int
value  type W = Entity, V, Float
 
def output = ^W[^E["ho"], ^V[1,2], 0.7]

See Value Types for a comprehensive introduction to declaring and using value types in Rel.

Next: Entities

Was this doc helpful?