Skip to main content

Ontological Significance and Messages

An important concept in Flex is that of ontological significance. We say that a data type has ontological significance if there is a universal understanding (across all uses) of its meaning.

We will illustrate the importance of ontological significance with an example. Suppose we define the following structs and functions. The getPosFromAVS function extracts a ship's position from a vehicle state value. The pos2loc function translates a Position into a Location in order to inferface with a component that only understands Location data and not Position data.

struct AirVehicleState {
    ownshipPosition: Position; // offset (in kilometers) from an origin point.
    // other details omitted
}

struct Position {
    x: float64;
    y: float64;
}

struct Location {
    x: float64;     // measured in miles
    y: float64;     // measured in miles
}

function getPosFromAVS(avs: AirVehicleState) -> Position {
    avs.ownshipPosition;
}

function pos2loc(pos: Position) -> Location {
    Location {
        x = pos.x;
        y = pos.y;
    };
}

Furthermore, suppose that all Position values contained within an AirVehicleState represent offsets measured in kilometers. In contrast, Location data is always in miles. The offsets in a Position value can be expressed in different units depending on the circumstance; getPosFromAVS assumes kilometers while pos2loc assumes miles.

Is there a universal understanding of what Position means? No! The two functions are not interoperable because they make different assumptions about the meaning of the data in a Position value. Flex is designed to perform code synthesis tasks such as fusing the above two functions into a single function from AirVehicleState to Location. However, the contradictory interpretations of the meaning of Position prevent this fusion from happening safely.

The problem is that Position is not ontologically significant; different functions treat Position values differently. In contrast, messages of open standards like LMCP or Mavlink all have universally agreed-upon interpretations. Thus, it is safe to perform code synthesis tasks on functions that operate on them.

In Flex, the message keyword is used to indicate that a data type is ontologically significant and that performing code synthesis is safe. The message keyword is allowed to modify struct and variant declarations. Newtypes are always ontologically significant (without needing the message keyword).

message struct AirVehicleState {
    ownshipPosition: Position;
    // other details omitted
}