Zum Inhalt
Erschienen in:

Open Access 2025 | OriginalPaper | Buchkapitel

Multiparty Session Typing, Embedded

Aktivieren Sie unsere intelligente Suche, um passende Fachinhalte oder Patente zu finden.

search-config
loading …

Abstract

Das Kapitel vertieft die Herausforderungen und Lösungen im Zusammenhang mit der Typisierung von Mehrparteien-Sitzungen (MPST) in Multithreadprogrammen, wobei die Grenzen der Abstraktionen zur Nachrichtenweitergabe hervorgehoben werden. Es führt MPST als Methode ein, um die Sicherheit und Lebendigkeit von Kommunikationsprotokollen zu gewährleisten, und beschreibt den Prozess der Spezifizierung von Protokollen als Verhaltenstypen und die Typüberprüfung von Implementierungen anhand dieser Spezifikationen. Die wichtigste Innovation ist die mpst.embedded-Bibliothek, die Scalas Match-Typen nutzt, um globale und lokale Typen direkt in die Sprache einzubetten. Dieser Ansatz beseitigt die mit externen DSLs verbundenen programmatischen Reibungen und vermeidet undichte Abstraktionen, indem globale und lokale Typen als erstklassige Bürger behandelt werden. Das Kapitel bietet einen detaillierten Überblick über mpst.embedded, einschließlich grundlegender und fortgeschrittener Funktionen wie Full Merge, Delegierung und allgemeine globale Typen. Außerdem werden die technischen Details der Einbettung von MPST in Scala diskutiert, einschließlich Projektions- und Typenprüfungsmechanismen. Der Evaluierungsteil bestätigt die praktische Durchführbarkeit von mpst.embedded durch systematische Messungen der Typenprüfzeiten und die Erforschung seiner Aussagekraft. Das Kapitel schließt mit einem Vergleich zu verwandten Arbeiten und einem Ausblick auf zukünftige Erweiterungen der MPST-Theorie, die in mpst.embedded. aufgenommen werden könnten.

1 Introduction

