7.1.6. Creating products and sums of roles
So how do products and sums of roles arise? PL allows for several ways to construct them.
7.1.6.1. Filling
The primary way to construct a Product Role is by specifying a Role with a filler:
user Person (..) filledBy PhysicalObject
Here we create the product of Person and PhysicalObject. All properties of PhysicalObject ‘can be reached’ through Person. We can specify a View with all those properties.
7.1.6.2. FilledBy as a constraint
The type we specify as the possible filler of a Role constrains what instances we may actually bind to that Role. Only inhabitants of the filler type may be bound to an instance of the Role.
When we say that the filler of a Role is the Empty Role, we say in effect that anything goes. There is no constraint. So, by default, each role has the Empty Role as its filler type.
In contrast, the Universal Role as the filler type of a Role is a tall order. We’ve seen that in the practice of our finite programs there can be no instances of the Universal Role. So in effect, by requiring the Universal Role as filler type of a Role, we say that that Role can have no filler.
7.1.6.3. Multiple fillers
This is how we create a Sum of Roles:
thing Vehicle (..) filledBy Bicycle, Car
Vehicle can be filled by either a Bicycle, or by a Car. Notice that we can add Properties to the definition of Vehicle itself, too. Then we would have a product of Vehicle and the sum of Bicycle and Car. All instances of Vehicle would have Vehicle’s properties.
When Vehicle has no properties of its own, it is in effect the EmptyRole. A product of R and the EmptyRole is R itself, so in that case Vehicle is just the sum of Bicycle and Car.
7.1.6.4. Multiple fillers in a product
We also have the option to specify multiple fillers in a product:
user ClientOfPharmacy (..) filledBy BankAccountHolder + Patient
Attention: we use the + symbol here to denote a product in the sense that we’ve defined it above. This is because +, interpreted as ‘and’, reads more natural to a lay person than *.
Here, an instance of the role ClientOfPharmacy must be filled by both an instance of BankAccountHolder and an instance of Patient. This is because the pharmacy needs access to my medical records and it also needs access to my bank account number (assuming it will automatically collect the costs incurred).
Why do we need the BankAccountHolder + Patient syntax? Can we not instead accumulate properties by filling BankAccountHolder with Patient? We could, and we could do it the other way round, too. And that is the catch: by choosing either way, we tie both roles together forever. Obviously, I don’t need my medical records in all situations where I need my bank account and the same holds vice versa. There is no ‘natural model’: it just depends on the situation.
Even worse, we can never be sure what combinations of properties might be required in future models. The best way we can prepare for that future is to lump everything together in the ‘role at the bottom’, whatever we choose that to be. It is an include everything even the kitchen sink approach to modelling we obviously want to avoid.
This is why we need the opportunity to bring in packets of properties as desired, using the product syntax given above.
Another way to think of this is that a product created by filling is ‘on the supply side’, whereas a product created by + is ‘on the demand side’. We create that product when we need it, instead of creating it because we might need it in the future.
7.1.6.5. Aspects
By giving a Role an Aspect, we bring in the properties of that Aspect. So, on the type level, Aspects create a product of roles, too. For example:
thing HomeAddress (..) aspect: Location
creates the product of HomeAddress and Location. Instances of a HomeAddress will have properties of both, for example TypeOfHome for HomeAddress and X and Y from Location.
The following lines create the same product type:
thing HomeAddress (..) filledBy Location
However, on the instance level things are different. With the latter model, we would have to bind an instance of Location to an instance of HomeAddress. With the former model, there would be no such instance. Instead, the HomeAddress instance would have the Location X and Y properties, too.
Aspects of Contexts work in the same way. A Context Aspect introduces Role types into a Context. However, there is no alternative modelling to consider, as we cannot ‘fill’ Contexts.