Session-ocaml: a Session-based Library with Polarities and Lenses

. We propose session-ocaml , a novel library for session-typed concurrent/distributed programming in OCaml. Our technique solely relies on parametric polymorphism, which can encode core session type structures with strong static guarantees. Our key ideas are: (1) polarised session types , which give an alternative formulation of duality enabling OCaml to automatically infer an appropriate session type in a session with a reasonable notational overhead; and (2) a parameterised monad with a data structure called ‘ slots ’ manipulated with lense s, which can statically enforce session linearity and delegations. We show applications of session-ocaml including a travel agency usecase and an SMTP protocol.


Introduction
Session types [ ], from their origins in the -calculus [ ], serve as rigorous specifications for coordinating link mobility in the sense that a communication link can move among participants, while ensuring type safety.In session type systems such mobility is called delegation.Once the ownership of a session is delegated (transferred) to another participant, it cannot be used anymore at the sender side.This property is called linearity of sessions and appears indispensable for all session type systems.
Linearity of session channels, however, is a major obstacle to adopt session type disciplines in mainstream languages, as it requires special syntax extensions for session communications [ ], or depends on specific language features, such as type-level functions in Haskell [ , , , ], and affine types in Rust [ ], or even falling back on run-time and dynamic checking [ , , , ].For instance, a common way in Haskell implementations is to track linear channels using an extra symbol table which denotes types of each resource conveyed by a parameterised monad.A Haskell type for a session-typed function is roughly of the form: where M is a monad type constructor of arity three,  is a result type and the two {• • •} are symbol tables before (and after) evaluation which assign each channel   to its session type   (and  ′  respectively).This symbol table is represented at the type level, hence the channel   is not a value, but a type which reflects an identity of a channel.Since this static encoding is Haskell-specific using type-level functions, it is not directly extendable to other languages.This paper proposes the session-ocaml library, which provides a fully static implementation of session types in OCaml without any extra mechanisms or tools (i.e.sessions are checked at compile-time).We extend the technique posted to the OCaml mailing list by Garrigue [ ] where linear usage of resources is enforced solely by the parametric polymorphism mechanism.According to [ ], the type of a file handle guarantees linear access to multiple resources using a symbol table in a monad-like structures.Adapting this technique to session types, in session-ocaml, multiple simultaneous sessions are statically encoded in a parameterised monad.More specifically, we extend the monad structure to a slot monad and the file handles to lenses.The slot monad is based on a type (, , ) monad (hereafter we use postfix type constructor of OCaml) where  and  are called slots which act like a symbol table.Slots are represented as a sequence of types represented by nested pair types  1 * ( 2 * • • •).Lenses [ ] are combinators that provide access to a particular element in nested tuples and are used to manipulate a symbol table in the slot monad.These mechanisms can provide an idiomatic way (i.e.code does not require interposing combinators to replace standard syntactic elements of functional languages) to declare session delegations and labelled session branching/selections with the static guarantee of type safety and linearity (unlike FuSe [ ] which combines static and dynamic checking for linearity, see § ).
To enable session-type inference solely by unification in OCaml, session-ocaml is equipped with polarised session types which give an alternative formulation of duality (binary relation over types which ensures reciprocal use of sessions).In a polarised session type (, ) sess, the polarity  is either serv (server) or cli (client).The usage of a session is prescribed in the protocol type  which provides an objective view of a communication based on a communication direction of req (request; client to server) and resp (response; server to client).For example, the protocol type for sending of a message type 'v from client to server is [`msg of req * 'v * 's] and the opposite is [`msg of resp * 'v * 's].Duality is not necessary for protocol types as it shows a protocol common to both ends of a session rather than biased by either end.Then the session type inference can be driven solely by type unification which checks whether a protocol matches its counterpart or not.For instance, the dual of (, cli) sess is (, serv) sess and vice versa.When a session is being initiated, polarities are assigned to each end of a session according to the primitives used, namely cli for the proactive peer and serv for the passive peer.The protocol types also provide a usual prefixing declaration of session types, which is more human-readable than FuSe types [ ] (see § ).
The rest of the paper is as follows.Section outlines programming with session-ocaml.Section shows the library design with the polarised session type and the slot monads.In Section , we present two examples, a travel agency usecase and SMTP protocol implementations.Section discusses comparisons with session type implementations in functional languages.Section concludes and discusses further application of our technique.

