REL
REFERENCE
Other

# Other Data Types

## Any

The type `Any` covers all possible values, and can be used as a wildcard to match any type.

### Type Relation: `Any(x)`

`Any(x)` will be `true` for any `x`.

### Example

``````// read query

def R = (1, 3) ; (1, "foo")

ic any_ic {subset(R, (Int, Any) )}

def output = R``````

## Boolean

π

The Rel language is based on two-valued logic (opens in a new tab) where the constants `true` and `false` are relations and not data values.

The relation `true` is represented by an empty tuple `()`, which is a relation of arity 0 and cardinality 1. The relation `false` is the empty relation `{}`, which has arity 0 and cardinality 0.

Rel does include, however, a separate `Boolean` data type that is useful for importing data that explicitly depends on `Boolean` values β in particular, JSON data. See the example below.

### Construction

There are two constructors, one for each `Boolean` value: `boolean_true` and `boolean_false`:

``````// read query

def output = {boolean_false; boolean_true}``````

### Type Relation: `Boolean(x)`

`Boolean(x)` tests whether `x` has the data type `Boolean`.

``````// read query

def R = {(1, boolean_true); (2, true); (3, boolean_false); (4, false)}

def output(x, y) = R(x, y) and Boolean(y)``````

### Examples

In the following example, the JSON `true` and `false` values are mapped to the Rel data type `Boolean`:

``````// read query

def joe = parse_json["""
{ "address": null, "name" : "JJ" , "person" : true , "company" : false }
"""]

ic { Boolean(joe:person) }
ic { boolean_and[joe:person, boolean_not[joe:company]] = boolean_true }
ic { joe:person = boolean_true }

def output = joe``````

Here is an example showing how `and`, `or`, and `not` operations over the data types are written:

``````// read query

def a = boolean_true
def b = boolean_false

def output:not_and = boolean_not[boolean_and[a, b]]
def output:or = boolean_or[a, b]``````

Note that `boolean_and`, `boolean_or`, and `boolean_not` are distinctly different from the Rel key words `and`, `or`, and `not`. The former operate only on boolean data, whereas the latter are part of logic expressions like conjunction, disjunction, and negation.

## FilePos

### Construction

`FilePos` types are created when importing CSV files. They are used as keys when joining columns from the same row. Currently, a user canβt directly create this data type themselves.

### Type Relation: `FilePos(x)`

`FilePos(x)` tests whether `x` has the data type `FilePos`:

``````// read query

def config:data="""
a,b,c
1,2,3
4,5,6
"""

def output(p) = csv(_, p, _)

def csv_ic {
subset(csv, (RelName, FilePos, String))
}``````

### Examples

``````// read query

def config:data="""
a,b,c
1,2,3
4,5,6
"""

See CSV Import for more details.

## Missing

π

Generally, missing or null data are simply represented in Rel by not having these facts in a relation.

`Missing` is a singleton type, containing only one value, `missing`.

It is used for data that require an explicit representation of null data. For instance, JSON data require an explicit representation for missing data (see example below). Data representation that is not fully normalized, such as Third Normal Form (opens in a new tab) (3NF), also requires an explicit representation of missing data.

For data that are stored in the fully normalized Graph Normal Form (GNF), missing data points are represented by not stating the missing fact in the relation. GNF is the recommended way to model data and makes best use of the RKGS query optimizer.

### Construction

A `Missing` data value is created by writing `missing`:

``````// read query

def output = missing``````

### Type Relation: `Missing(x)`

`Missing(x)` tests whether `x` has the data type `Missing`:

``````// read query

def R = {("+1", 'π'); ("+10", missing); ("+100", 'π―')}

def output(x, y) = R(x, y) and not Missing(y)``````

### Examples

Parsing JSON data that contain explicit null data:

``````// read query

def json = parse_json[""" { "address": null, "name" : "JJ" } """]