Types

Types are used in RiskScape to define the shape of the data that goes in and out of your models. All data is constructed around a set of built in simple types. For example, we have simple types, such as:

  • integers, e.g. 1, -4

  • real numbers (floating point), e.g. 0.25454, -8464564564.2

  • text - e.g. free form strings of text with no fixed length

  • geometry - e.g. points, polygons lines etc

Special Cases

There are a few special types that are treated specially in RiskScape, namely nullable and anything.

  • The nullable type is a way of saying that a value might be null, aka not present. When used in a function, it means the argument is optional, or that a function might not return something.

  • The anything type is a way of saying that there must be a value, but it can be absolutely any value. It must, however, be something. It can be combined with nullable to say that there doesn’t have to be a value.

Complex types

Simple types are so called because there’s only ever one of them - every integer is the same as every other integer. There are also complex types where this doesn’t hold true. The most commonly used complex type in RiskScape is called a struct.

Struct type

A struct is a bit like the schema of a database table. More formally, it is an ordered mapping of keys to types.

Given we had this table of geographical points of interest:

id

name

location

category

replacement_cost

1

The Beehive

-41.278,174.775

Government Building

2000000

2

Te Papa

-41.290,174.779

Tourism

25000000

Then a type expression for this (more on this later) might be:

struct(id: integer, name: text, location: geometry, category: text, replacement_cost: integer)

Querying type information

To list the different built-in RiskScape types available to use, run the riskscape type-registry list command. This displays some help information alongside each of the types, explaining what is is and how it might be used.

If you’re new to RiskScape, try running riskscape type-registry list now.

Defining types

Types are defined using a type expression. For simple types, it is enough to refer to them by their id. Complex types look more like function calls and accept arguments, e.g:

# a simple type
text
# a list of text
list(text)
# a struct with various members, including a nullable description
struct(id: integer, name: text, description: nullable(text))

Types can be defined in your Projects by adding type expressions to your project’s INI file. A type can be added like this:

# the bit after type is the identifier
[type my_types_id]
# single line definition
type = struct(id: integer, name: text)

[type another_type]
# multi-line struct definition
type.id = integer
type.name = text

You can view the results of adding types to your project with the riskscape type list command. Any problems with the types in your project will be shown to you when RiskScape starts up.

Coercion

In some situations, a value in your model can be coerced from one type to another. This is not guaranteed to succeed and a failed coercion can result in different behaviour. Typically it will fail the model run or give a null result.

An example of coercion would be converting some text to a number, for example the text “11.43” can be coerced to type floating, but “$11.43c” can not.

Type equivalence

A type is said to be equivalent (or more formally, covariant) if the value of the type can be safely represented by another type. The type anything is equivalent to any other type you give it, except nullable. Apart from this special case, equivalence is determined by comparing the two types for equality and things called wrapping types - a wrapping type surrounds another type to add extra metadata or validation to it.

An examples of a wrapping types is the within type - it wraps another type to constrain values to be within a known set, e.g. animals = within(text, 'cat', 'dog', 'pig'). The text type is equivalent to this animals type, as the text type can represent all the values that it can. The opposite is not true, as there are text values that can not be represented by the animals type, e.g. “robot” is not a valid value for animals.

An understanding of this can be helpful when building expressions to customize your models.