Intersections and Unions of Session Types
NN. Kobayashi (Ed.): Eighth Workshopon Intersection Types and Related Systems (ITRS 2016).EPTCS 242, 2017, pp. 4–19, doi:10.4204/EPTCS.242.3 c (cid:13)
C. Acay & F. PfenningThis work is licensed under theCreative Commons Attribution License.
Intersections and Unions of Session Types
Cos¸ku Acay
Carnegie Mellon UniversityPennsylvania, USA [email protected]
Frank Pfenning
Carnegie Mellon UniversityPennsylvania, USA [email protected]
Prior work has extended the deep, logical connection between the linear sequent calculus and session-typed message-passing concurrent computation with equi-recursive types and a natural notion ofsubtyping. In this paper, we extend this further by intersection and union types in order to expressmultiple behavioral properties of processes in a single type. We prove session fidelity and absence ofdeadlock and illustrate the expressive power of our system with some simple examples. We observethat we can represent internal and external choice by intersection and union, respectively, which waspreviously suggested in [6, 18] for a different language of session types motivated by operationalrather than logical concerns.
Prior work has established a Curry-Howard correspondence between intuitionistic linear sequent calculusand session-typed message-passing concurrency [5, 19, 17]. In this formulation, linear propositions areinterpreted as session types, proofs as processes, and cut reduction as communication. Session types areassigned to channels and prescribe the communication behavior along them. Each channel is offered bya unique process and used by exactly one, which is ensured by linearity. When the behavior along achannel c satisfies the type A and P is the process that offers along c , we say that P provides a session oftype A along c .In the base system, each type directly corresponds to a process of a certain form. For example, aprocess providing the type A ⊗ B first sends out a channel satisfying A , then acts as B . Similarly, a processoffering sends the label end and terminates. We call these structural types since they correspond toprocesses of a certain structure. In this paper, we extend the base type system with intersections andunions. We call these property types since they do not correspond to specific forms of processes in thatany process may be assigned such a type. In addition, if we interpret a type as specifying a property, thenintersection corresponds to satisfying two properties simultaneously and union corresponds to satisfyingone or the other.Our goal is to show that the base system extended with intersection, unions, recursive types, and anatural notion of subtyping is type-safe. We do this by proving the usual type preservation and progresstheorems, which correspond to session fidelity and deadlock freedom in the concurrent context. Inthe presence of a strong subtyping relation and transparent (i.e. non-generative) equi-recursive types,intersections and unions turn out to be powerful enough to specify many interesting communicationsbehaviors, which we demonstrate with examples analogous to those in functional languages [12, 10].Our contributions are summarized below: • We introduce intersection and union types to a session-typed concurrent calculus and prove sessionfidelity and deadlock freedom. • We give a simple and sound coinductive subtyping relation in the presence of equi-recursive types,intersections, and unions reminiscent of Gentzen’s multiple conclusion sequent calculus [14, 15]..Acay &F.Pfenning 5 • We show how intersections and unions can be used as refinements of recursive types in a linearsetting. • We show decidability of subtyping and present a system for algorithmic type checking. • We demonstrate how internal and external choice can be understood as singletons interacting withintersection and union.An extended version of this paper can be found at [1].
We give only a brief review of linear logic and its connection to session types here. Interested readers arereferred to [5, 19, 17]. The key idea of linear logic is to treat logical propositions as resources: each mustbe used exactly once in a proof. According to the Curry-Howard isomorphism for intuitionistic linearlogic, propositions are interpreted as session types, proofs as concurrent processes, and cut-eliminationsteps as communication. For this correspondence, hypotheses are labelled with channels (rather thanwith variables). We also assign a channel name to the conclusion so that a process providing a sessioncan refer to the same channel name as process using it. This replaces the usual notion of duality inclassical session-typed calculi [17] and gives us the following form for typing judgments: c : A , . . . , c n : A n ⊢ P :: ( c : A ) which should be interpreted as “ P provides along the channel c the session A using channels c , . . . , c n (linearly) with their corresponding types ”. We assume c , . . . , c n and c are all distinct so that when achannel c occurs in P , its reference is unambiguous. We abbreviate hypotheses using Y , Y ′ , etc.Two key rules explaining this judgment are cut and identity . Logically, cut means that if we canprove A , then we can use it as a resource in the proof of some other proposition C . Operationally, itcorresponds to parallel composition with a private shared variable for communication. Y ⊢ P c :: ( c : A ) Y ′ , c : A ⊢ Q c :: ( d : D ) Y , Y ′ ⊢ c ← P c ; Q c :: ( d : D ) cut We write c ← P c ; Q c instead of the customary ( n c )( P c | Q c ) because it is more readable in actual programs.The subscript here indicates that c is a bound variable and occurs in both P c and Q c .Logically, the identity states the fundamental principle that the resource A can be used to prove theconclusion A . Operationally, it corresponds to forwarding : we provide a session along channel c byforwarding to d . Note that forwarding does not have a direct correspondence in the p -calculus but canbe implemented in terms of other primitives (for example, ! ( c ( d ) . c h d i + d ( c ) . d h c i ) ). d : A ⊢ c ← d :: ( c : A ) id Forwarding is employed in session-typed programming with surprising frequency as will be evident fromthe examples we provide.Cut and identity are general constructs, independent of any particular proposition. The isomorphismtakes shape once we work out the interpretations of all of the connectives of linear logic as session types .We foreshadow the operational interpretation from the perspective of the provider of a session: Intersections and Unions ofSession Types A , B , C ::= send end and terminate | A ⊗ B send channel of type A and continue as B | ⊕{ lab k : A k } k ∈ I send lab i and continue as A i for some i ∈ I | A ⊸ B receive channel of type A and continue as B | & { lab k : A k } k ∈ I receive lab i and continue as A i for some i ∈ I In this paper, we do not need ! A . Instead of replication, we use recursive types to describe recurringbehavior. We also generalize the binary A ⊕ B to ⊕{ lab k : A k } k ∈ I and A & B to & { lab k : A k } k ∈ I , which is inthe tradition of much prior work on session types and makes programs more readable. Here, I is a finite non-empty set of distinct labels whose order does not matter. We call ⊕{ lab k : A k } k ∈ I an internal choicesince the provider selects which branch to take (i.e. the provider sends the label), and & { lab k : A k } k ∈ I anexternal choice since the client makes the decision. The processes (or proof terms) corresponding to these types are given below with the sending constructfollowed by the receiving construct. The notation P x emphasizes the scope of a bound variable x in thecut, send, and receive constructs. As a shorthand for substitution, we write P a for [ a / x ] P , the capture-avoiding substitution of a for x in P . P , Q , R ::= x ← P x ; Q x cut (spawn) | c ← d id (forward) | close c | wait c ; P | send c ( y ← P y ) ; Q | x ← recv c ; R x A ⊗ B , A ⊸ B | c . lab ; P | case c of { lab k → Q k } k ∈ I & { lab k : A k } k ∈ I , ⊕{ lab k : A k } k ∈ I Because a process P always provides a session along a unique channel, we sometimes identify aprocess with the channel along which it provides. Keeping this in mind, the intuitive readings of processexpressions are as follows. x ← P x ; Q x creates a fresh channel c , spawns a new process P c providingalong the channel c , and Q c uses this new channel. The forwarding process c ← d terminates by globallyidentifying channels c and d . Further communication along c will instead take place along d . A pos-sible implementation of a forwarding process might tell the two end-points to communicate with eachother and itself terminate, effectively, tying the two ends together and stepping out of the way. Processclose c sends the token end and terminates, whereas the matching wait c ; P waits for end along c andcontinues as P . Processes send and recv are used for communicating channels along channels. In thecase of send c ( y ← P y ) ; Q , a new channel d is created and a process P d is spawned, but unlike cut, thecontinuation ( Q ) cannot refer to the new channel d , since it is sent along c to be used by a differentprocess. Finally, c . lab ; P sends lab along c , and case c of { lab k → Q k } k ∈ I receives a label along c andbranches on it. These are used to determine which branches to take in internal and external choices. For practical programming, we of course need recursive types and recursively defined processes. Usually,this is incorporated into the type language in a local way by introducing a new construct m t . A t andidentifying m t . A with its unfolding [ m t . A / t ] A in the style of Amadio and Cardelli [2]. This makes it harderto incorporate mutual recursion, however, requiring type level pairs [21] for a fully formal treatment. Wetherefore go with the much simpler approach of using a global signature h of mutually recursive typedefinitions and process definitions . Type definitions are straightforward with the form t = A . They add.Acay &F.Pfenning 7defined type names as a new alternative to possible types. The fact that type definitions are transparent,that is, the fact that they are identified with their definition (or unfolding) without process-level termsto witness the isomorphism, corresponds to an equi-recursive interpretation of types. Process definitionshave the form X :: ( c : A ) = P c where P provides session A along c . h :: = · | h , t = A | X :: ( c : A ) = P c Note that c is a bound variable with scope P . Formally, our judgments are now decorated with a fixedsignature h , but we might elide it since the signature usually does not change during a derivation.The identification of defined type names and their unfoldings is normally formalized by defining anew type equivalence judgment and adding conversion rules to process typing. In our formalization, wewill integrate this into the subtyping judgment, but we delay its discussion to section 2.4. For now, itsuffices to think of type definitions as finite representations of possibly infinite trees. For example, thedefinition t = t ⊗ t stands for the tree ( . . . ⊗ . . . ) ⊗ ( . . . ⊗ . . . ) . However, for this to make sense, we needto slightly restrict valid type definitions to those that are contractive [21, 13]. In our setting, this meansevery type definition must have a structural type at the top. For example, the previous example of t = t ⊗ t is contractive since its top level construct is ⊗ whereas t = t and t = u are not.As an example for signatures with recursion, consider processes producing a sequence of the label succ followed a single zero (i.e. Peano naturals). Nat = ⊕{ zero : , succ : Nat } z :: ( c : Nat ) = c . zero ; close c s :: ( c : Nat ⊸ Nat ) = d ← recv c ; c . succ ; c ← d The s process here receives a channel d representing a natural number, outputs one succ , and then behaveslike d . Effectively, this computes the successor. To double a natural number, we need a recursive processdefinition. double :: ( c : Nat ⊸ Nat ) = d ← recv c ; case d of zero → wait d ; c . zero ; close c succ → c . succ ; c . succ ; e ← double ; send e ( d ′ ← ( d ′ ← d )) ; c ← e The last line here implements the following sequence: e ← double cut: start a new process double which provides along the new channel e send e ( d ′ ← ( d ′ ← d )) essentially, send d along e to the new process, but we have to use a forward c ← e now forward e to c This is a frequent pattern, so we make two small improvements in the surface syntax: (1) we parameterizeprocess definitions with the channels that they provide and use, and (2) instead of creating a new processand then forwarding it, we directly implement the provider channel with a new call. Then the definitionbecomes the much more readable double : Nat ⊸ Nat c ← double d = case d of zero → wait d ; c . zero ; close c succ → c . succ ; c . succ ; c ← double d Intersections and Unions ofSession TypesIn an actual implementation, the new definition would be “desugared” to the previous one.
The typing rules for processes are derived from linear logic by decorating derivations with proof terms.The rules are given in fig. 1. Note that in ⊕ L and & R , we allow unused branches in case expressions.This makes width subtyping easier, which is discussed in section 2.4. In addition, the def rule implicitlyrenames the channel name in the signature to the one expected by the judgment.In our simple language, checking that a type is valid, ⊢ h A : type , just verifies that all type names in A are defined in h and that A is contractive. A signature h itself is checked with the rules below. Notethat we allow mutual recursion in the definitions which is witnessed by the fact that the signature h ispropagated identically everywhere. ⊢ h /0 ⊢ h h ′ ⊢ h A : type ⊢ h h ′ , t = A ⊢ h h ′ ⊢ h A : type /0 ⊢ h P c :: ( c : A ) ⊢ h h ′ , X :: ( c : A ) = P c c : A ⊢ d ← c :: ( d : A ) id Y ⊢ P c :: ( c : A ) Y ′ , c : A ⊢ Q c :: ( d : D ) Y , Y ′ ⊢ c ← P c ; Q c :: ( d : D ) cut /0 ⊢ close c :: ( c : ) R Y ⊢ P :: ( d : A ) Y , c : ⊢ wait c ; P :: ( d : A ) L Y ⊢ P d :: ( d : A ) Y ′ ⊢ Q :: ( c : B ) Y , Y ′ ⊢ send c ( d ← P d ) ; Q :: ( c : A ⊗ B ) ⊗ R Y , d : A , c : B ⊢ P d :: ( e : E ) Y , c : A ⊗ B ⊢ d ← recv c ; P d :: ( e : E ) ⊗ L i ∈ I Y ⊢ P :: ( c : A i ) Y ⊢ c . lab i ; P :: ( c : ⊕{ lab k : A k } k ∈ I ) ⊕ R I ⊆ J Y , c : A k ⊢ P k :: ( d : D ) for k ∈ I Y , c : ⊕{ lab k : A k } k ∈ I ⊢ case c of { lab k → P k } k ∈ J :: ( d : D ) ⊕ L Y , d : A ⊢ P d :: ( c : B ) Y ⊢ d ← recv c ; P d :: ( c : A ⊸ B ) ⊸ R Y ⊢ P d :: ( d : A ) Y ′ , c : B ⊢ Q :: ( e : E ) Y , Y ′ , c : A ⊸ B ⊢ send c ( d ← P d ) ; Q :: ( e : E ) ⊸ L J ⊆ I Y ⊢ P k :: ( c : A k ) for k ∈ J Y ⊢ case c of { lab k → P k } k ∈ I :: ( c : & { lab k : A k } k ∈ J ) & R i ∈ I Y , c : A i ⊢ P :: ( d : D ) Y , c : & { lab k : A k } k ∈ I ⊢ c . lab i ; P :: ( d : D ) & L X = P :: ( c : A ) ∈ h /0 ⊢ X :: ( d : A ) def Figure 1: Type assignment for process expressions
Gay and Hole [13] add coinductive subtyping (denoted A ≤ B in this paper) to their system in order toadmit width and depth subtyping for n -ary choices, which are standard for record-like and variant-like.Acay &F.Pfenning 9structures. In our system, subtyping also doubles as a convenient way of identifying a recursive type andits unfolding using the following rules: ( t = B ∈ h ) A ≤ h BA ≤ h t Def R ( t = A ∈ h ) A ≤ h Bt ≤ h B Def L Double lines here indicate that the rules should be interpreted coinductively as is common with theoriesusing equi-recursive types. We will not go into the details of Gay and Hole’s system since we will switchto a different relation in the next section anyway. Either way, we relate subtyping to process typing withsubsumption rules: Y ⊢ h P :: ( c : A ′ ) A ′ ≤ h A Y ⊢ h P :: ( c : A ) SubR Y , c : A ′ ⊢ h P :: ( d : B ) A ≤ h A ′ Y , c : A ⊢ h P :: ( d : B ) SubL
So far in the theory, we have only considered processes in isolation. In this section, we introduce processconfigurations in order to talk about the interactions between multiple processes. A process configura-tion, denoted by W , is simply a set of processes where each process is labelled with the channel alongwhich it provides. We use the notation proc c ( P ) for labelling the process P , and require all labels in aconfiguration to be distinct.With the above restriction, each process offers along a specific channel and each channel is offeredby a unique process. Since channels are linear resources in our system, they must be used by exactlyone process. In addition, we do not allow cyclic dependence, which imposes an implicit forest (set oftrees) structure on a process configuration where each node has one outgoing edge and any number ofincoming edges that correspond to channels the process uses. This observation suggests the typing rulesbelow, which mimic the structure of a multi-way tree. Note that the definition is well founded since thesize of the configuration gets strictly smaller. | = /0 :: /0 config | = W :: Y Y ⊢ P :: ( c : A ) | = W , proc c ( P ) :: ( c : A ) config | = W i :: ( c i : A i ) for i ∈ { , . . . , n } n > | = W , . . . , W n :: ( c : A , . . . , c n : A n ) config n A process configuration evolves over time when a process takes a step, either by spawning a new process( cut ), forwarding ( id ) or when two matching processes communicate. Our configurations are sets, soorder is not significant when we match the left-hand sides against the configuration W . When we requirea new name to be chosen, it must not already be offered by some process in the configuration. Theserules are an example of a substructural operational semantics [20], presented in the form of a multisetrewriting system [7].0 Intersections and Unions ofSession Types W , proc c ( c ← d ) −→ [ d / c ] WW , proc c ( x ← P x ; Q x ) −→ W , proc a ( P a ) , proc c ( Q a ) ( a fresh) W , proc c ( X ) −→ W , proc c ([ c / d ] P ) ( X = P :: ( d : A ) ∈ h ) W , proc c ( close c ) , proc e ( wait c ; P ) −→ W , proc e ( P ) W , proc c ( send c ( x ← P x ) ; Q ) , proc e ( x ← recv c ; R x ) −→ W , proc a ( P a ) , proc c ( Q ) , proc e ( R a ) ( a fresh) W , proc c ( c . lab i ; P ) , proc e ( case c of { lab k → Q k } k ∈ I ) −→ W , proc c ( P ) , proc e ( Q i ) ( i ∈ I ) W , proc c ( x ← recv c ; P x ) , proc d ( send c ( x ← Q x ) ; R ) −→ W , proc c ( P a ) , proc a ( Q a ) , proc d ( R ) ( a fresh) W , proc c ( case c of { lab k → P k } k ∈ I ) , proc e ( c . lab i ; Q ) −→ W , proc c ( P i ) , proc e ( Q ) ( i ∈ I )This concludes the discussion of the base system. In the next section, we introduce intersections,unions, and a multiple-conclusion subtyping relation which constitute our main contributions. Recall our definition of process-level naturals Nat. One can imagine cases where we would like to knowmore about the exact nature of the natural. For example, if we are using a natural to track the size of alist, we might want to ensure it is non-zero. Sometimes, it might be relevant to track whether we have aneven or an odd number. The system we have described so far turns out to be strong enough to describeall these refinements as illustrated below
Nat = ⊕{ zero : , succ : Nat } Pos = ⊕{ succ : Nat } Even = ⊕{ zero : , succ : Odd } Odd = ⊕{ succ : Even } Recall also the definitions z : Nat s : Nat ⊸ Nat double : Nat ⊸ Nat c ← z = c ← s d = c ← double d = c . zero ; close c c . succ ; c ← d case d of zero → wait d ; c . zero ; close c succ → c . succ ; c . succ ; c ← double d Intuitively, it is easy to see that Pos, Even, and Odd are all subtypes of Nat. We run into a problemwhen we try to implement the behavior described by these types, however. The s process, for example,satisfies many properties: Nat ⊸ Nat, Pos ⊸ Pos, Even ⊸ Odd, Odd ⊸ Even etc. Subtyping can beused to combine some of these (e.g. Nat ⊸ Pos for Nat ⊸ Nat and Pos ⊸ Pos) but it is not expressiveenough to combine all properties. An elegant solution is to add intersections to the type system..Acay &F.Pfenning 11
We denote the intersection of two types A and B as A ⊓ B . A process offers an intersection type if itsbehavior satisfies both types simultaneously. Using intersections, we can assign the programs introducedin section 2.1 types specifying all behavioral properties we care about: z : Nat ⊓ Evens : ( Nat ⊸ Nat ) ⊓ ( Even ⊸ Odd ) ⊓ ( Odd ⊸ Even ) double : ( Nat ⊸ Nat ) ⊓ ( Nat ⊸ Even ) Note that as is usual with intersections, multiple types are assigned to the same process . Put differently,we cannot use two different processes or specify two different behaviors to satisfy the different branchesof an intersection. This leads to the following typing rule: Y ⊢ h P :: ( c : A ) Y ⊢ h P :: ( c : B ) Y ⊢ h P :: ( c : A ⊓ B ) ⊓ R When we are using a channel on the left that offers an intersection of two types, we know it has tosatisfy both properties so we get to pick the one we want: Y , c : A ⊢ h P :: ( d : D ) Y , c : A ⊓ B ⊢ h P :: ( d : D ) ⊓ L Y , c : B ⊢ h P :: ( d : D ) Y , c : A ⊓ B ⊢ h P :: ( d : D ) ⊓ L It may seem as if the two left typing rules for intersection are somehow unnecessary: because oflinearity, only one of A or B can be selected in any given derivation. But process definitions are usedarbitrarily often, essentially spawning a new process along a new linear channel at each use point, so wemay need to select a different component of the type at each occurrence. For example: s : ( Even ⊸ Odd ) ⊓ ( Odd ⊸ Even ) (from before) s2 : Even ⊸ Even c ← s2 d = d ← s d (use s : Even ⊸ Odd by ⊓ L )c ← s d (use s : Odd ⊸ Even by ⊓ L ) The standard subtyping rules are given below. It should be noted that the left typing rules above arederivable by an application of subsumption on the left using ≤ ⊓ L and ≤ ⊓ L , so we will not explicitlyadd these to the final system. Also, we will have to modify the subtyping relation later in this section, sothese rules are only a first attempt. A ≤ B A ≤ B A ≤ B ⊓ B ≤ ⊓ R A ≤ BA ⊓ A ≤ B ≤ ⊓ L A ≤ BA ⊓ A ≤ B ≤ ⊓ L One final note about intersection types and recursion is that intersections are not considered structuraltypes and thus do not contribute to contractiveness. That is, the type t = t ⊓ t is not contractive.2 Intersections and Unions ofSession Types Unions are the dual of intersections and correspond to processes that satisfy one or the other property, andare written A ⊔ B . We add unions because they are a natural extension to a type system with intersections.We will also see how n -ary internal choice can be interpreted as the union of singleton choices. Withoutthem, our interpretation would only be half-complete since we could interpret external choice (withintersections) but not internal choice.Being dual to intersections, the typing rules for unions mirror the typing rules for intersections: wehave two right rules and one left rule, and this time the right rules are derivable from subtyping. Therules are given below: Y ⊢ h P :: ( c : A ) Y ⊢ h P :: ( c : A ⊔ B ) ⊔ R Y ⊢ h P :: ( c : B ) Y ⊢ h P :: ( c : A ⊔ B ) ⊔ R Y , c : A ⊢ h P :: ( d : D ) Y , c : B ⊢ h P :: ( d : D ) Y , c : A ⊔ B ⊢ h P :: ( d : D ) ⊔ L The right rules state the process has to offer either the left type or the right type respectively. The leftrule says we need to be prepared to handle either type. It is interesting to observe that the usual problemswith unions in functional languages do not arise in our setting. The natural left rule we give here (naturalsince it is dual to the right rule for intersection) has been shown to be unsound in functional languages[3]. One somewhat heavy solution limits the left rule to expressions in evaluation position [11]. Thestraightforward left rule turns out to be already sound here, essentially due to linearity and the use of thesequent calculus.The usual subtyping rules are given below. The ⊔ R rules are derivable by general subtyping, so theydon’t need to be explicitly added to the system. A ≤ B A ≤ B ⊔ B ≤ ⊔ R A ≤ B A ≤ B ⊔ B ≤ ⊔ R A ≤ B A ≤ BA ⊔ A ≤ B ≤ ⊔ L For an example where unions are the most natural way to express a property, consider moving to abinary representation of natural numbers. We define the type of binary string where the least significantbit is sent first and the string of bits is terminated with eps : Bits = ⊕{ eps : , zero : Bits , one : Bits } We can define bit strings in standard form (no leading zeros) as follows:
Std = Empty ⊔ StdPosEmpty = ⊕{ eps : } StdPos = ⊕{ one : Std , zero : StdPos } We are able to naturally express standard bit strings as either an empty bit string or a positive one;expressing such types without unions would be cumbersome at the very least. Now we can write an The acute reader might notice that
Std actually fails our simple contractiveness criteria. This does not lead to unsoundness,however, since its one level unfolding is contractive (i.e. inlining
Empty and
StdPos makes it contractive). We write it inclosed form here for better readability, but one can consider this simple syntactic sugar. It is not too hard to formulate a soundcontractiveness condition that allows such definitions, but we decided to err on the side of simplicity for this paper. .Acay &F.Pfenning 13increment function that preserves bit strings in standard form: inc : Std ⊸ Std ⊓ StdPos ⊸ StdPos ⊓ Empty ⊸ StdPos c ← inc d = case d of eps → wait d ; c . one ; c . eps ; close c zero → c . one ; c ← d one → c . zero ; inc d This example also demonstrates that for a recursively defined type we may need to specify more informa-tion than we ultimately care about, since checking this definition just against the type
Std ⊸ Std will fail,and we need to assign the more specific type for the type checking to go through. This is because of thenature of our system which essentially requires the type checker to verify a fixed point rather than inferthe least one. This has proven highly beneficial for providing good error messages even in the simplercase of pure subtyping, without intersections and unions [16].
In line with our propositional interpretation of intersections and unions, one would naturally expect theusual properties of these to hold in our system. For example, unions should distribute over intersectionsand vice versa, that is, the following equalities should be admissible: ( A ⊔ B ) ⊓ ( A ⊔ B ) ≡ ( A ⊓ A ) ⊔ B ( A ⊔ A ) ⊓ B ≡ ( A ⊓ B ) ⊔ ( A ⊓ B ) Going from right to left turns out to be easy, but we quickly run into a problem if we try to do theother direction: whether we break down the union on the right or the intersection on the left, we alwayslose half the information we need to carry out the rest of the proof. Our solution is doing the obvious: if the problem is losing half the information, well, we should justkeep it around. This suggests a system where the single type on the left and the type on the right arereplaced with (multi)sets of types. That is, instead of the judgment A ≤ B , we use a judgment of the form A , . . . , A n ⇒ B , . . . , B n , where the left of ⇒ is interpreted as a conjunction (intersection) and the right isinterpreted as a disjunction (union). This results in a system reminiscent of [14, 15]. However, we takea slightly different approach since we are working with coinductive rules.The rules are given in fig. 2. We use a and b to denote multisets of types. The intersection left rulesare combined into one rule that keeps both branches around. The same is done with union right rules.Intersection right and union left rules split into two derivations, one for each branch, but keep the rest ofthe types unchanged. We can unfold a recursive type on the left or on the right. When we choose to applya structural rule, we have to pick exactly one type on the left and one on the right with the same structure.We conjecture that matching multiple types might give us distributivity of intersection and union overstructural types, although a naive extension along these lines fails to satisfy type safety. This issue does not come up in the other direction since intersection right and union left rules are invertible, that is, theypreserve all information. We use multisets rather than sets since types have nontrivial equality, so it is not obvious when we should combine theminto one. a ⇒ b , A a ⇒ b , A a ⇒ b , A ⊓ A ⇒ ⊓ R a , A , A ⇒ ba , A ⊓ A ⇒ b ⇒ ⊓ L a ⇒ b , A , A a ⇒ b , A ⊔ A ⇒ ⊔ R a , A ⇒ b a , A ⇒ ba , A ⊔ A ⇒ b ⇒ ⊔ L a , ⇒ b , ⇒ A ⇒ A ′ B ⇒ B ′ a , A ⊗ B ⇒ b , A ′ ⊗ B ′ ⇒ ⊗ I ⊆ J A k ⇒ A ′ k for k ∈ I a , ⊕{ lab k : A k } k ∈ I ⇒ b , ⊕{ lab k : A ′ k } k ∈ J ⇒ ⊕ A ′ ⇒ A B ⇒ B ′ a , A ⊸ B ⇒ b , A ′ ⊸ B ′ ⇒ ⊸ J ⊆ I A k ⇒ A ′ k for k ∈ J a , & { lab k : A k } k ∈ I ⇒ b , & { lab k : A ′ k } k ∈ J ⇒ & ( t = A ∈ h ) a ⇒ b , A a ⇒ b , t ⇒ Def R ( t = A ∈ h ) a , A ⇒ ba , t ⇒ b ⇒ Def L Figure 2: Subtyping with multiple hypothesis and conclusions; coinductively with respect to a fixedsignature h In this section, we show that that intersections and unions are useful beyond their refinement interpre-tation, and help us understand external and internal choices better. Take external choice, for instance.A comparison between the typing rules for intersections and external choice reveal striking similarities.The only difference, in fact, is that internal choice has process-level constructs whereas intersections areimplicit.Consider the special case of binary external choice: & { inl : A , inr : B } . This type says: I will act as A if you send me inl and I will act as B if you send me inr . We know the and can be interpreted as anintersection, and either side can be thought of as a singleton internal choice. A similar argument canbe given for internal choice and unions. This gives us the following redefinitions of n -ary external andinternal choices: & { lab k : A k } k ∈ I , l k ∈ I & { lab k : A k }⊕ { lab k : A k } k ∈ I , G k ∈ I ⊕{ lab k : A k } It is a straightforward calculation that these definitions satisfy the typing and subtyping rules for externaland internal choices.
In this section, we show that subtyping and type-checking are decidable by designing an algorithm thattakes in a (sub)typing judgment and produces true if and only if there is a derivation. Note that everythingin the judgment is considered an input..Acay &F.Pfenning 15
The subtyping judgment we gave is already mostly algorithmic (a necessity of working with coinductiverules), so we only have to tie up a few loose ends. The first is deciding which rule to pick when multipleare applicable. We apply ⇒ ⊓ R , ⇒ ⊓ L , ⇒ ⊔ R , ⇒ ⊔ L , ⇒ Def R , ⇒ Def L eagerly since these areinvertible. At some point, all types must be structural (since definitions are restricted to be contractive),at which point we non-deterministically pick a structural rule and continue. In the implementation, webacktrack over these choices.Second, the coinductive nature of subtyping means we can (and often will) have infinite derivations.We combat this by using a cyclicity check (similar to the one in [13]): we maintain a context of previouslyseen subtyping comparisons and immediately terminate with success if we ever compare the same pair ofsets of types again. Every recursive step corresponds to a rule, which ensures a productive derivation. Weknow there cannot be an infinite chain of new types due to the contractiveness restriction which impliesan upper-bound on the size of the previously-seen set. A more formal treatment can be found in [21]. Designing a type checking algorithm is quite simple for the base system where we only have structuraltypes (no recursive types or subtyping), since the form of the process determines a unique applicabletyping rule. The cut rule causes a small problem since we do not have a type for the new channel. Thisis solved by requiring a type annotation when necessary such that the new term becomes c : A ← P c ; Q c .The overwhelmingly common case where it is not necessary is when P c is a defined process name X because we simply fall back on its given type.In the extended system with subtyping and property types, type-checking is trickier for two reasons:(1) subsumption can be applied anytime where one of the types in A ≤ B can be anything (the other willbe fixed due to typing rules, but one causes enough damage), and (2) intersection left and union rightrules lose information which means they have to be applied non-deterministically. The latter issue isresolved by switching to a judgment where each channel (whether on the left or the right) is assigneda multiset of types. These multisets are interpreted conjunctively for channels used (on the left) anddisjunctively for the channel provided (on the right). This makes intersection left and union right rulesinvertible, so they can be applied eagerly.The former problem is solved by checking subtyping only at the identity rule (forwarding). Thisrelies on the subformula property for the sequent calculus, excepting only the cut rule which is annotated.The new judgment is written Y (cid:13) h P :: ( c : a ) , where Y and a are multisets. Typing rules are givenin fig. 3. Note the explicit ⊓ L , ⊔ R , Def L , and Def R . These rules were derivable in the declarativesystem using subsumption, which is no longer possible since application of subsumption is restricted toforwarding processes. Next, we show that the algorithmic system is sound and complete with respect to the declarative system(modulo erasure of type annotations, which we denote by J P K ). Due to space limitations, we can only givevery brief proof sketches here. Interested readers are referred to the first author’s thesis [1]. We define F a as the union of all the types in a , and similarly for d a . For contexts we define d ( c : a , . . . , c n : a n ) = c : d a , . . . , c n : d a n . Theorem 4.1 (Soundness of Algorithmic Typing) . If Y (cid:13) h P :: ( c : a ) , then d Y ⊢ h J P K :: ( c : F a ) . Y (cid:13) h P :: ( c : A , a ) Y (cid:13) h P :: ( c : B , a ) Y (cid:13) h P :: ( c : A ⊓ B , a ) ⊓ R Y , c : ( a , A , B ) (cid:13) h P :: ( d : b ) Y , c : ( a , A ⊓ B ) (cid:13) h P :: ( d : b ) ⊓ L Y (cid:13) h P :: ( c : A , B , a ) Y (cid:13) h P :: ( c : A ⊔ B , a ) ⊔ R Y , c : ( a , A ) (cid:13) h P :: ( d : b ) Y , c : ( a , B ) (cid:13) h P :: ( d : b ) Y , c : ( a , A ⊔ B ) (cid:13) h P :: ( d : b ) ⊔ L ( t = A ∈ h ) Y (cid:13) h P :: ( c : A , a ) Y (cid:13) h P :: ( c : t , a ) Def R ( t = A ∈ h ) Y , c : ( a , A ) (cid:13) h P :: ( d : b ) Y , c : ( a , t ) (cid:13) h P :: ( d : b ) Def L a ⇒ b c : a (cid:13) h d ← c :: ( d : b ) id Y (cid:13) h P c :: ( c : A ) Y ′ , c : A (cid:13) h Q c :: ( d : a ) Y , Y ′ (cid:13) h c : A ← P c ; Q c :: ( d : a ) cut /0 (cid:13) h close c :: ( c : , a ) R Y (cid:13) h P :: ( d : b ) Y , c : ( a , ) (cid:13) h wait c ; P :: ( d : b ) L Y (cid:13) h P :: ( d : A ) Y ′ (cid:13) h Q :: ( c : B ) Y , Y ′ (cid:13) h send c ( d ← P d ) ; Q :: ( c : A ⊗ B , a ) ⊗ R Y , d : A , c : B (cid:13) h P d :: ( e : b ) Y , c : ( a , A ⊗ B ) (cid:13) h d ← recv c ; P d :: ( e : b ) ⊗ L i ∈ I Y (cid:13) h P :: ( c : A i ) Y (cid:13) h c . lab i ; P :: ( c : ⊕{ lab k : A k } k ∈ I , a ) ⊕ R I ⊆ J Y , c : A k (cid:13) h P k :: ( d : b ) for k ∈ I Y , c : ( a , ⊕{ lab k : A k } k ∈ I ) (cid:13) h case c of { lab k → P k } k ∈ J :: ( d : b ) ⊕ L Y , d : A (cid:13) h P d :: ( c : B ) Y (cid:13) h d ← recv c ; P d :: ( c : A ⊸ B , a ) ⊸ R Y (cid:13) h P d :: ( d : A ) Y ′ , c : B (cid:13) h Q :: ( e : b ) Y , Y ′ , c : ( a , A ⊸ B ) (cid:13) h send c ( d ← P d ) ; Q :: ( e : b ) ⊸ L J ⊆ I Y (cid:13) h P k :: ( c : A k ) for k ∈ J Y (cid:13) h case c of { lab k → P k } k ∈ I :: ( c : & { lab k : A k } k ∈ J , a ) & R i ∈ I Y , c : A i (cid:13) h P :: ( d : b ) Y , c : ( a , & { lab k : A k } k ∈ I ) (cid:13) h c . lab i ; P :: ( d : b ) & L X = P :: ( c : A ) ∈ hY (cid:13) h /0 :: ( X : d ) A def Figure 3: Process Typing in the Algorithmic System
Proof.
By induction on the typing derivation. The only non-straightforward cases are ⊓ R and ⊔ L , whichdepend on the distributivity of intersection and union over each other (which is one of the reasons whywe insisted such be the case while designing the subtyping relation). Lemma 4.2 (Completeness of Delayed Subtyping) . The following are admissible: • If Y (cid:13) h P :: ( c : a ) and F a ⇒ b then Y (cid:13) h P :: ( c : b ) . .Acay &F.Pfenning 17 • If Y , d : a (cid:13) h P :: ( c : b ) and a ′ ⇒ d a then Y , d : a ′ (cid:13) h P :: ( c : b ) .Note that the type annotations in P stay the same.Proof. By lexicographic induction, first on the structure of P , then on the combined sizes of involvedtypes. Theorem 4.3 (Completeness of Algorithmic Typing) . If Y ⊢ h P :: ( c : A ) , then there exists P ′ such that J P ′ K = P and Y (cid:13) h P ′ :: ( c : A ) .Proof. By induction on the typing derivation, using lemma 4.2 for
SubR and
SubL . Our main contribution is proving type safety for the system with intersections and unions, which wedo so by showing the standard progress and preservation theorems, renamed to deadlock freedom andsession fidelity, respectively, within this context. Since the algorithmic system is more well behaved(no subsumption), we use the algorithmic judgment in the statements and proofs of these results. Typesafety for the declarative system follows from its equivalence to the algorithmic system. We only statethe theorems here. Full proofs can be found in [1].In a functional setting, progress states a well-typed expression either takes a step or is a value. Thecorresponding notion of a value is a poised configuration. A configuration is poised if every process init is, and a process is poised if it is waiting to communicate with its client. With this definition, we canstate the progress theorem:
Theorem 5.1 (Progress) . If | = W :: Y then either1. W −→ W ′ for some W ′ , or2. W is poised.Proof. By induction on | = W :: Y followed by a nested induction on the typing of the root process for the config case. When two processes are involved, we also need inversion on client’s typing. Theorem 5.2 (Preservation) . If | = W :: Y and W −→ W ′ then | = W ′ :: Y .Proof. By inversion on W −→ W ′ , followed by induction on the typing judgments of the involved pro-cesses. Padovani describes a calculus similar to ours [18] where he interprets internal and external choices asunion and intersection, respectively. This resembles what we did in section 3.4 except we keep singletonchoices at the type and term levels to maintain the connection to linear logic, whereas Padovani is ableto remove them completely since his calculus is based on CSS [8]. While we give axiomatic rules for(sub)typing, he takes a semantic approach, which we believe is complementary to our work. However,semantic definitions make deriving algorithmic rules harder and he leaves this as future work. Moresignificantly, Padovani does not consider higher-order types and processes, which means it is not possibleto communicate channels along channels. Moreover, his calculus only deals with the interaction betweentwo processes that are required to have matching (or dual) types and behaviors (for example, if one sends,8 Intersections and Unions ofSession Typesthe other must receive etc.). We consider a tree of processes where each process can use many providers(as long as it respect the behavior along their channels) and even spawn new ones. For example, a clientusing two providers could communicate with one of them while the other is idle, or ignore both altogetherand only communicate with its client.Castagna et al. describe a generic framework [6] that make use of set operations (intersection, union,and negation) for sessions and take a semantic approach as well. Their framework has the advantage thatit is agnostic to the underlying functional language. There are descriptions of our base calculus that take asimilar approach [22] and it should not be too hard to extend them to cover our contributions. Contrary toPadovani, Castagna et al. have higher order sessions and give algorithms to decide all semantic relationsthey describe. However, their system and presentation are significantly different from ours becauseof their semantic emphasis, inclusion of negation (which makes their session language Boolean), andtreatment of process composition (which is closer to Padovani’s). In particular, they do not have ageneral primitive for spawning new processes or forwarding.We introduced intersections and unions to a simple system of session types, and demonstrated howthey can be used to refine behavioral specifications of processes. Some aspects that would be importantin a full accounting of the system are omitted for the sake of brevity or are left as future work. For exam-ple, integrating an underlying functional language [22], adding shared channels [5, 19], or consideringasynchronous communication [9, 19, 16] are straightforward extensions based on prior work. In addition,it would be very useful to have behavioral polymorphism [4] and abstract types. Their interaction withsubtyping, intersections, and unions is an interesting avenue for future work.
Acknowledgments.
This work was funded in part by NSF grant CNS1423168 and by the FCT (Por-tuguese Foundation for Science and Technology) through the Carnegie Mellon Portugal Program. Wewould like to thank the anonymous referees for their many helpful suggestions.
References [1] Cos¸ku Acay (2016):
Refinements for Session Typed Concurrency . Undergraduate honors thesis, CarnegieMellon University. Available at .[2] Roberto M. Amadio & Luca Cardelli (1991):
Subtyping Recursive Types . In: POPL, ACM Press, pp. 104–118, doi:10.1145/99583.99600.[3] Franco Barbanera, Mariangiola Dezani-Ciancaglini & Ugo de’Liguoro (1995):
Intersection and Union Types:Syntax and Semantics . Inf.Comput. 119(2), pp. 202–230, doi:10.1006/inco.1995.1086.[4] Lu´ıs Caires, Jorge A. P´erez, Frank Pfenning & Bernardo Toninho (2013):
Behavioral Polymorphism andParametricity in Session-Based Communication . In: ESOP, Lecture Notes in Computer Science 7792,Springer, pp. 330–349, doi:10.1007/978-3-642-37036-6 19.[5] Lu´ıs Caires & Frank Pfenning (2010):
Session Types as Intuitionistic Linear Propositions . In: CONCUR,LectureNotesinComputerScience 6269, Springer, pp. 222–236, doi:10.1007/978-3-642-15375-4 16.[6] Giuseppe Castagna, Mariangiola Dezani-Ciancaglini, Elena Giachino & Luca Padovani (2009):
Foundationsof session types . In: PPDP, ACM, pp. 219–230, doi:10.1145/1599410.1599437.[7] Iliano Cervesato & Andre Scedrov (2009):
Relating state-based and process-based concurrency throughlinear logic (full-version) . Inf.Comput. 207(10), pp. 1044–1077, doi:10.1016/j.ic.2008.11.006.[8] Rocco De Nicola & Matthew Hennessy (1987):
CCS without tau’s . In: TAPSOFT, Vol.1, Lecture Notes inComputerScience 249, Springer, pp. 138–152, doi:10.1007/3-540-17660-8 53. .Acay &F.Pfenning 19 [9] Henry DeYoung, Lu´ıs Caires, Frank Pfenning & Bernardo Toninho (2012):
Cut Reduction in Linear Logicas Asynchronous Session-Typed Communication . In: CSL, LIPIcs 16, Schloss Dagstuhl - Leibniz-Zentrumfuer Informatik, pp. 228–242, doi:10.4230/LIPIcs.CSL.2012.228.[10] Joshua Dunfield & Frank Pfenning (2003):
Type Assignment for Intersections and Unions in Call-by-Value Languages . In: FoSSaCS, Lecture Notes in Computer Science 2620, Springer, pp. 250–266,doi:10.1007/3-540-36576-1 16.[11] Joshua Dunfield & Frank Pfenning (2004):
Tridirectional typechecking . In: POPL, ACM, pp. 281–292,doi:10.1145/964001.964025.[12] Timothy S. Freeman & Frank Pfenning (1991):
Refinement Types for ML . In: PLDI, ACM, pp. 268–277,doi:10.1145/113445.113468.[13] Simon J. Gay & Malcolm Hole (2005):
Subtyping for session types in the pi calculus . ActaInf. 42(2-3), pp.191–225, doi:10.1007/s00236-005-0177-z.[14] Gerhard Gentzen (1935):
Untersuchungen ¨uber das Logische Schließen . Mathematische Zeitschrift 39, pp.176–210, 405–431, doi:10.1007/BF01201353. English translation in M. E. Szabo, editor,
The CollectedPapers of Gerhard Gentzen , pages 68–131, North-Holland, 1969.[15] Jean-Yves Girard (1987):
Linear Logic . Theor. Comput. Sci. 50, pp. 1–102,doi:10.1016/0304-3975(87)90045-4.[16] Dennis Griffith (2016):
Polarized Substructural Session Types . Ph.D. thesis, University of Illinois at Urbana-Champaign. In preparation.[17] Kohei Honda (1993):
Types for Dyadic Interaction . In: CONCUR, LectureNotesinComputerScience 715,Springer, pp. 509–523, doi:10.1007/3-540-57208-2 35.[18] Luca Padovani (2010):
Session Types = Intersection Types + Union Types . In: ITRS, EPTCS 45, pp. 71–89,doi:10.4204/EPTCS.45.6.[19] Frank Pfenning & Dennis Griffith (2015):
Polarized Substructural Session Types . In: FoSSaCS, LectureNotesinComputerScience 9034, Springer, pp. 3–22, doi:10.1007/978-3-662-46678-0 1.[20] Robert J. Simmons (2012):
Substructural Logical Specifications . Ph.D. thesis, Carnegie Mellon University.[21] Christopher A. Stone & Andrew P. Schoonmaker (2005):
Equational Theories with Recursive Types . Unpub-lished Manuscript.[22] Bernardo Toninho, Lu´ıs Caires & Frank Pfenning (2013):