Background With the advent of multicore processors, multithreaded programming—a notoriously error-prone enterprise—has become increasingly important.
Because of this, mainstream languages have started to offer core support for higher-level communication primitives besides lower-level synchronisation primitives (e.g., Clojure, Go, Kotlin, Rust). The idea has been to add message passing as an abstraction for shared memory, as—supposedly—channels are easier to use than locks. Yet, empirical research shows that “message passing does not necessarily make multithreaded programs less error-prone than shared memory” [33].
One of the core challenges is as follows: given a specification S of the communication protocols that an implementation I should fulfil, how to prove that I is safe and live relative to S? Safety means “bad” communication actions never happen: if a communication action happens in I, then it is allowed to happen by S. Liveness means “good” communication actions eventually happen.
Multiparty session typing (MPST) MPST [16] is a method to automatically prove safety and liveness of communication protocol implementations relative to specifications. The idea is to write specifications as behavioural types [1, 19] against which implementations are type-checked. Formally, the central theorem is that well-typedness at compile-time implies safety and liveness at run-time. Over the past 10–15 years, much progress has been made, including the development of many tools to combine MPST with mainstream languages (e.g., F# [29], F\(^\star \) [36], Go [5], Java [17, 18], OCaml [20], Rust [26, 27], Scala [2, 6, 12, 30], and TypeScript [28]). Fig. 1 visualises the idea behind MPST in more detail:
Fig. 1:
MPST
Fig. 2:
A few possible runs of the Negotation protocol
1.
First, a protocol among roles \(r_1, \ldots , r_n\) is implemented as a session of processes \(P_1, \ldots , P_n\) (concrete), while it is specified as a global type G (abstract). The global type models the behaviour of all processes together.
 
2.
Next, G is decomposed into local types \(L_1, \ldots , L_n\) by projecting G onto each role. Each local type models the behaviour of one process alone.
 
3.
Last, safety and liveness are verified by type-checking each \(P_i\) against \(L_i\).
 
Example 1
The Negotiation protocol, originally defined in the MPST literature by Neykova et al. [29], consists of roles Alice and Bob. Fig. 2 shows three possible runs. First, a proposal is communicated from Alice to Bob. Next, its acceptance, rejection, or a counter-proposal is communicated from Bob to Alice. Next:
  • In case of an acceptance, a confirmation is communicated from Alice to Bob.
  • In case of a rejection, the protocol ends.
  • In case of a counter-proposal, its acceptance, rejection, or another counter-proposal is communicated from Alice to Bob. And so on.
The following recursive global type specifies the protocol:
Global type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figd_HTML.gif specifies the communication of a value of data type \(t_i\) from role p to role q, followed by \(G_i\), for some \({1} {\le } {i} {\le } {n}\); we omit braces when \({n} {=} {1}\). Global type \(\checkmark \) specifies termination. The following recursive local type, projected from the global type, specifies Bob (Alice is similar):
Local types https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figf_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figg_HTML.gif specify the send and receive of a value of data type \(t_i\) from role p to role q, followed by \(L_i\), for some \({1} {\le } {i} {\le } {n}\); we omit braces when \({n} {=} {1}\). Local type \(\checkmark \) specifies termination. The following process, well-typed by the local type, implements a version of Bob:
Process https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figi_HTML.gif implements the send of the value of expression e from role p to role q, followed by P, in session x. Process https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figj_HTML.gif implements the receive of a value of data type \(t_i\) into variable \(x_i\), followed by \(P_i\), in session x, for some \({1} {\le } {i} {\le } {n}\); we omit braces when \({n} {=} {1}\). Process \(\textbf{0}\) implements termination. Processes \(\textbf{loop}_{x}{P}\) and \(\textbf{recur}_{x}\) implement iteration in session x.    \(\square \)
Fig. 3:
Workflow of external-DSL-based MPST tools
In practice [34], the premier approach to combine MPST with mainstream languages—in the absence of native support—is based on: (1) external DSLs1 to write global types; (2) associated tooling to generate corresponding code in mainstream languages, including Scribble [17, 18], its extensions [5, 8, 9, 2630, 36], StMungo [25], mpstpp [24], \(\upnu \)Scr [35], Pompset [6], Teatrino [2], and Oven [12].
The key ideas of the external-DSL-based approach were originally conceived by Deniélou, Hu, and Yoshida. It is based on two insights: local types can be interpreted as finite-state machines (FSM) [10, 11], where states and transitions model sends and receives; FSMs can be encoded as object-oriented application programming interfaces (API) [17, 18], where classes and methods model states and transitions. Fig. 3 visualises the workflow. First, the programmer writes a global type in a DSL; this is the input of the MPST tool. Next, the MPST tool projects the global type to local types, interprets the local types as FSMs, and encodes the FSMs as APIs in the mainstream language; this is the output of the MPST tool. Last, the programmer uses the APIs to write processes.
Fig. 4:
Global type for Negotation (Scribble)
Fig. 5:
FSM for Bob
Fig. 6:
Callback-based API for Bob (Scala)
Fig. 7:
Process for Bob
Example 2
Fig. 4 shows a global type for Negotiation (cf. G in Exmp. 1), written in the external DSL of Scribble. Statement https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figk_HTML.gif specifies the communication of a value of data type t from p to q. Statement   https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figl_HTML.gif specifies a choice among \(G_1, \ldots , G_k\) made by r.
Fig. 5 shows the FSM for Bob, derivable from Fig. 4. Transition labels https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figm_HTML.gif and \(pq \text {?}t\) specify the send and receive of a value of data type t from p to q.
Fig. 6 shows a callback-based API for Bob in Scala, derivable from Fig. 5. Trait https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Fign_HTML.gif in the API corresponds with state i of the FSM; methods of trait https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figo_HTML.gif correspond with transitions of state i. Traits https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figp_HTML.gif and   https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figq_HTML.gif also extend trait https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figr_HTML.gif to be able to start callback-based iteration in states 2 and 3 (i.e., these are the only states on a cycle in the FSM) in a type-sound manner. We note that each method and each callback returns a value of type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figs_HTML.gif to ensure that the program can terminate only when the final state has been reached.
To demonstrate the usage of the API, Fig. 7 shows a process for Bob (cf. P in Exmp. 1). The idea is to write a function, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figt_HTML.gif , that consumes an “initial state object”   https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figu_HTML.gif as input and produces a “final state object” https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figv_HTML.gif as output. First, the only communication action that can be performed, is the one for which https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figw_HTML.gif has a method (receiving). When that method is called, the actual receive is performed, and the callback is called with the received value https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figx_HTML.gif and a fresh “successor state object” https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figy_HTML.gif . Next, the only communication actions that can be performed, are the ones for which https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figz_HTML.gif has a method (sending). And so on.    \(\square \)
This work The external-DSL-based approach is well-established in the MPST literature: it is used in all MPST tools [5, 6, 8, 9, 12, 17, 18, 20, 2430, 35, 36] that support classical MPST as in Fig. 1 (global types and projection; fully automatic; static up-to linearity). However, despite the major impact, it has two weaknesses:
  • Programming friction: The usage of an external DSL to specify protocols as global types causes programming friction. In general, this is a well-documented issue with external DSLs (e.g., [13]): new syntax needs to be learned; new tools to edit DSL code need to be adopted; extra effort is needed to intermix DSL code with the mainstream language.
  • Leaky abstractions: As demonstrated in Exmp. 2, APIs generated by MPST tools leak internal details: global types are essentially declarative, whereas the FSMs that seep through the APIs are essentially imperative. This representational gap causes dissonance between the level of abstraction at which global types are produced by the programmer (before API generation), and the level of abstraction at which local types are consumed by that same programmer in terms of FSMs (after API generation).
To avoid these weaknesses, we explore a different approach and study the question of how to support classical MPST by using internal DSLs. Answering this question positively, we present the mpst.embedded library: it leverages Scala’s “lightweight form of dependent typing” [3], called match types, to embed global/local types directly into Scala. As a result, mpst.embedded offers a frictionless interface between global/local types and processes (i.e., no new syntax, editors, or other tools need to be adopted). Moreover, mpst.embedded avoids leaky abstractions by not relying on FSMs; global/local types are first-class citizens.
In this way, mpst.embedded is the first internal-DSL-based MPST tool that supports all key aspects of classical MPST as in Fig. 1 (unlike Imai et al. [20], who do not support n-ary choice and require extra manual work to guide projection). This is a significant contribution, because: (a) internal DSLs have advantages over external DSLs, but (b) it is far from obvious how to build an internal DSL for MPST in a mainstream language without native support for session types.
Technically, to apply classical MPST and offer static guarantees, some form of compile-time computation is needed. This is the role of match types. They are essentially match expressions at the type level, which are evaluated by the Scala compiler as part of its static analysis, and which we use in this work to embed MPST theory. That is, the Scala compiler can check the typing rules of MPST theory by evaluating carefully crafted match types.
First, through extensive examples, we give an overview of the capabilities of mpst.embedded (Sect. 2 and Sect. 3). Next, we present technical details (Sect. 4). Last, we conclude this paper with related work and future work (Sect. 5).
Fig. 8:
Correspondence between mpst.embedded (left) and MPST theory (right)

2 A Tour of mpst.embedded: Basic Features

Global types Fig. 8 (top rows) shows the correspondence between global types in mpst.embedded and in MPST theory. In mpst.embedded, each global type G is built from classes https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figaa_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figab_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figac_HTML.gif , and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figad_HTML.gif . The third type parameter of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figae_HTML.gif is an n-ary product type, called “the branches”. Type parameter X of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figaf_HTML.gif is bound in type parameter G to the whole https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figag_HTML.gif , to embed a recursive type. Each role p or q, and each recursion variable X, is a Scala string literal type (e.g., https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figah_HTML.gif is a type with one inhabitant, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figai_HTML.gif ). Each data type t is a Scala type.
Fig. 9:
Global type for Negotiation
Fig. 10:
Local type for Bob
Fig. 11:
Processes for Alice and Bob
Example 3
Fig. 9 shows a global type for Negotiation (cf. G in Exmp. 1).    \(\square \)
Local types and projection Fig. 8 (middle rows) shows the correspondence between local types in mpst.embedded and in MPST theory. We add that local types can be computed from global types fully automatically and statically via type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figaj_HTML.gif : the Scala compiler reduces https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figak_HTML.gif to the projection of G onto r.
Example 4
Fig. 10 shows a local type for Bob (cf. \(L_{\texttt{b}}\) in Exmp. 1). Alternatively, it can be computed by having the Scala compiler reduce https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figal_HTML.gif .    \(\square \)
Processes and type checking Fig. 8 (bottom rows) shows the correspondence between processes in mpst.embedded and in MPST theory. In mpst.embedded, each process is a sequence of calls to methods https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figam_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figan_HTML.gif , https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figao_HTML.gif , and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figap_HTML.gif of class https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figaq_HTML.gif . This generic class has two type parameters: one to represent a role (enacted by the process), and another one to represent a local type (with which the process must comply). In turn, instances of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figar_HTML.gif are obtained through calls to method https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figas_HTML.gif of class https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figat_HTML.gif . This generic class has one type parameter to represent a global type (with which all processes must comply). Method https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figau_HTML.gif consumes a role, initialises the session for it, and produces a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figav_HTML.gif object for it. Calls to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figaw_HTML.gif  are blocking: they return only when all processes have called https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figax_HTML.gif .
Intuitively, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figay_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figaz_HTML.gif objects represent executable sessions from the global and local perspective, leveraging the same abstractions as the global and local types by which they are parametrised (no leaky abstractions).
Example 5
Fig. 11 shows processes for Alice and Bob on lines 1–19 and 21–31 (cf. P in Exmp. 1), plus session initiation on lines 33–35. We make three remarks:
  • The process for Bob looks similar to Fig. 7. However, Fig. 11 is defined in terms of communication actions in a session ( https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figba_HTML.gif objects), whereas Fig. 7 is defined in terms of transitions of an FSM ( https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbb_HTML.gif objects).
  • The process for Bob exactly mimics the recursive structure of local type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbc_HTML.gif . Such mimicry is not a general requirement for well-typed processes, as demonstrated by the process for Alice: instead of exactly mimicking the recursive structure of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbd_HTML.gif (which has a similar recursive structure as https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbe_HTML.gif in Fig. 9), it mimics two unfoldings of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbf_HTML.gif , followed by termination. That is, lines 5–15 in Fig. 11 comply with the first unfolding, while lines 16–19 comply with the second unfolding, without entering a loop.    \(\square \)
Using mpst.embedded, the Scala compiler statically checks for each call \(\alpha \) on a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbg_HTML.gif object, parametrised by local type L, whether or not \(\alpha \) complies with L. If not, the Scala compiler reports an error. In this way, mpst.embedded assures that well-typedness at compile-time implies safety and liveness at run-time, modulo linear usage of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbh_HTML.gif objects (checked dynamically), and modulo non-terminating/exceptional behaviour (unchecked). These two provisos are standard for MPST tools. As the type parameters of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbi_HTML.gif objects are erased at compile-time, only generic https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbj_HTML.gif objects exist at run-time.
Example 6
The following protocol violations are reported at compile-time:
  • In Fig. 11, replace line 29 with one of the following:
  • In Fig. 11, uncomment line 26 and replace line 31 with:
The following protocol violation is reported as an error at run-time:
  • In Fig. 11, replace line 31 with:
The technical report [22] contains a screenshot of error reporting.    \(\square \)
Besides protocol violations, additionally, basic well-formedness violations of global types are reported as errors at compile-time; they are checked as part of the instantiation of generic class https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbp_HTML.gif (e.g., Fig. 11, line 33). For instance, for https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbq_HTML.gif , we always require \(p \ne q\) and \(n \ge 1\).

3 The Tour, Continued: Advanced Features

Full merging To project global types, an auxiliary partial operator to merge local types—the projections—is needed. There are two variants [31]: “plain” (basic) and “full” (advanced). Plain merge is relatively easy to support, but it works for few local types, so many global types cannot be projected. Conversely, full merge works for many local types, but it is relatively hard to support. For instance, Imai et al. [20] support only manual full merge (i.e., the programmer must write extra protocol-specific code to guide the computation of projections). In contrast, mpst.embedded supports automatic full merge via type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbr_HTML.gif : the Scala compiler reduces https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbs_HTML.gif to the full merge of \(L_1\) and \(L_2\).
Fig. 12:
Global type for Two-Buyer
Fig. 13:
Local type for Seller
Fig. 14:
Process for Seller
Fig. 15:
Global types for Three-Buyer
Fig. 16:
Process for Buyer2
Fig. 17:
Process for Buyer3
Example 7
The Two-Buyer protocol, originally defined in the MPST literature by Honda et al. [16], consists of roles Buyer1, Buyer2, and Seller: “[Buyer1 and Buyer2] wish to buy an expensive book from Seller by combining their money. Buyer1 sends the title of the book to Seller, Seller sends to both Buyer1 and Buyer2 its quote, Buyer1 tells Buyer2 how much she can pay, and Buyer2 either accepts the quote or rejects the quote by notifying Seller.” We use an extended version defined by Coppo et al. [7], in which Buyer2 notifies not only Seller about acceptance/rejection, but also Buyer1. In the case of acceptance, Buyer2 sends his address to Seller, and Seller sends back the delivery date to Buyer2.
Fig. 12 and Fig. 13 show a global type for Two-Buyer and a local type for Seller (split into https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbt_HTML.gif / https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbu_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbv_HTML.gif / https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbw_HTML.gif for presentational reasons.) First, we note that the communication from Buyer1 to Buyer2 on line 5 in the global type has no counterpart on line 5 in the local type; as Seller does not participate in the communication, it is simply skipped in the projection. Second, we note that the communication from Buyer2 to Buyer1 on line 9 in the global type is ignored, too, but the projections of the two branches do need to be combined into one. This is achieved by having the Scala compiler reduce
  https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbx_HTML.gif
to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figby_HTML.gif .
Fig. 14 shows a process for Seller. It demonstrates that merging is a type-level concept, hidden from the programmer: the Scala compiler reduces https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figbz_HTML.gif and type-checks the code against the result transparently.    \(\square \)
Delegation Sessions are higher-order: https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figca_HTML.gif object   https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcb_HTML.gif for a first session can be delegated between processes via https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcc_HTML.gif object https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcd_HTML.gif for a second session, by sending https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figce_HTML.gif via https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcf_HTML.gif . In the presence of delegation, within each session, well-typedness at compile-time continues to imply safety and liveness at run-time (modulo the “two provisos”; page 8). However, between sessions, liveness is not assured; supporting this would require substantial extra technical machinery [7], so none of the existing MPST tools support it.
Example 8
The Three-Buyer protocol, originally defined in the MPST literature by Coppo et al. [7], consists of roles Buyer1, Buyer2, Buyer3, and Seller. It resembles the Two-Buyer protocol, except that Buyer2 can ask Buyer3 to enact his role on his behalf—unbeknownst to Buyer1 and Seller—through delegation.
Fig. 15 shows global types for Three-Buyer. Global type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcg_HTML.gif specifies the first sub-protocol among Buyer1, Buyer2, and Seller; it is identical to the global type for Two-Buyer. Global type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figch_HTML.gif specifies the second sub-protocol between Buyer2 and Buyer3. Notably, line 8 specifies the delegation from Buyer2 to Buyer3.
Fig. 16 shows a process for Buyer2: on lines 1–4, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figci_HTML.gif objects for two sessions are consumed as inputs (to engage in two sub-protocols); on lines 5–6, the first session is used; on lines 7–10, the second session is used; on line 8, the remainder of the first session is delegated via the second session. Similarly, Fig. 17 shows a process for Buyer3: on lines 1–3, a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcj_HTML.gif object for the first session is consumed as input; on line 5, a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figck_HTML.gif object for the second session is received.
The process for Seller is exactly the same in Three-Buyer as in Two-Buyer (Fig. 14). In particular, Seller does not know that it communicates with Buyer3 instead of Buyer2. Thus, delegation is hidden from each role not involved.    \(\square \)
Generic global types By embedding global/local types as Scala types, Scala’s built-in mechanism of type parametrisation is readily available. This allows the programmer to write generic global types with type parameters for roles (common in external-DSL-based MPST tools) and sub-protocols (novel of mpst.embedded).
Fig. 18:
Generic global types for Negotiation
Example 9
To alleviate the repetitive feel of Fig. 9, Fig. 18 shows generic global types that leverage type parameters. Type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcl_HTML.gif generically specifies the communication of an acceptance, rejection, or counter-proposal from https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcm_HTML.gif to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcn_HTML.gif (type parameters for roles), followed by https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figco_HTML.gif (type parameter for a sub-protocol) in case of a counter-proposal; it can be instantiated twice to replace lines 5–7 and lines 8–10 in Fig. 9. This is done in type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcp_HTML.gif , which generically specifies a role-parametric version of the whole https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcq_HTML.gif in Fig. 9. Thus, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcr_HTML.gif is equivalent to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcs_HTML.gif in Fig. 9.    \(\square \)
Consistency mpst.embedded also supports explicit consistency checking of sets of local types. Details can be found in the technical report [22], as they are rather technical/subtle. We do evaluate consistency checking times in Sect. 4.3, though.

4 Technical Details

As mpst.embedded closely follows MPST theory, and as it uses unique parts of the Scala type system, first, we summarise a few essential preliminaries (Sect. 4.1). Next, we describe our embedding of MPST into Scala (Sect. 4.2).
This section focusses on the basic features of Sect. 2. It allows us to keep the necessary background on MPST theory simple and succinct, while still being able to explain the general ideas of the embedding into the Scala type system in sufficient depth. The advanced features of Sect. 3 are based on more complex theoretical concepts, but their embedding follows similar general ideas.
Fig. 19:
Projection in MPST theory
Fig. 20:
Type checking in MPST theory (excerpt)

4.1 Preliminaries

MPST theory We summarise the theory behind classical MPST (Fig. 1):
  • Global types, local types, and processes: The syntax was defined and explained in Fig. 8 (right column) and Exmp. 1.
  • Projection: Let \(G \mathbin {{\upharpoonright }}r\) denote the projection of G onto r; it is defined in Fig. 19. The projection of a communication yields a send if r is the sender, a receive if r is the receiver, or the full merge—denoted by \(\sqcap \)—of the projected branches otherwise (i.e., r does not participate in the communication).
  • Type checking: Let \(\varGamma \mathrel {{\vdash }} P\) denote well-typedness of P in typing environment \(\varGamma \); it is defined in Fig. 20. Rule [Send] states that a send from p to q in x is well-typed when the local type of x specifies a send, e is well-typed by \(t_j\), and P is well-typed after setting the local type of x to \(L_j\) in the typing environment, for some j. Rule [Recv] states that a receive from p to q in x is well-typed when the local type of x specifies a receive, and \(P_i\) is well-typed after setting the local type of x to \(L_i\) in the typing environment, for each i. Thus, there is asymmetry: for sending, only one send specified must be implemented, but for receiving, each receive specified must be implemented.
  • Central theorem: Static well-typedness implies dynamic safety and liveness.
Match types in Scala The main feature of the Scala type system that we take advantage of in mpst.embedded  is match types. We explain it with an example. Suppose that we need to write a function to convert https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figct_HTML.gif s and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcu_HTML.gif s:
However, return type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcw_HTML.gif is not precise enough. For instance, the Scala compiler fails to prove that https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcx_HTML.gif is safe, as it cannot infer that https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcy_HTML.gif is https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figcz_HTML.gif . What is missing, is a relation between the actual type of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figda_HTML.gif (e.g., https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdb_HTML.gif ) and the return type (e.g., https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdc_HTML.gif ). Match types define such relations.
1.
First, we redefine the signature of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdd_HTML.gif as follows:
Thus, we introduce a type parameter https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdf_HTML.gif (subtype of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdg_HTML.gif ) and declare https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdh_HTML.gif to be https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdi_HTML.gif . Also, we declare the return value to be of match type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdj_HTML.gif .
 
2.
Next, the idea is to define https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdk_HTML.gif in such a way that the relation between the actual type of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdl_HTML.gif and the return type can be inferred, as follows:
The Scala compiler reduces every occurrence of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdn_HTML.gif to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdo_HTML.gif or https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdp_HTML.gif , depending on the instantiation of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdq_HTML.gif (e.g., https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdr_HTML.gif is reduced to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figds_HTML.gif ).
 
3.
Last, for instance, the Scala compiler correctly succeeds/fails to type-check https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdt_HTML.gif (safe) and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdu_HTML.gif (unsafe).
 
Thus, match types are a “lightweight form of dependent typing” [3], to perform “type-level programming”. In the remainder, we use the following built-ins:
  • https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdv_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdw_HTML.gif reduce to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdx_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdy_HTML.gif .
  • https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figdz_HTML.gif reduces to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figea_HTML.gif . We note that https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figeb_HTML.gif can be a type lambda of the form https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figec_HTML.gif .

4.2 Embedding MPST into Scala

Global types, local types, processes As explained in Sect. 2, and as shown in Fig. 8, global types and local types are implemented as classes, while processes are implemented as methods of class https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figed_HTML.gif . The communication infrastructure for processes is based on concurrent queues. However, a transport layer for distributed processes is also possible (orthogonal concern).
Fig. 21:
Projection in mpst.embedded
Projection Fig. 21 shows match type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figee_HTML.gif . It is used to have the Scala compiler fully automatically and statically compute local types (e.g., line 2 in Fig. 11).
Match type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figef_HTML.gif has two type parameters: a global type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figeg_HTML.gif and a role https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figeh_HTML.gif (cf. \(G \mathbin {{\upharpoonright }}r\)). To reduce https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figei_HTML.gif , the Scala compiler matches https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figej_HTML.gif to a global type constructor, and it produces a local type exactly as defined in Fig. 19. By convention, lower case letters in patterns are type variables; they are bound to types as part of the matching algorithm. For instance, on lines 3–5 in Fig. 21, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figek_HTML.gif is bound to a product type of the form https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figel_HTML.gif , where each https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figem_HTML.gif is a data type, and each https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figen_HTML.gif is a global type. When https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figeo_HTML.gif is passed to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figep_HTML.gif  on lines 3–4, it is converted into https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figeq_HTML.gif . Alternatively, when https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figer_HTML.gif is passed to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figes_HTML.gif on line 5, it is converted into https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/648515_1_En_8_Figet_HTML.gif , which is subsequently passed to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figeu_HTML.gif ; this is a helper match type that reduces to the full merge of all local types in the product type.
Fig. 22:
Type checking in mpst.embedded (excerpt)
Type checking Fig. 22 shows an excerpt of class https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figev_HTML.gif related to type checking. The idea is to have the Scala compiler reduce match types https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figew_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figex_HTML.gif to fully automatically and statically compute the expected types of the callback arguments of methods https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figey_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figez_HTML.gif , given a local type L. The reduction succeeds, and the actual callback argument is well-typed by the expected type, if, and only if, the communication action is well-typed by L exactly as defined in Fig. 20. Otherwise, the Scala compiler reports an error. In this way, mpst.embedded implements the same MPST typing rules as in Fig. 20 in terms of Scala match type reduction, and it provides the same assurances (modulo the “two provisos”; page 8):
  • if, at compile-time, each process is well-typed by its projection,
  • then, at run-time, the session of all processes is safe and live,
  • modulo linear usage of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfa_HTML.gif objects (checked dynamically),
  • modulo non-terminating/exceptional behaviour (unchecked).
We now explain https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfb_HTML.gif and https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfc_HTML.gif . Regarding https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfd_HTML.gif , Fig. 20 states that a send is well-typed if the local type specifies it directly (rule [Send]) or indirectly (rule [Unfold]). These cases correspond precisely to the two cases in https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfe_HTML.gif :
  • Lines 6–7 state that a send is well-typed if the sender, receiver, and data type match the send of the local type https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figff_HTML.gif , and if the callback is a function that consumes a https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfg_HTML.gif object, parametrised by the selected branch of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfh_HTML.gif , namely https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfi_HTML.gif . We note that https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfj_HTML.gif https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfk_HTML.gif reduces to https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfl_HTML.gif .
  • Line 8 states that a send is also well-typed when it is well-typed by the unfolding of the local type. We note that https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfm_HTML.gif reduces to a version of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfn_HTML.gif in which each occurrence of https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfo_HTML.gif is replaced with https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfp_HTML.gif .
Regarding https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfq_HTML.gif , similarly, Fig. 20 states that a receive is well-typed if the local type specifies the receive directly (rule [Recv]) or indirectly (rule [Unfold]). Due to the asymmetry between sends and receives, https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfr_HTML.gif (singular) reduces to a single function type, while https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figfs_HTML.gif (plural) reduces to a product of function types, computed using https://static-content.springer.com/image/chp%3A10.1007%2F978-3-031-90643-5_8/MediaObjects/648515_1_En_8_Figft_HTML.gif . Besides that, they follow the same ideas.

4.3 Evaluation and Discussion

Compile-time performance To validate the practical feasibility of using mpst.embedded, we systematically measured the type checking times during non-incremental compilation of all examples in Sect. 2 and Sect. 3, as well as twelve additional examples from the MPST literature [7, 30, 31] and the Scribble repository [14].2 This is a representative set of protocols, previously developed by other researchers (including the protocols in our examples in Sect. 2 and Sect. 3), of various sizes, that exercise all aspects of classical MPST theory.3
To measure only the protocol-related type checking times, the processes contained almost no computation code; just communication actions in compliance with the protocol. The measurements were obtained using an Intel i7-8569U processor (4 physical/4 virtual cores at 2.8 GHz) and 16 GB of memory, running macOS 14.0, OpenJDK 18.0.2, and Scala 3.3.1. We ran the measurements with consistency checking disabled and enabled, to be able to study the difference.
Table 1.
Type checking times in milliseconds, reported as \(\mu \pm \sigma \), where \(\mu \) is the average (of 31 measurements), and where \(\sigma \) is the standard deviation
protocol
type checking
without consistency
type checking
with consistency
difference\(^\dagger \)
Negotiation (Exmp. 5)
\({1,399}\pm {118}\,\textrm{ms}\)
\({1,254}\pm {36}\,\textrm{ms}\)
\({-145}\pm {125}\,\textrm{ms}\)
Negotiation (Exmp. 9)
\({1,299}\pm {85}\,\textrm{ms}\)
\({1,240}\pm {22}\,\textrm{ms}\)
\({-60}\pm {88}\,\textrm{ms}\)
Two-Buyer (Exmp. 7)
\({1,399}\pm {31}\,\textrm{ms}\)
\({1,658}\pm {50}\,\textrm{ms}\)
\({258}\pm {59}\,\textrm{ms}\)
Three-Buyer (Exmp. 8)
\({1,489}\pm {57}\,\textrm{ms}\)
\({1,728}\pm {50}\,\textrm{ms}\)
\({239}\pm {76}\,\textrm{ms}\)
Three-Buyer [7]
\({1,341}\pm {57}\,\textrm{ms}\)
\({1,622}\pm {71}\,\textrm{ms}\)
\({280}\pm {78}\,\textrm{ms}\)
OAuth2 Fragment [31]
\({713}\pm {24}\,\textrm{ms}\)
inconsistent
inconsistent
Rec. Two-Buyers [31]
\({775}\pm {24}\,\textrm{ms}\)
inconsistent
inconsistent
Rec. Map/Reduce [31]
\({1,016}\pm {45}\,\textrm{ms}\)
inconsistent
inconsistent
MP Workers [31]
\({891}\pm {27}\,\textrm{ms}\)
inconsistent
inconsistent
Game [30]
\({1,095}\pm {35}\,\textrm{ms}\)
\({1,338}\pm {29}\,\textrm{ms}\)
\({243}\pm {46}\,\textrm{ms}\)
Adder [14]
\({763}\pm {21}\,\textrm{ms}\)
\({781}\pm {19}\,\textrm{ms}\)
\({18}\pm {28}\,\textrm{ms}\)
Booking [14]
\({1,099}\pm {35}\,\textrm{ms}\)
inconsistent
inconsistent
Fibonacci [14]
\({759}\pm {22}\,\textrm{ms}\)
\({779}\pm {17}\,\textrm{ms}\)
\({20}\pm {28}\,\textrm{ms}\)
HTTP [14]
\({1,703}\pm {41}\,\textrm{ms}\)
\({1,838}\pm {77}\,\textrm{ms}\)
\({134}\pm {88}\,\textrm{ms}\)
Loan Application [14]
\({879}\pm {48}\,\textrm{ms}\)
\({1132}\pm {29}\,\textrm{ms}\)
\({253}\pm {56}\,\textrm{ms}\)
SMTP [14]
\({1,726}\pm {70}\,\textrm{ms}\)
\({2079}\pm {128}\,\textrm{ms}\)
\({353}\pm {146}\,\textrm{ms}\)
\(^\dagger \) The difference between type checking times without consistency \(\mu _1 \pm \sigma _1\) and with consistency \(\mu _2 \pm \sigma _2\) are reported as \(\mu \pm \sigma \), where \(\mu = \mu _2 - \mu _1\) and \(\sigma = \sqrt{\sigma _1^2 + \sigma _2^2}\)
Table 1 shows the results, averaged over 31 runs per protocol. We make two main observations. First, without consistency checks, the type checking times seem sufficiently low for the usage of mpst.embedded to be practically feasible: less than two seconds for the biggest protocol in our benchmark set (SMTP). Moreover, our measurements were obtained using non-incremental compilation and, as such, constitute an upper bound on the expected type checking delays when using incremental compilation. Anecdotally, in our development environment (Visual Studio Code 1.87 with the Metals 1.30 extension for Scala programming), when using incremental compilation, the type checking delays were significantly lower (\({<}100\) ms) than those in Table 1, and not disruptive at all.
Second, with consistency checks (i.e., five examples violate consistency; this was expected), the results show that some overhead is added, but it does not make the usage of mpst.embedded infeasible (\({<}500\) ms). Also, when using incremental compilation, the type checking delays continued to not get in the way.
Experience The implementation of the benchmark set turned out to be, in its own right, a validation activity to experience whether or not the type checker catches all mistakes in practice. This is because, until a protocol implementation is finished, it does not comply with the specification yet. Thus, all until the end, the type checker reports errors to point out missing pieces. This guidance by the type checker effectively prevented us from making unintended programming mistakes, especially when writing the implementations of HTTP and SMTP (which are the more complicated protocols in our benchmark set). It would be interesting to try to reproduce these anecdotal findings in a larger user study.
Expressiveness Our benchmark set shows that mpst.embedded is feature-complete relative to classical MPST theory,\(^\text {3}\) with full merging (e.g., the OAuth2 fragment requires full merge), as intended. Moreover, while the ability to write generic global types does not add expressive power in the formal sense, it enables better reuse of global types and serves as an abstraction/composition mechanism: it allows large protocols to be split into separate smaller sub-protocols—specified as generically as possible to maximise the opportunity for reuse—which can then be “invoked” from each other with concrete arguments. Such generic sub-protocols can also be packaged into libraries and shared between projects.

5 Conclusion

Related work Closest to our approach in this paper is the work by Imai et al. [20]. They developed an internal DSL in OCaml to specify protocols and verify processes based on MPST. However, their tool does not support all key aspects of classical MPST as in Fig. 1: it supports only binary choices instead of n-ary choices (e.g., Exmp. 1, which has ternary choices, is not supported), and it is not fully automatic (i.e., Imai et al. require the programmer to manually write extra protocol-specific code to project global types). In contrast, mpst.embedded supports n-ary choices and is fully automatic.
Another related tool is the Discourje library [15], which offers an MPST-based internal DSL in Clojure. However, Discourje does all verification dynamically, whereas mpst.embedded performs all verification statically up-to linearity.
Table 2.
Comparison of MPST tools for Scala
 
DSL
projection
interpretation
encoding
Scribble-Scala [30]
external
syntactic
FSMs
lchannels
Pompset [6]
external
syntactic
pomsets
vanilla Scala
Teatrino [2]
external
syntactic
Effpi
Oven [12]
external
semantic
FSMs
vanilla Scala
mpst.embedded
internal
syntactic
vanilla Scala
There are four existing tools to combine MPST with Scala: Scribble-Scala [30], Pompset [6], Teatrino [2], and Oven [12]. Table 2 summarises the differences:
  • DSLs to specify protocols as global types: Scribble-Scala, Pompset, and Teatrino are based on the external DSL of Scribble, while Oven is based on an external DSL for regular expressions.
  • Projection of global types: Scribble-Scala, Pompset, and Teatrino apply the classical structural projection operator (defined in terms of the syntax of global types; Sect. 4.2), while Oven applies a non-classical behavioural projection operator (defined in terms of the operational semantics of global types). The latter has additional expressive power to support the usage of regular expressions as global types [23].
  • Interpretation of local types: Different from Fig. 3, Pompset uses partially-ordered multisets instead of FSMs as an intermediate operational model, while Teatrino directly encodes local types as APIs in Scala.
  • Encoding as APIs: The APIs generated by Scribble-Scala and Teatrino are built on top of the existing libraries lchannels and Effpi (discussed in more detail below), while Pompset and Oven do not rely on such existing libraries.
Besides these existing tools to combine multiparty session typing with Scala (including global types and projection), there also exist libraries to combine binary session typing with Scala (excluding global types and projection), namely lchannels [30] and Effpi [32]. Conceptually, as mpst.embedded targets multiparty instead of binary, it is not really comparable to lchannels and Effpi. Technically, moreover, lchannels and Effpi do not use match types.
Future work Many extensions of MPST theory have been proposed. We are keen to explore which of them can be incorporated in mpst.embedded using match types. For instance, an important feature that we believe is compatible with mpst.embedded and match types is parameterised MPST with indexed roles as developed by Castro et al. [5]. Another feature that seems representable using match types, is MPST with refinements along the lines of Zhou et al. [36]. In contrast, a feature that seems prohibitively difficult to incorporate, is timed MPST [4]: match types seem unsuitable to statically offer real-time guarantees.
Open Access This chapter is licensed under the terms of the Creative Commons Attribution 4.0 International License (http://​creativecommons.​org/​licenses/​by/​4.​0/​), which permits use, sharing, adaptation, distribution and reproduction in any medium or format, as long as you give appropriate credit to the original author(s) and the source, provide a link to the Creative Commons license and indicate if changes were made.
The images or other third party material in this chapter are included in the chapter's Creative Commons license, unless indicated otherwise in a credit line to the material. If material is not included in the chapter's Creative Commons license and your intended use is not permitted by statutory regulation or exceeds the permitted use, you will need to obtain permission directly from the copyright holder.
Fußnoten
1
A domain-specific language (DSL) is either external or internal. External DSLs are stand-alone languages with their own dedicated syntax, while internal DSLs are embedded languages into a general-purpose language (GPL) with syntax inherited from that GPL. Both approaches have advantages and disadvantages [13].
 
2
Run-time performance (e.g., latency/throughput) depends on the transport mechanism for message passing, which is orthogonal to the contributions of this paper.
 
3
That is, the theory as originally defined by Honda et al. [16], but presented in the more recent style of, e.g., Scalas–Yoshida [31], including the full merge operator.
 
Literatur
1.
Zurück zum Zitat Ancona et al., D.: Behavioral types in programming languages. Foundations and Trends in Programming Languages 3(2-3), 95–230 (2016) Ancona et al., D.: Behavioral types in programming languages. Foundations and Trends in Programming Languages 3(2-3), 95–230 (2016)
2.
Zurück zum Zitat Barwell, A.D., Hou, P., Yoshida, N., Zhou, F.: Designing asynchronous multiparty protocols with crash-stop failures. In: ECOOP. LIPIcs, vol. 263, pp. 1:1–1:30. Schloss Dagstuhl - Leibniz-Zentrum für Informatik (2023) Barwell, A.D., Hou, P., Yoshida, N., Zhou, F.: Designing asynchronous multiparty protocols with crash-stop failures. In: ECOOP. LIPIcs, vol. 263, pp. 1:1–1:30. Schloss Dagstuhl - Leibniz-Zentrum für Informatik (2023)
3.
Zurück zum Zitat Blanvillain, O., Brachthäuser, J.I., Kjaer, M., Odersky, M.: Type-level programming with match types. Proc. ACM Program. Lang. 6(POPL), 1–24 (2022) Blanvillain, O., Brachthäuser, J.I., Kjaer, M., Odersky, M.: Type-level programming with match types. Proc. ACM Program. Lang. 6(POPL), 1–24 (2022)
4.
Zurück zum Zitat Bocchi, L., Yang, W., Yoshida, N.: Timed multiparty session types. In: CONCUR. LNCS, vol. 8704, pp. 419–434. Springer (2014) Bocchi, L., Yang, W., Yoshida, N.: Timed multiparty session types. In: CONCUR. LNCS, vol. 8704, pp. 419–434. Springer (2014)
5.
Zurück zum Zitat Castro, D., Hu, R., Jongmans, S., Ng, N., Yoshida, N.: Distributed programming using role-parametric session types in go: statically-typed endpoint apis for dynamically-instantiated communication structures. PACMPL 3(POPL), 29:1–29:30 (2019) Castro, D., Hu, R., Jongmans, S., Ng, N., Yoshida, N.: Distributed programming using role-parametric session types in go: statically-typed endpoint apis for dynamically-instantiated communication structures. PACMPL 3(POPL), 29:1–29:30 (2019)
6.
Zurück zum Zitat Cledou, G., Edixhoven, L., Jongmans, S., Proença, J.: API generation for multiparty session types, revisited and revised using scala 3. In: ECOOP. LIPIcs, vol. 222, pp. 27:1–27:28. Schloss Dagstuhl - Leibniz-Zentrum für Informatik (2022) Cledou, G., Edixhoven, L., Jongmans, S., Proença, J.: API generation for multiparty session types, revisited and revised using scala 3. In: ECOOP. LIPIcs, vol. 222, pp. 27:1–27:28. Schloss Dagstuhl - Leibniz-Zentrum für Informatik (2022)
7.
Zurück zum Zitat Coppo, M., Dezani-Ciancaglini, M., Yoshida, N., Padovani, L.: Global progress for dynamically interleaved multiparty sessions. Math. Struct. Comput. Sci. 26(2), 238–302 (2016) Coppo, M., Dezani-Ciancaglini, M., Yoshida, N., Padovani, L.: Global progress for dynamically interleaved multiparty sessions. Math. Struct. Comput. Sci. 26(2), 238–302 (2016)
8.
Zurück zum Zitat Cutner, Z., Yoshida, N.: Safe session-based asynchronous coordination in rust. In: COORDINATION. Lecture Notes in Computer Science, vol. 12717, pp. 80–89. Springer (2021) Cutner, Z., Yoshida, N.: Safe session-based asynchronous coordination in rust. In: COORDINATION. Lecture Notes in Computer Science, vol. 12717, pp. 80–89. Springer (2021)
9.
Zurück zum Zitat Cutner, Z., Yoshida, N., Vassor, M.: Deadlock-free asynchronous message reordering in rust with multiparty session types. In: PPoPP. pp. 246–261. ACM (2022) Cutner, Z., Yoshida, N., Vassor, M.: Deadlock-free asynchronous message reordering in rust with multiparty session types. In: PPoPP. pp. 246–261. ACM (2022)
10.
Zurück zum Zitat Deniélou, P., Yoshida, N.: Multiparty session types meet communicating automata. In: ESOP. LNCS, vol. 7211, pp. 194–213. Springer (2012) Deniélou, P., Yoshida, N.: Multiparty session types meet communicating automata. In: ESOP. LNCS, vol. 7211, pp. 194–213. Springer (2012)
11.
Zurück zum Zitat Deniélou, P., Yoshida, N.: Multiparty compatibility in communicating automata: Characterisation and synthesis of global session types. In: ICALP (2). LNCS, vol. 7966, pp. 174–186. Springer (2013) Deniélou, P., Yoshida, N.: Multiparty compatibility in communicating automata: Characterisation and synthesis of global session types. In: ICALP (2). LNCS, vol. 7966, pp. 174–186. Springer (2013)
12.
Zurück zum Zitat Ferreira, F., Jongmans, S.: Oven: Safe and live communication protocols in scala, using synthetic behavioural type analysis. In: ISSTA. pp. 1511–1514. ACM (2023) Ferreira, F., Jongmans, S.: Oven: Safe and live communication protocols in scala, using synthetic behavioural type analysis. In: ISSTA. pp. 1511–1514. ACM (2023)
13.
Zurück zum Zitat Fowler, M.: Domain-Specific Languages. The Addison-Wesley signature series, Addison-Wesley (2011) Fowler, M.: Domain-Specific Languages. The Addison-Wesley signature series, Addison-Wesley (2011)
15.
Zurück zum Zitat Hamers, R., Jongmans, S.: Discourje: Runtime verification of communication protocols in clojure. In: TACAS (1). LNCS, vol. 12078, pp. 266–284. Springer (2020) Hamers, R., Jongmans, S.: Discourje: Runtime verification of communication protocols in clojure. In: TACAS (1). LNCS, vol. 12078, pp. 266–284. Springer (2020)
16.
Zurück zum Zitat Honda, K., Yoshida, N., Carbone, M.: Multiparty asynchronous session types. In: POPL. pp. 273–284. ACM (2008) Honda, K., Yoshida, N., Carbone, M.: Multiparty asynchronous session types. In: POPL. pp. 273–284. ACM (2008)
17.
Zurück zum Zitat Hu, R., Yoshida, N.: Hybrid session verification through endpoint API generation. In: FASE. LNCS, vol. 9633, pp. 401–418. Springer (2016) Hu, R., Yoshida, N.: Hybrid session verification through endpoint API generation. In: FASE. LNCS, vol. 9633, pp. 401–418. Springer (2016)
18.
Zurück zum Zitat Hu, R., Yoshida, N.: Explicit connection actions in multiparty session types. In: FASE. LNCS, vol. 10202, pp. 116–133. Springer (2017) Hu, R., Yoshida, N.: Explicit connection actions in multiparty session types. In: FASE. LNCS, vol. 10202, pp. 116–133. Springer (2017)
19.
Zurück zum Zitat Hüttel, H., Lanese, I., Vasconcelos, V.T., Caires, L., Carbone, M., Deniélou, P., Mostrous, D., Padovani, L., Ravara, A., Tuosto, E., Vieira, H.T., Zavattaro, G.: Foundations of session types and behavioural contracts. ACM Comput. Surv. 49(1), 3:1–3:36 (2016) Hüttel, H., Lanese, I., Vasconcelos, V.T., Caires, L., Carbone, M., Deniélou, P., Mostrous, D., Padovani, L., Ravara, A., Tuosto, E., Vieira, H.T., Zavattaro, G.: Foundations of session types and behavioural contracts. ACM Comput. Surv. 49(1), 3:1–3:36 (2016)
20.
Zurück zum Zitat Imai, K., Neykova, R., Yoshida, N., Yuen, S.: Multiparty session programming with global protocol combinators. In: ECOOP. LIPIcs, vol. 166, pp. 9:1–9:30. Schloss Dagstuhl - Leibniz-Zentrum für Informatik (2020) Imai, K., Neykova, R., Yoshida, N., Yuen, S.: Multiparty session programming with global protocol combinators. In: ECOOP. LIPIcs, vol. 166, pp. 9:1–9:30. Schloss Dagstuhl - Leibniz-Zentrum für Informatik (2020)
23.
Zurück zum Zitat Jongmans, S., Ferreira, F.: Synthetic behavioural typing: Sound, regular multiparty sessions via implicit local types. In: ECOOP. LIPIcs, vol. 263, pp. 42:1–42:30. Schloss Dagstuhl - Leibniz-Zentrum für Informatik(2023) Jongmans, S., Ferreira, F.: Synthetic behavioural typing: Sound, regular multiparty sessions via implicit local types. In: ECOOP. LIPIcs, vol. 263, pp. 42:1–42:30. Schloss Dagstuhl - Leibniz-Zentrum für Informatik(2023)
24.
Zurück zum Zitat Jongmans, S., Yoshida, N.: Exploring type-level bisimilarity towards more expressive multiparty session types. In: ESOP. LNCS, vol. 12075, pp. 251–279. Springer (2020) Jongmans, S., Yoshida, N.: Exploring type-level bisimilarity towards more expressive multiparty session types. In: ESOP. LNCS, vol. 12075, pp. 251–279. Springer (2020)
25.
Zurück zum Zitat Kouzapas, D., Dardha, O., Perera, R., Gay, S.J.: Typechecking protocols with mungo and stmungo: A session type toolchain for java. Sci. Comput. Program. 155, 52–75 (2018) Kouzapas, D., Dardha, O., Perera, R., Gay, S.J.: Typechecking protocols with mungo and stmungo: A session type toolchain for java. Sci. Comput. Program. 155, 52–75 (2018)
26.
Zurück zum Zitat Lagaillardie, N., Neykova, R., Yoshida, N.: Implementing multiparty session types in rust. In: COORDINATION. LNCS, vol. 12134, pp. 127–136. Springer (2020) Lagaillardie, N., Neykova, R., Yoshida, N.: Implementing multiparty session types in rust. In: COORDINATION. LNCS, vol. 12134, pp. 127–136. Springer (2020)
27.
Zurück zum Zitat Lagaillardie, N., Neykova, R., Yoshida, N.: Stay safe under panic: Affine rust programming with multiparty session types. In: ECOOP. LIPIcs, vol. 222, pp. 4:1–4:29. Schloss Dagstuhl - Leibniz-Zentrum für Informatik (2022) Lagaillardie, N., Neykova, R., Yoshida, N.: Stay safe under panic: Affine rust programming with multiparty session types. In: ECOOP. LIPIcs, vol. 222, pp. 4:1–4:29. Schloss Dagstuhl - Leibniz-Zentrum für Informatik (2022)
28.
Zurück zum Zitat Miu, A., Ferreira, F., Yoshida, N., Zhou, F.: Communication-safe web programming in typescript with routed multiparty session types. In: CC. pp. 94–106. ACM (2021) Miu, A., Ferreira, F., Yoshida, N., Zhou, F.: Communication-safe web programming in typescript with routed multiparty session types. In: CC. pp. 94–106. ACM (2021)
29.
Zurück zum Zitat Neykova, R., Hu, R., Yoshida, N., Abdeljallal, F.: A session type provider: compile-time API generation of distributed protocols with refinements in f#. In: CC. pp. 128–138. ACM (2018) Neykova, R., Hu, R., Yoshida, N., Abdeljallal, F.: A session type provider: compile-time API generation of distributed protocols with refinements in f#. In: CC. pp. 128–138. ACM (2018)
30.
Zurück zum Zitat Scalas, A., Dardha, O., Hu, R., Yoshida, N.: A linear decomposition of multiparty sessions for safe distributed programming. In: ECOOP. LIPIcs, vol. 74, pp. 24:1–24:31. Schloss Dagstuhl - Leibniz-Zentrum fuer Informatik (2017) Scalas, A., Dardha, O., Hu, R., Yoshida, N.: A linear decomposition of multiparty sessions for safe distributed programming. In: ECOOP. LIPIcs, vol. 74, pp. 24:1–24:31. Schloss Dagstuhl - Leibniz-Zentrum fuer Informatik (2017)
31.
Zurück zum Zitat Scalas, A., Yoshida, N.: Less is more: multiparty session types revisited. Proc. ACM Program. Lang. 3(POPL), 30:1–30:29 (2019) Scalas, A., Yoshida, N.: Less is more: multiparty session types revisited. Proc. ACM Program. Lang. 3(POPL), 30:1–30:29 (2019)
32.
Zurück zum Zitat Scalas, A., Yoshida, N., Benussi, E.: Verifying message-passing programs with dependent behavioural types. In: PLDI. pp. 502–516. ACM (2019) Scalas, A., Yoshida, N., Benussi, E.: Verifying message-passing programs with dependent behavioural types. In: PLDI. pp. 502–516. ACM (2019)
33.
Zurück zum Zitat Tu, T., Liu, X., Song, L., Zhang, Y.: Understanding real-world concurrency bugs in go. In: ASPLOS. pp. 865–878. ACM (2019) Tu, T., Liu, X., Song, L., Zhang, Y.: Understanding real-world concurrency bugs in go. In: ASPLOS. pp. 865–878. ACM (2019)
34.
Zurück zum Zitat Yoshida, N.: Programming language implementations with multiparty session types. In: Active Object Languages: Current Research Trends, Lecture Notes in Computer Science, vol. 14360, pp. 147–165. Springer (2024) Yoshida, N.: Programming language implementations with multiparty session types. In: Active Object Languages: Current Research Trends, Lecture Notes in Computer Science, vol. 14360, pp. 147–165. Springer (2024)
35.
Zurück zum Zitat Yoshida, N., Zhou, F., Ferreira, F.: Communicating finite state machines and an extensible toolchain for multiparty session types. In: FCT. LNCS, vol. 12867, pp. 18–35. Springer (2021) Yoshida, N., Zhou, F., Ferreira, F.: Communicating finite state machines and an extensible toolchain for multiparty session types. In: FCT. LNCS, vol. 12867, pp. 18–35. Springer (2021)
36.
Zurück zum Zitat Zhou, F., Ferreira, F., Hu, R., Neykova, R., Yoshida, N.: Statically verified refinements for multiparty protocols. Proc. ACM Program. Lang. 4(OOPSLA), 148:1–148:30 (2020) Zhou, F., Ferreira, F., Hu, R., Neykova, R., Yoshida, N.: Statically verified refinements for multiparty protocols. Proc. ACM Program. Lang. 4(OOPSLA), 148:1–148:30 (2020)
Metadaten
Titel
Multiparty Session Typing, Embedded
verfasst von
Sung-Shik Jongmans
Copyright-Jahr
2025
DOI
https://doi.org/10.1007/978-3-031-90643-5_8