","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"In this case distance (in miles) was accidentally added to travel time (in hours), thus producing unhelpful output. Ideally, users should be protected from these kinds of mistakes."}]},{"type":"p","children":[{"type":"text","text":"We are excited to announce the support of "},{"type":"a","url":"https://docs.relational.ai/help/glossary#value-type","title":null,"children":[{"type":"text","text":"value types"}]},{"type":"text","text":" in Rel, which allow users to distinguish elements that represent different things when writing applications in Rel."}]},{"type":"p","children":[{"type":"text","text":"You can define a value type as follows:"}]},{"type":"code_block","lang":"rel","value":"value type Distance = Float\nvalue type Duration = Int","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"These declarations define two types, one for travel distance and one for travel duration. A value type has its own name and is distinct from every other type, even though it may be parameterized by common underlying types."}]},{"type":"p","children":[{"type":"text","text":"Value types are useful as they allow users to make their models clearer, more readable, and more maintainable. They also help avoid mistakes similar to the one presented above."}]},{"type":"p","children":[{"type":"text","text":"Value types allow users to distinguish between different kinds of values, regardless of the potentially identical underlying representation. Additionally, value types can be used to define other value types under certain conditions."}]},{"type":"h2","children":[{"type":"text","text":"Defining Value Types"}],"id":"defining-value-types"},{"type":"p","children":[{"type":"text","text":"Using value types, the previous example can now be rewritten:"}]},{"type":"code_block","lang":"rel","value":"value type Distance = Float\nvalue type Duration = Int\n \ndef distance = (\"Tampa\", \"Miami\", ^Distance[279.9])\ndef distance = (\"Miami\", \"Atlanta\", ^Distance[662.6])\n \ndef travel_time = (\"Tampa\", \"Miami\", ^Duration[5])\ndef travel_time = (\"Miami\", \"Atlanta\", ^Duration[11])","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"In this example, the "},{"type":"a","url":"https://docs.relational.ai/help/glossary#partial-application","title":null,"children":[{"type":"text","text":"partial application"}]},{"type":"text","text":" "},{"type":"text","text":"^Distance[279.9]","code":true},{"type":"text","text":" evaluates to the value of type "},{"type":"text","text":"Distance","code":true},{"type":"text","text":" that corresponds to the number "},{"type":"text","text":"279.9","code":true},{"type":"text","text":". Given the use of value types, the relation "},{"type":"text","text":"distance","code":true},{"type":"text","text":" is now represented as follows:"}]},{"type":"code_block","lang":"rel","value":"def output = distance","children":[{"type":"text","text":""}]},{"type":"code_block","lang":"rel","value":"value type Distance = Float\nvalue type Duration = Int\n \ndef distance = (\"Tampa\", \"Miami\", ^Distance[279.9])\ndef distance = (\"Miami\", \"Atlanta\", ^Distance[662.6])\n \ndef travel_time = (\"Tampa\", \"Miami\", ^Duration[5])\ndef travel_time = (\"Miami\", \"Atlanta\", ^Duration[11])\ndef output = distance","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Output:"}]},{"type":"html","value":"","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"The third column now contains values of type "},{"type":"text","text":"Distance","code":true},{"type":"text","text":"."}]},{"type":"p","children":[{"type":"text","text":"Value types need not be parameterized by individual values; they can be parameterized by tuples. For example, here is a value type "},{"type":"text","text":"Point3d","code":true},{"type":"text","text":" that represents a point in a three dimensional space:"}]},{"type":"code_block","lang":"rel","value":"value type Point3d = Float, Float, Float","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Value types also support expressions in their declaration. For example, here is a value type "},{"type":"text","text":"Age","code":true},{"type":"text","text":", which is meant to represent a person's age:"}]},{"type":"code_block","lang":"rel","value":"value type Age(x in Int) { 0 <= x and x <= 120 } \n\ndef output = ^Age[15] ; ^Age[150]","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Output:"}]},{"type":"html","value":"","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Value types don't necessarily represent infinite relations as we saw with the "},{"type":"text","text":"Distance","code":true},{"type":"text","text":" relation above."}]},{"type":"p","children":[{"type":"text","text":"As an example, consider the following two value type definitions. The first specifies the days of the week, while the second defines a boolean value type which is parameterized by an 8-bit integer constrained to be either 0 or 1:"}]},{"type":"code_block","lang":"rel","value":"value type Weekday = 1; 2; 3; 4; 5; 6; 7\n\nvalue type Bool(x) = Int[8](x) and (x = 0 or x = 1)","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Additionally, a value type does not necessarily need a representation or an underlying type. For example, the following declaration specifies a value type called "},{"type":"text","text":"None","code":true},{"type":"text","text":" that has the empty constructor relation "},{"type":"text","text":"^None","code":true},{"type":"text","text":"."}]},{"type":"code_block","lang":"rel","value":"value type None\n\ndef none = ^None[]\n\ndef output:tuple = 1, none, \"str\"\ndef output:mul = none * 10","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Output:"}]},{"type":"html","value":"","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Value types can also be parameterized by other value types. Here is an example that first defines the value type "},{"type":"text","text":"DistanceUnit","code":true},{"type":"text","text":" with distance units and then defines another value type "},{"type":"text","text":"Distance","code":true},{"type":"text","text":" that uses "},{"type":"text","text":"DistanceUnit","code":true},{"type":"text","text":"."}]},{"type":"code_block","lang":"rel","value":"value type DistanceUnit = :Meters; :Miles\nvalue type Distance = DistanceUnit, Int\n\ndef output = ^Distance[^DistanceUnit[:Meters], 10]","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Output:"}]},{"type":"html","value":"","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Defining value types that build upon other value types allows for greater expressivity and clarity in the applications being created."}]},{"type":"h2","children":[{"type":"text","text":"Performing Operations Using Value Types"}],"id":"performing-operations-using-value-types"},{"type":"p","children":[{"type":"text","text":"The definitions presented so far show how to describe different types and construct data that adhere to those value types."}]},{"type":"p","children":[{"type":"text","text":"In order to use and perform operations on the data of a given value type, the associated data need to be extracted to perform the operation accordingly."}]},{"type":"p","children":[{"type":"text","text":"Consider again one of the first examples using the "},{"type":"text","text":"Distance","code":true},{"type":"text","text":" value type:"}]},{"type":"code_block","lang":"rel","value":"value type Distance = Float\nvalue type Duration = Int\n \ndef distance = (\"Tampa\", \"Miami\", ^Distance[279.9])\ndef distance = (\"Miami\", \"Atlanta\", ^Distance[662.6])","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"In order to find the distance from Tampa to Atlanta through Miami, the two distances need to be added together. This operation can be performed by extracting the two floating point numbers from "},{"type":"text","text":"^Distance","code":true},{"type":"text","text":":"}]},{"type":"code_block","lang":"rel","value":"def float_from_distance(d in Distance, x) = ^Distance(x, d)\n\ndef output { \n float_from_distance[distance[\"Tampa\", \"Miami\"]] \n + float_from_distance[distance[\"Miami\", \"Atlanta\"]]\n}","children":[{"type":"text","text":""}]},{"type":"code_block","lang":"rel","value":"value type Distance = Float\nvalue type Duration = Int\n \ndef distance = (\"Tampa\", \"Miami\", ^Distance[279.9])\ndef distance = (\"Miami\", \"Atlanta\", ^Distance[662.6])\ndef float_from_distance(d in Distance, x) = ^Distance(x, d)\n\ndef output { \n float_from_distance[distance[\"Tampa\", \"Miami\"]] \n + float_from_distance[distance[\"Miami\", \"Atlanta\"]]\n}","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Output:"}]},{"type":"html","value":"","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"We are also excited to announce support for operators over value types. Specifically, the same addition operation used over the "},{"type":"text","text":"Distance","code":true},{"type":"text","text":" value type can also be defined as an operator."}]},{"type":"p","children":[{"type":"text","text":"Operators can be applied over data of specific value types to perform computations depending on need. Here is the same example where an addition "},{"type":"text","text":"+","code":true},{"type":"text","text":" operator is defined:"}]},{"type":"code_block","lang":"rel","value":"def (+)[x in Distance, y in Distance] =\n ^Distance[float_from_distance[x] + float_from_distance[y]]\n\ndef output = distance[\"Tampa\", \"Miami\"] + distance[\"Miami\", \"Atlanta\"]","children":[{"type":"text","text":""}]},{"type":"code_block","lang":"rel","value":"value type Distance = Float\nvalue type Duration = Int\n \ndef distance = (\"Tampa\", \"Miami\", ^Distance[279.9])\ndef distance = (\"Miami\", \"Atlanta\", ^Distance[662.6])\ndef float_from_distance(d in Distance, x) = ^Distance(x, d)\ndef (+)[x in Distance, y in Distance] =\n ^Distance[float_from_distance[x] + float_from_distance[y]]\n\ndef output = distance[\"Tampa\", \"Miami\"] + distance[\"Miami\", \"Atlanta\"]","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"Output:"}]},{"type":"html","value":"","children":[{"type":"text","text":""}]},{"type":"p","children":[{"type":"text","text":"In summary, value types help distinguish between different kinds of values, even though the underlying data may be identical. Value types can be used to define other value types."}]},{"type":"p","children":[{"type":"text","text":"For more details please see the "},{"type":"a","url":"https://docs.relational.ai/rel/concepts/value-types","title":null,"children":[{"type":"text","text":"Value Types Concept Guide"}]},{"type":"text","text":"."}]}],"_content_source":{"queryId":"src/content/resources/value-types-in-rel.mdx","path":["resource","body"]}},"_content_source":{"queryId":"src/content/resources/value-types-in-rel.mdx","path":["resource"]}}},"errors":null,"query":"\n query resource($relativePath: String!) {\n resource(relativePath: $relativePath) {\n ... on Document {\n _sys {\n filename\n basename\n breadcrumbs\n path\n relativePath\n extension\n }\n id\n }\n ...ResourceParts\n }\n}\n \n fragment ResourceParts on Resource {\n __typename\n title\n description\n date\n image\n categories\n authors {\n __typename\n name\n link\n }\n seo {\n __typename\n keywords\n description\n image\n image_alt\n canonical_url\n author\n published\n modified\n language\n robots\n site_name\n content_type\n }\n body\n}\n ","variables":{"relativePath":"value-types-in-rel.mdx"}},"src/content/meta/meta.md":{"data":{"meta":{"_sys":{"filename":"meta","basename":"meta.md","breadcrumbs":["meta"],"path":"src/content/meta/meta.md","relativePath":"meta.md","extension":".md"},"id":"src/content/meta/meta.md","__typename":"Meta","banner":{"__typename":"MetaBanner","enabled":true,"content":{"type":"root","children":[{"type":"p","children":[{"type":"text","text":"Check out "},{"type":"a","url":"/resources/highlights-of-relationalai-at-snowflake-data-cloud-summit-2024","title":"SF summit highlights","children":[{"type":"text","text":"highlights"}]},{"type":"text","text":" of RelationalAI at "},{"type":"text","text":"Snowflake's Data Cloud Summit 2024!","bold":true}]}],"_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","banner","content"]}},"_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","banner"]}},"header":{"__typename":"MetaHeader","links":[{"__typename":"MetaHeaderLinks","text":"Product","url":"/product","style":"default","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","header","links",0]}},{"__typename":"MetaHeaderLinks","text":"Company","url":"/company","style":"default","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","header","links",1]}},{"__typename":"MetaHeaderLinks","text":"Docs","url":"/docs","style":"default","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","header","links",2]}},{"__typename":"MetaHeaderLinks","text":"Resources","url":"/resources/all/1","style":"default","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","header","links",3]}},{"__typename":"MetaHeaderLinks","text":"Get Started","url":"/get-started","style":"cta","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","header","links",4]}}],"_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","header"]}},"footer":{"__typename":"MetaFooter","sections":[{"__typename":"MetaFooterSections","name":"Product","links":[{"__typename":"MetaFooterSectionsLinks","text":"Overview","url":"/product","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",0,"links",0]}},{"__typename":"MetaFooterSectionsLinks","text":"Use Cases","url":"/product#for-problems-that-matter","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",0,"links",1]}},{"__typename":"MetaFooterSectionsLinks","text":"Capabilities","url":"/product#a-new-toolset","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",0,"links",2]}}],"_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",0]}},{"__typename":"MetaFooterSections","name":"Resources","links":[{"__typename":"MetaFooterSectionsLinks","text":"Documentation","url":"/docs/get-started","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",1,"links",0]}},{"__typename":"MetaFooterSectionsLinks","text":"News","url":"/resources/news/1","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",1,"links",1]}},{"__typename":"MetaFooterSectionsLinks","text":"Research","url":"/resources/research/1","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",1,"links",2]}},{"__typename":"MetaFooterSectionsLinks","text":"Releases","url":"/resources/releases/1","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",1,"links",3]}}],"_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",1]}},{"__typename":"MetaFooterSections","name":"About Us","links":[{"__typename":"MetaFooterSectionsLinks","text":"Our Company","url":"/company","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",2,"links",0]}},{"__typename":"MetaFooterSectionsLinks","text":"Contact Us","url":"/get-started","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",2,"links",1]}},{"__typename":"MetaFooterSectionsLinks","text":"Careers","url":"/careers","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",2,"links",2]}},{"__typename":"MetaFooterSectionsLinks","text":"Legal","url":"/legal","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",2,"links",3]}},{"__typename":"MetaFooterSectionsLinks","text":"GDPR","url":"/gdpr","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",2,"links",4]}},{"__typename":"MetaFooterSectionsLinks","text":"Security & Trust","url":"https://trust.relational.ai/","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",2,"links",5]}}],"_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","sections",2]}}],"socials":[{"__typename":"MetaFooterSocials","text":"GitHub","url":"https://github.com/RelationalAI","icon":"https://assets.tina.io/91d76337-e55d-4722-acb5-3106adb895b6/img/logos/github.png","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","socials",0]}},{"__typename":"MetaFooterSocials","text":"LinkedIn","url":"https://www.linkedin.com/company/relationalai/about","icon":"https://assets.tina.io/91d76337-e55d-4722-acb5-3106adb895b6/img/logos/linkedin.png","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","socials",1]}},{"__typename":"MetaFooterSocials","text":"Twitter","url":"https://twitter.com/relationalai","icon":"https://assets.tina.io/91d76337-e55d-4722-acb5-3106adb895b6/img/logos/twitter.png","_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer","socials",2]}}],"_content_source":{"queryId":"src/content/meta/meta.md","path":["meta","footer"]}},"_content_source":{"queryId":"src/content/meta/meta.md","path":["meta"]}}},"errors":null,"query":"\n query meta($relativePath: String!) {\n meta(relativePath: $relativePath) {\n ... on Document {\n _sys {\n filename\n basename\n breadcrumbs\n path\n relativePath\n extension\n }\n id\n }\n ...MetaParts\n }\n}\n \n fragment MetaParts on Meta {\n __typename\n banner {\n __typename\n enabled\n content\n }\n header {\n __typename\n links {\n __typename\n text\n url\n style\n }\n }\n footer {\n __typename\n sections {\n __typename\n name\n links {\n __typename\n text\n url\n }\n }\n socials {\n __typename\n text\n url\n icon\n }\n }\n}\n ","variables":{"relativePath":"./meta.md"}}};
globalThis.tina_info = tina;
})();
Value Types in Rel · RelationalAI
Check out highlights of RelationalAI at Snowflake's Data Cloud Summit 2024!
Differentiating between types of values is an essential aspect of application development, as it enables clarity of modeling and leads to fewer errors.
Consider a database that stores distances and travel times between different cities. For example:
Although this data describes the scenario reasonably well, it may lead to issues when querying the data. Specifically, distances and time intervals are represented here as plain numbers even though they represent quantities denominated in different units, so it's possible to confuse the two when querying.
For example, the following query produces results even though they are not meaningful:
In this case distance (in miles) was accidentally added to travel time (in hours), thus producing unhelpful output. Ideally, users should be protected from these kinds of mistakes.
We are excited to announce the support of value types in Rel, which allow users to distinguish elements that represent different things when writing applications in Rel.
You can define a value type as follows:
value type Distance = Float
value type Duration = Int
These declarations define two types, one for travel distance and one for travel duration. A value type has its own name and is distinct from every other type, even though it may be parameterized by common underlying types.
Value types are useful as they allow users to make their models clearer, more readable, and more maintainable. They also help avoid mistakes similar to the one presented above.
Value types allow users to distinguish between different kinds of values, regardless of the potentially identical underlying representation. Additionally, value types can be used to define other value types under certain conditions.
Defining Value Types
Using value types, the previous example can now be rewritten:
value type Distance = Float
value type Duration = Int
def distance = ("Tampa", "Miami", ^Distance[279.9])
def distance = ("Miami", "Atlanta", ^Distance[662.6])
def travel_time = ("Tampa", "Miami", ^Duration[5])
def travel_time = ("Miami", "Atlanta", ^Duration[11])
In this example, the partial application^Distance[279.9] evaluates to the value of type Distance that corresponds to the number 279.9. Given the use of value types, the relation distance is now represented as follows:
def output = distance
value type Distance = Float
value type Duration = Int
def distance = ("Tampa", "Miami", ^Distance[279.9])
def distance = ("Miami", "Atlanta", ^Distance[662.6])
def travel_time = ("Tampa", "Miami", ^Duration[5])
def travel_time = ("Miami", "Atlanta", ^Duration[11])
def output = distance
Output:
The third column now contains values of type Distance.
Value types need not be parameterized by individual values; they can be parameterized by tuples. For example, here is a value type Point3d that represents a point in a three dimensional space:
value type Point3d = Float, Float, Float
Value types also support expressions in their declaration. For example, here is a value type Age, which is meant to represent a person's age:
value type Age(x in Int) { 0 <= x and x <= 120 }
def output = ^Age[15] ; ^Age[150]
Output:
Value types don't necessarily represent infinite relations as we saw with the Distance relation above.
As an example, consider the following two value type definitions. The first specifies the days of the week, while the second defines a boolean value type which is parameterized by an 8-bit integer constrained to be either 0 or 1:
value type Weekday = 1; 2; 3; 4; 5; 6; 7
value type Bool(x) = Int[8](x) and (x = 0 or x = 1)
Additionally, a value type does not necessarily need a representation or an underlying type. For example, the following declaration specifies a value type called None that has the empty constructor relation ^None.
value type None
def none = ^None[]
def output:tuple = 1, none, "str"
def output:mul = none * 10
Output:
Value types can also be parameterized by other value types. Here is an example that first defines the value type DistanceUnit with distance units and then defines another value type Distance that uses DistanceUnit.
value type DistanceUnit = :Meters; :Miles
value type Distance = DistanceUnit, Int
def output = ^Distance[^DistanceUnit[:Meters], 10]
Output:
Defining value types that build upon other value types allows for greater expressivity and clarity in the applications being created.
Performing Operations Using Value Types
The definitions presented so far show how to describe different types and construct data that adhere to those value types.
In order to use and perform operations on the data of a given value type, the associated data need to be extracted to perform the operation accordingly.
Consider again one of the first examples using the Distance value type:
value type Distance = Float
value type Duration = Int
def distance = ("Tampa", "Miami", ^Distance[279.9])
def distance = ("Miami", "Atlanta", ^Distance[662.6])
In order to find the distance from Tampa to Atlanta through Miami, the two distances need to be added together. This operation can be performed by extracting the two floating point numbers from ^Distance:
value type Distance = Float
value type Duration = Int
def distance = ("Tampa", "Miami", ^Distance[279.9])
def distance = ("Miami", "Atlanta", ^Distance[662.6])
def float_from_distance(d in Distance, x) = ^Distance(x, d)
def output {
float_from_distance[distance["Tampa", "Miami"]]
+ float_from_distance[distance["Miami", "Atlanta"]]
}
Output:
We are also excited to announce support for operators over value types. Specifically, the same addition operation used over the Distance value type can also be defined as an operator.
Operators can be applied over data of specific value types to perform computations depending on need. Here is the same example where an addition + operator is defined:
def (+)[x in Distance, y in Distance] =
^Distance[float_from_distance[x] + float_from_distance[y]]
def output = distance["Tampa", "Miami"] + distance["Miami", "Atlanta"]
value type Distance = Float
value type Duration = Int
def distance = ("Tampa", "Miami", ^Distance[279.9])
def distance = ("Miami", "Atlanta", ^Distance[662.6])
def float_from_distance(d in Distance, x) = ^Distance(x, d)
def (+)[x in Distance, y in Distance] =
^Distance[float_from_distance[x] + float_from_distance[y]]
def output = distance["Tampa", "Miami"] + distance["Miami", "Atlanta"]
Output:
In summary, value types help distinguish between different kinds of values, even though the underlying data may be identical. Value types can be used to define other value types.