Programming with session-ocaml
In this section, we overview session-typed programming with session-ocaml and summarise communication primitives in the library.

Send and receive primitives
Listing shows a server and client which communicate boolean values.The module Session0 introduces functions of session-ocaml in the scope.xor _ ch (line ) is a service channel (or shared channel) that is used to start communication by a client connecting (connect _ ) to the server waiting (accept _ ) at it.The server (lines -) receives (recv) a pair of booleans, then calculates the exclusive-or of these values, transmits (send) back the resulting boolean, and finishes the session (close).These communication primitives communicate on an implicit session endpoint (or session channel) which is connected to the other endpoint.For inferring session types by OCaml, communication primitives are concatenated by the bind operations >> and >>= of a parameterised monad [ ] which conveys session endpoints.The syntax let%s pat = 1 in 2 binds the value returned by  1 to the pattern pat and executes  2 , which is shorthand for 1 >>= fun pat -> 2 (the % symbol indicates a syntax extension point in an OCaml program).The client (lines -) sends a pair of boolean, receives from the server and finishes the session, as prescribed in the following type.These server and client behaviours are captured by the protocol type argument of the channel type inferred at xor _ ch as follows: The protocol type is the primary language of communication specification in session-ocaml.Here, [`msg of  *  * ] is a protocol that represents communication of a message of type  before continuing to .  ∈ {req,resp} indicates a communication direction from client to server and vice versa, respectively.
[`close] is the end of a session.Thus the above type indicates that by a session established at xor _ ch, ( ) the server receives a request of type bool * bool and then ( ) sends a response of type bool back to the client.
The suffix 0 means that it only uses the slot (see later in this section).The suffixed underscore means that they run immediately instead of returning a monadic action (see later).

