Fields of Choral classes can be distributed over different roles.
For example, a class BiPair
can define a “distributed pair” storing two values at different roles.
class BiPair@(A, B)<L@X, R@Y> {
private L@A left;
private R@B right;
public BiPair(L@A left, R@B right) {
this.left = left;
this.right = right;
}
public L@A left() {
return this.left;
}
public R@B right() {
return this.right;
}
}
Try it yourself: see the source code on .
Class BiPair
is distributed between roles A
and B
and has two fields, left
and right
.
The class is also parameterised on two data types, L
and R
, which exemplifies our support for generics.
In the class declaration, L@X
specifies that L
is expected to be a data type parameterised over a single role, abstracted by X
; similarly for R@Y
.
Choral interprets type parameter declarations and usages as in Java generics: the first appearance of a type parameter declares the parameter (it is a “binder”), while subsequent occurrences of the same parameter name are usages of that parameter (these occurrences are “bound”).
The two fields found in the first two lines after the class declaration, left
and right
, are respectively located at A
and B
with the types L
and R
.
Choral classes can have constructors that take data in from different roles, as shown by the method public BiPair(L@A left, R@B right)
.
The BiPair
class also has two accessor methods that return data at different roles, to access the respective two fields left
and right
.
Data structures like BiPair
are useful when defining choreographies where the data at some role needs to correlate with data at another role, as with distributed authentication tokens. We are going to use this in our examples later on.
The roles A
and B
mentioned in class BiPair
are actually parameters that can be replaced at will when objects of the class are created: Choral class types are type constructors, or higher-kinded types, parameterised over roles.
For example, we can now freely create a BiPair
for roles Client
and Server
, and another BiPair
for other roles Alice
and Bob
.
BiPair@(Client, Server)<Integer, Integer> p1 = new BiPair@(Client, Server)<Integer, Integer>(10@Client, 20@Server);
BiPair@(Alice, Bob)<String, String> p2 = new BiPair@(Alice, Bob)<Integer, Integer>("Key"@Alice, "Value"@Bob);
p.left(); // this returns 10@Client
p2.right(); // this returns "Value"@Bob
We do not have a lot of type inference in Choral yet. For example, the first line of the snippet above could be written as follows in principle.
var p1 = new BiPair@(Client, Server)<>(10, 20); // not supported.. yet!
Having to write types explicitly helped us in checking that Choral makes sense while we developed our first examples. We plan on introducing type inference in the future.