Listing
is the syntax for branching to the expression   after label lab  is received.Upon receipt of bin, the server receives requests for a logical operation from the client (type binop and bool * bool), sends back a response and returns to the branch (note that the server is recursively defined by let rec).In the case of fin, the session is terminated.[%select0 `] is a syntax to select one of branches with a label .A client using selection is shown in lines -: it selects the label bin, requests conjunction, and selects fin; then the session ends.
For the branching primitive on arbitrary labels, session-ocaml uses OCaml polymorphic variants and syntax extensions.By using equi-recursive types, recursive protocols are also directly encoded into OCaml types.
Link mobility with delegation Link mobility with session delegation enables one to describe a protocol where the communication counterpart dynamically changes during a session.A typical pattern utilising delegation incorporates a main thread accepting a connection and worker threads doing the actual work to increase responsiveness of a service.
Here the bracket is another form of a syntax extension point applied to an expression (see the OCaml manual).
Listing A highly responsive server using delegation (log _ ch is from Listing .)In session-ocaml, a program using delegation handles multiple sessions simultaneously.We explicitly assign each session endpoint to a slot using slot specifiers _ 0, _ 1, • • • which gives an idiomatic way to use linear channels.Listing shows an example of a highly responsive server using delegation.The server receives repeated connection requests on channel log _ ch, consisting of the main thread and six worker threads.The module SessionN provides slot specifiers and accompanying communication primitives, where the suffix N means that it can handle on arbitrary number of sessions.The main thread (lines -) accepts a connection from a client (accept) with log _ ch and assigns the established session to slot (~bindto: _ 0).Next, it connects (connect) to a worker waiting for delegation at channel worker _ ch (line ) and assigns the session to slot (~bindto: _ 1).Finally it delegates the session with the client to the worker (deleg _ send), then ends the session with the worker and accepts the next connection.The worker thread (lines -) receives the delegated session from the main thread (deleg _ recv) and assigns the session to slot , then continues to logic _ server (Listing ).Here, Session0 module used by logic _ server implicitly allocates the session type to slot , hence can be used with SessionN module.Line starts the main thread and workers.Here run is a function that executes session-ocaml threads.
The protocol type of worker _ ch is inferred as follows: [`deleg of req * (logic _ p, serv) sess * [`close]] Here logic _ p is the protocol type of log _ ch and [`deleg of  *  * ] is the delegation type. is a communication direction,  is a polarised session type (a type with protocol and polarity which we explain next) for the delegated session and  is a continuation.By inferring the protocol types, session-ocaml can statically guarantee safety of higher-order protocols including delegations.
The polarised session types Communication safety is checked by matching each protocol type inferred at both ends.The polarised session type (, ) sess given to each endpoint plays a key role for protocol type inference.Here  is a protocol type, and  ∈ {serv,cli} is the polarity determined at session initiation.serv is assigned to the accept side and cli to the connect side.serv and cli are dual to each other.
~arg: is a labelled argument  for a named parameter arg.
The polarised session type gives a simple way to let the type checker infer a uniform protocol type according to a communication direction and a polarity assigned to the endpoint.For example, as we have seen, we deduce resp (response) from server transmission (send) and client reception (recv).Table shows correspondences between polarities and communication directions.Here the type (, , ) session specifies that it expects slot sequence  at the beginning, and returns another slot sequence  and a value of type .The type empty * (empty * 'ss) denotes that slot and are empty at the beginning, and since they never return the answer (i.e. the recursion runs infinitely), the rest of types 'tt and 'a are left as variables.
The type of logic _ server in Listing has a session type: ((logic _ p, serv) sess * 'ss, empty * 'ss, unit) session Here logic _ server expects a session assigned at slot before it is called, hence it expects the session type (logic _ p, serv)sess in its pre-type.A difference from  main and worker above is that since each of them establishes or receives sessions by their own (by using accept, connect or deleg _ recv), they expect that slots and are empty.
Table shows the type and communication behaviour before and after the execution of each session-ocaml communication primitive.Each row has a pretype (the type required before execution) and post-type (the type guaranteed after execution).The protocol type at serv is obtained by replacing req with resp and resp with req.For example, the session send _   has pre-type ([`msg of req *  * ], cli) sess at cli and ([`msg of resp *  * ], serv) sess at serv where _  is a slot specifier,  is an expression,  is a value type and  is a protocol type.Selection

Design and implementation of session-ocaml
In this section, we first show the design of polarised session types associated with communication primitives ( § .); then introduce the slot monad which conveys multiple session endpoints in a sequence of slots and constructs the whole session type for a session ( § .).In § ., we introduce the slot specifier to look up a particular slot in a slot sequence with lenses which are a polymorphic data manipulation technique known in functional programming languages.We present the syntax extension for branching and selection, and explain a restriction on the polarised session types.This section mainly explains the type signatures of the communication primitives.Implementation of the communication behaviours is left to [ ]. .

Polarity polymorphism
The polarity polymorphism is accompanied within all session primitives in that the appropriate direction type is assigned according to the polarity.This resolves a trade-off of having two polarised session types for one transmission.For instance, a transmission of a value could have two candidates, [`msg of req * 'v * 's] and [`msg of resp * 'v * 's] but they are chosen according to the polarity from which the message is sent.In order to relate the polarities to the directions, cli and serv are defined by type aliases as follows: type cli = req * resp type serv = resp * req For each communication primitive, we introduce fresh type variables  req and  resp representing the communication direction, and put  req *  resp as the polarity in its session type.When its polarity is cli, we put  req for req and  resp for resp, while when it is serv, we put  req for resp and  resp for req.For example, the pre-type of send is ([`msg of 'r1 * 'v * 'p],'r1 * 'r2) sess and that of recv is ([`msg of ' r2 * 'v * 'p],'r1 * 'r2) sess.The same discipline applies to branching and delegation.
The actual typing is deferred to the following subsections. .

The slot monad carrying multiple sessions
The key factor to achieve linearity is to keep session endpoints securely inside a monad.In session-ocaml, multiple sessions are conveyed in slots using the slot monad of type which denotes a computation of a value of type , turning each pre-type   of slot  to post-type   .We refer to slots before and after computation as preand post-slots, respectively.The type signature of the slot monad is shown in Listing .The operators >>= and >> (lines -) compose computation sequentially while propagating type changes on each slot by demanding the same type 'q in the post-slots on the left-hand side and the pre-slots on the right-hand side.
Usually they construct compound session types via unification.For example, in send And >> send (true, false) (from Listing ) the left hand side (send Add) has the following type: Listing The slot monad type ('p,'q,'a) session and empty and all _ empty = empty * 'a as 'a val return : 'a -> ('p,'p,'a) session val (>>=) : ('p,'q,'a) session -> ('a -> ('q,'r,'b) session) -> ('p,'r,'b) session val (>>) : ('p,'q,'a) session -> ('q,'r,'b) session -> ('p,'r,'b) session val run : (all _ empty,all _ empty,unit) session -> unit  In line , run executes the slot monad and requires all slots being empty before and after execution, thus it precludes use of unallocated slots, and mandates that all sessions are finally closed (which corresponds to the absence of contraction in linear type systems).The type all _ empty (line ) is a type alias for OCaml equi-recursive type empty * 'a as 'a, enabling use of arbitrarily many slots. .

Lenses focusing on linear channels
In order to provide access to session endpoints conveyed inside a slot monad, we apply lenses [ ] to to slot specifiers _ 0, _ 1, • • • which are combinators to manipulate a polymorphic data structure.The following shows the type of a slot specifier which modifies slot  of a slot sequence: The type says that it replaces the type 'a of slot  in the slot sequence 's0 with 'b and the resulting sequence type becomes to Listing exhibits type signatures of accept, connect, close, send, recv, deleg _ send and deleg _ recv which are compiled from lenses, the polarised session types ( § .), In order to have such a type, we compile the code with the -rectypes option.If we chose types for slots using objects or polymorphic variants, there is no need to use this option.slot monads ( § .), and pre-and post-types in Table ( § ).Note that bindto: and release: are named parameters of a primitive.

Listing Signatures for communication primitives in
accept and connect (lines -) assign a new session channel to the empty slot, whereas close (lines -) finishes the session and leave the slot empty again.send and recv (lines -) proceed the protocol type by removing a `msg prefix.
deleg _ send and deleg _ recv (lines -) update a pair of slots; one is for the transmission/reception and the other is for the delegated session.To update the slots twice, they take a pair of slot specifiers which share an intermediate slot sequence 'mid.They embody an aspect of linearity: deleg _ send releases the ownership of the delegated session by replacing the slot type to empty, while deleg _ recv allocates another empty slot to the acquired session.
The primitives for binary selection select _ left, select _ right and branching branch2 (lines -) communicate left and right labels.branch2 takes a pair of continuations as well as a pair of slot specifiers.According to the received label, one of the continuations is invoked after the pre-type of the invoked continuation is assigned to the corresponding slot.
Finally, we present how to embed slot type changes into a pair of slot sequences in a slot monad where the position of the slot is specified by applying a slot specifier.In each type signature, the first and second type arguments of type slot prescribes how a slot type changes.The third and fourth arguments do not specify a slot in the slot sequence conveyed by the slot monad.For example, the type of function application close _ 1 is given by the following type substitution: (change of the slot type specified by close) 'a ↦ → ([`close],'r1 * 'r2) sess, 'b ↦ → empty, (change of the slot sequence type specified by _ 1) 'pre ↦ → 's0 * ([`close],'r1 * 'r2) sess * 'ss, 'post ↦ → 's0 * (empty * 'ss) And the type completing the session at slot is: Recall that connect yields a cli endpoint while accept gives a serv.Due to the different polarities in the delegated session types, the types of then and else clause conflict with each other, even if they have the identical behaviour.In [ ], where polarity is not a type but a syntactic construct, such a restriction does not exist.
A similar restriction exists in GV [ ] which has polarity in end (end ! and end ?).In principle, it is possible to automatically assign numbers to slot specifiers locally in a function instead of writing them explicitly.However, since sequential composition of the session monad requires each post-and pre-type to match with each other, the global assignment of slot specifiers would require a considerable amount of work and can be hard to predict its behaviour.As shown in Listing , one can handle two sessions by just using two slot specifiers.

Syntax extension for arbitrarily labelled branch
Since the OCaml type system does not allow to parameterise type labels (polymorphic variants), we provide macros for arbitrarily-labelled branching.Listing provides helper functions for the macros.For selection, the macro [%select _  `labi ] is expanded to _ select _  (fun x -> `labi (x)), where the helper function _ select transmits label lab i on the slot .
The helper functions _ branch _ start and _ branch have the type shown in Listing .
The anonymous function will have type where  is the polarity and   is the protocol type in the pre-type at slot  in   .When a label lab ( ∈ {1 . . .}) is received, _ branch _ start _   passes a pair of witness `lab(p) and q of a polarised session type (p, q) sess to the function  .The anonymous function extracts the witness and by _ branch it rebuilds the session type ('p,'q) sess and passes the session to the continuation   as the Listing The helper functions for branching/selection with arbitrary labels

Travel agency
We demonstrate programming in session-ocaml using the Travel agency scenario from [ ], which consists of typical patterns found in business and financial protocols.The scenario is played by three participants: customer, agency and service (Listing ).customer and service initially do not know each other, and agency mediates a deal between them by session delegation.
customer begins an order session with agency and binds it to their own slot (each process has a separate slot sequence).Then customer requests and receives the price for the desired journey after sending the quote label.In our scenario, customer requests "London to Paris" and agency replies with a fixed price 80.0.
Then customer might send the agree label to proceed the transaction with the current price.Or if customer does not agree with the price, customer can cancel the transaction by sending the reject label.Or, customer can send quote again and this will be repeated an arbitrary number of times for different journeys (we omit this branch from the code).In our program, customer agrees with agency at a price less than 100.0, or otherwise rejects it and terminates the transaction.
Next, if customer agrees with the price, agency opens the session with service and binds it to slot .Then it delegates to service, through slot , the interactions with customer remaining for slot .customer then sends the billing address (unaware that he/she is now talking to service), and service replies with the dispatch date (now()) for the purchased tickets.The transaction is complete.
The protocol type between customer and agency is inferred as: The delegated type is polymorphic on the polarity and communication directions ( § .), hence the service can handle both polarities.It reflects the part after agree in the protocol above where 'r1 is req and 'r2 is resp.Thus delegation with the polarised session types and slots effectively gives a way to coordinate higher order communication incurred by link mobility.Static checking of delegation makes it easier to find errors otherwise hard to analyse due to the indirect nature of delegation.Consider a case that service changes its behaviour to receive addr * paymeth.Now the inferred protocol type at service would be: Whereas that of agency remains same as before, it results in a type error at the moment when a service channel is passed.Without static typing, the run-time error would be deferred until the beginning of actual client-service communication.

. An SMTP protocol
This section shows an SMTP client implementation by session-ocaml.Listing and Listing show the protocol type of SMTP and message types representing SMTP commands and replies; and Listing shows the client implementation.Line in Listing generates a service channel for connecting to the SMTP server.Here smtp _ adapter is an adapter that converts a sequence of session messages to a Listing The protocol type of SMTP TCP stream.Its definition is shown in Listing and built using the combinators shown in Listing .The functions req and resp accept a function to convert between a message of type 'v and a command string and construct an adapter.bra and sel are branching and selection respectively, and cls is the end of the session.
The function with the same name as the message type is a function for converting to a string (or vice versa) and is responsible for actual stream processing.In OCaml, f @@ g means function composition fun x -> f (g x), and begin  end means ().Since OCaml evaluates eagerly, each function is -expanded with a parameter ch so that it does not recurse infinitely.The adapter for branch bra is asymmetric in its parameters [ ]. bra has a parser of type string -> 'v option on the left side since the adapter determines a continuation in a branch according to the parsed result of a received string.The adapter chooses left if the parser succeeds (returns Some(x)), and right if it fails (None).By nesting bra, any nesting of branch can be constructed.
Comparing to the existing Haskell implementation in [ ], an advantage is that our OCaml version enjoys equi-recursive session types, so we avoid the manual annotation of repeated unwind operations needed to unfold iso-recursive

Listing
The TCP adapter for a SMTP client let rec smtp _ adapter ch = (resp r200 @@ req ehlo @@ resp r200 @@ ml _ p) ch and ml _ p ch = sel ~left:(req mail @@ resp r200 @@ rp _ p) ~right:(req quit @@ cls) ch and rp _ p ch = sel ~left:(req rcpt @@ bra ~left:(r200, rp _ p) ~right:(resp r500 @@ req quit @@ cls)) ~right:bd _ p ch and bd _ p ch = (req data @@ resp r354 @@ req string _ list @@ resp r200 @@ ml _ p) ch types in Haskell.A shortcoming of the OCaml version is the explicit nature of adapter.However, since the adapter and the protocol type have the same structure, it can be generated semi-automatically from the type declaration in Listing when OCaml gains ad hoc polymorphism such as type classes.We expect this to be possible with modular-implicits [ ], which will be introduced in a future version of OCaml.On the other hand, it is also possible to omit the protocol type declaration in Listing by inferring the type of the adapter.

Related work
We discuss related work focusing on the functional programming languages.For other related work, see § .

Implementations in OCaml
Padovani [ ] introduces FuSe, which implements multiple sessions with dynamic linearity checking and its single-session version with static checking in OCaml.Our session-ocaml achieves static typing for multiple sessions with delegation by introducing session manipulations based on lenses; and provides an idiomatic way to declare branching with arbitrary labels; while FuSe combines static and dynamic approach to achieve them.
The following example shows that session-ocaml can avoid linearity violation, while FuSe dynamically checks it at the runtime.let rec loop () = let s = send " * " s in match branch s with `stop s -> close s |`cont _ -> loop () loop sends " * " repeatedly until it receives label stop.Although the endpoint s should be used linearly, the condition is violated at the beginning of the second iteration since the endpoint is disposed by using the wildcard _ at the end of the loop.In FuSe ., loop is well-typed and terminates in error InvalidEndpoint at runtime.In session-ocaml, this error inherently does not occur since each endpoint is implicit inside the monad and indirectly accessed by lenses.
[ ] gives a micro-benchmark which measures run-time performance between the static and dynamic versions of FuSe.Based on the benchmark, it is shown that the overhead incurred by dynamic checking is negligible when implemented with a fast communication library such as Core [ ], and concludes that the static version of FuSe performs well enough in spite of numerous closure creations in a monad.The FuSe implementation has been recently extended to context free session types [ ] by adding an endpoint attribute to session types [ ].
On duality inference, a simple approach in OCaml is firstly introduced by Pucella and Tov [ ].The idea in [ ] is to keep a pair of the current session and its dual at every step; therefore the notational size of a session type is twice as big as that in [ ]. FuSe [ ] reduces its size by almost half using the encoding technique in [ ] by modelling binary session types as a chain of linear channel types as follows.A session type in FuSe ('a, 'b) t prescribes input ('a) and output ('b) capabilities.A transmission and a reception of a value 'v followed by a session ('a, 'b) t are represented as ( _ 0, 'v * ('a, 'b) t) t and ('v * ('a, 'b) t, _ 0) t respectively, where _ 0 means "no message"; then the dual of a session type is obtained by swapping the top pair of the type.A drawback of these FuSe notations is it becomes less readable when multiple nestings are present.For example, in a simplified variant of the logic operation server in Listing with no recursion nor branch, the protocol type of log _ ch becomes: In FuSe, at server's side, the channel should be inferred as: (binop * ((bool * bool) * ( _ 0, bool * ( _ 0, _ 0) t) t, _ 0) t, _ 0) t Due to a sequence of flipping capability pairs, more effort is needed to understand the protocol.To recover the readability, FuSe supplies the translator Rosetta which compiles FuSe types into session type notation with the prefixing style and vice versa.Our polarised session types are directly represented in a prefixing manner with the slight restriction shown in § . .

Conclusion
We have shown session-ocaml, a library for session-typed communication which supports multiple simultaneous sessions with delegation in OCaml.The contributions of this paper are summarised as follows.( ) Based on lenses and the slot monad, we achieved a fully static checking of session types by the OCaml type system without adding any substantial extension to the language.Previously, a few implementations were known for a single session [ , ], but the one that allows statically-checked multiple sessions is new and shown to be useful.To the authors' knowledge, this is the first implementation which combines lenses and a parameterised monad.( ) On top of ( ), we proposed macros for arbitrarily labelled branches.The macros "patch up" only the branching and selection parts where linear variables are inevitably exposed due to limitation on polymorphic variants.( ) We proposed a session type inference framework solely based on the OCaml built-in type unification.Communication safety is guaranteed by checking equivalence of protocol types inferred at both ends with different polarities.
Type inference plays a key role in using lenses without the burden of writing any type annotations.Functional programming languages such as Standard ML, F# and Haskell have a nearly complete type inference, hence it is relatively easy to apply the method presented in this paper.On the other hand, languages such as Scala, Java and C# have a limited type inference system.However, by a recent extension with Lambda expressions in Java , lenses became available without type annotations in many cases (see a proof-of-concept at https://github.com/keigoi/slotjava).The main difficulty for implementing session types is selection primitives since they require type annotations for non-selected branches.Development of such techniques is future work.
Our approach which uses slots for simultaneous multiple sessions resembles parameterised session types [ , ], and it is smoothly extendable to the multiparty session type framework [ ].We plan to investigate code generations from Scribble [ ] (a protocol description language for the multiparty session types) along the line of [ , ] integrating with parameterised features [ , ].

Listing
Buffered channel module A slot specifier (line ) is a pair of getter and setter for accessing on a sequence of slots.Slot specifiers _ 0, _ 1, • • • (lines -) are defined as getters and setters for specific positions of (nested) pair types.

A. Implementing communication primitives
Since session types allow a channel to send and receive messages with heterogeneous types, they cannot be implemented directly by OCaml types.A resolution is to use untyped channels as an underlying communication medium as Padovani [ ] did in his FuSe work, which we do not explain here because it is relatively easy to extend the technique of [ ] by slots.Instead, we build session types based on the encoding from session types to linear types by Kobayashi et al [ ].This implementation is inherently safe since it does not use dangerous operations on untyped channels.A shortcoming is that the encoding incurs some overhead to generate a channel each time when a message is sent or received.
Listing shows the definitions of service channels (line ) and session channels (line ) where the signature of underlying Channel module are given in Listing .Hereafter channels from Channel module are called plain channels.A session channel ('p, 'r) sess (line ) is a pair of a plain channel 'p wrap Channel.t and a polarity 'r.Here, wrap (line ) is the type of the wrapper of the message payload (if any) and a plain channel for subsequent communications.The wrapper uses GADT [ ] to associate session messages with the three kinds of protocol types.The constructor Msg (lines ) is communicated by send and recv and has the protocol type of [`msg ..] and the payload is the OCaml's value type ('v).Branch{L, R} (lines -) is for branching (branch2, select _ left and select _ right) and the protocol type is [`branch of [`left .. | `right ..]].The wrapper labels have no payload since each constructor represents a branching label itself.Chan (lines -) is for delegation (deleg _ send and deleg _ recv) and the protocol type is [`deleg ..].It has a delegated session channel ('pp, 'rr) sess as a payload.
Listing shows the implementation of communication primitives.new _ channel (line ) creates a new channel and returns it.The primitives connect (lines -) and accept (lines -) create a new session channel and share the session over a service channel.Primitives for session communications send (lines -), recv (lines -), select _ left (lines -) and select _ right (lines -) ( ) take the session channel from the slot string with the lenses; and ( ) communicate using the wrapper, storing the new session channel in the slot.Branching branch2 (lines -) matches on the received message and branches to the appropriate continuations.Delegation deleg _ send (lines -) transmits the session channel stored in the second slot and empties it.deleg _ recv (lines -) receives the delegated channel and stores it in the second slot.Finally, close just throws away the session channel and fill the slot with Empty.

B Further application: a database server
As a more practical application with delegation, we show an implementation of a database server.This database processes queries with a thread pool in order to handle a number of queries and authenticate client connections to the server by the main thread.At the same time, in order to respond to the clients quickly, a session established in the main thread is delegated to the worker thread.
The database server shown in Listing behaves as follows.
. A client starts a session with the server on db _ ch and sends the authentication information (cred: credential) (line ). .The main thread accepts or rejects the client according to the authentication result.If it rejects, the session ends (lines -). .The main thread connects to a worker thread waiting on worker _ ch and delegates the session to it (line ). .The database session enters a loop which receives a command and returns a result.The client either terminates the session (line ) or send another query (query: query) to the worker thread (line ).The worker thread returns the query result (res: result) and repeats the loop (lines -).
Technical report [ ] includes the implementation of session-ocaml modules and additional examples.Appendix A shows the implementation of session-ocaml modules.For an additional example, Listing The xor server and its client open Session0 let xor _ ch = new _ channel (an example of database server.Session-ocaml is available at https://github.com/keigoi/session-ocaml.

Fig. .
Fig. .Session type changes in xor _ server [%select _ ] has open polymorphic variant type [>. ..] in pre-type to simulate subtyping of the labelled branches.
* [• • • |`lab of  | • • •]]represents a protocol that branches to   when label lab  is communicated.Here  is a communication direction. as 'a is an equi-recursive type [ ] of OCaml that represents recursive structure of a session where 'a in  is instantiated by  as 'a.Lines -describe the body of the server.It receives one of the labels bin or fin, and branches to a different protocol.match%branch0 () with |

Table .
Correspondence between polarities and communication directions

Table .
session-ocaml primitives and protocol types [`msg of req *  * ]  sending  :  at slot n let%s pat = recv _ n [`msg of resp *  * ]  Reception at slot n, in • • • binding to pattern  :  [%select _  `labi ] [`branch of req *  Select label lab at slot n [> `lab of ]] match%branch _  with [`branch of resp *  Branch at  with labels

Table .
Types for slot specifiers The delegation [`deleg of  *  * ] distinguishes polarity in the delegated session .This results in a situation where two sessions exhibiting the same communicating behaviour cannot be delegated at a single point in a protocol, if they have different polarities from each other.It is illustrated by the following (untypeable) example.
Haskell via graded monads based on a formal encoding of session-typed -calculus into PCF with an effect system.Lindley and Morris [ ] provide an embedding of the GV session-typed functional calculus [ ] into Haskell, building on a linear -calculus embedding by Polakow [ ]. Duality inference is mostly represented by a multi-parameter type class with functional dependencies [ ]; For instance, class Dual t t'| t -> t', t' -> t declares that t can be inferred from its dual t' and vice versa.However, all of the above works depend on type-level features in Haskell, hence they are not directly applicable to other programming languages including OCaml.See [ ] for a detailed survey.session-ocaml generalises the authors' previous work in Haskell [ ] by replacing type-level functions with lenses, leading to wider applicability to other programming languages.