• No se han encontrado resultados

Session types are a language mechanism for describing communication protocols between two actors (Honda, 1993; Kobayashi et al., 1999). A session is a channel with exactly two endpoints. Linearity ensures that the protocols for both endpoints of the channel are always in sync. Here we present a simple interface for session types, inspired by Lindley and Morris’s GV calculus (2015).

A session type is given by the following grammar:

data Session where

| (⟨!⟩) : LType → Session→ Session | (⟨?⟩) : LType → Session→ Session | End : Session

data LType where ⋯

∣ Channel : Session → LType For a linear type σ and a session type S, a channel with session type σ⟨!⟩S promises to

∆⊢e∶ChannelS–⊸LUnit ∆⊢spawn e∶Channel S new

∆⊢e∶Channel End ∆⊢close e∶LUnit close ∆⊢e∶σ ∆′⊢e′∶Channel(σ⟨!⟩S)

∆,∆′⊢send e e′∶ChannelS send

∆⊢e∶Channel(σ⟨?⟩S)

∆⊢receivee∶σ⊗ChannelS recv ∆1⊢e1∶Channel S ∆2 ⊢e2∶Channel(S–)

∆1,∆2⊢link e1 e2∶LUnit

link

Figure 3.6: Linear interface to session types.

send a value of typeσand then continue with the protocolS. On the other hand, a channel with session typeσ⟨?⟩S will receive a value of type σ and then continue asS. The session type Enddenotes the end of a communication process.

It is clear that every session typeS has a corresponding dual typeS– such that, if Alice has access to one end of the channel with session type S and Bob has access to the other end of the channel, then Bob’s channel has the session typeS–:

(σ⟨!⟩S)–≡σ⟨?⟩S– (σ⟨?⟩S)–≡σ⟨!⟩S– End–≡End

The linear type Channel S is a channel with session type S, and the interface to these channels is shown in Figure 3.6. A channel can be created by spawning a process that consumes the opposite end of the channel. A channel of session type End can be closed, resulting in a unit type. Users can send and receive values on channels, and any two channels of dual session types can be linked together, so that the communications of one are forwarded along to the other.

Lindley and Morris (2015) present an operational semantics of this language, which draws on process calculi like the π-calculus (Milner, 1999). In Chapter 4 we implement a different session-typed language and describe its operational behavior in more detail.

An echo server. Consider an echo server that receives a message, echoes that message back over the channel, then terminates. That protocol can be expressed as a session type

and implemented as a process as follows:

EchoProtocol ≡ Lower String ⟨?⟩ Lower String ⟨!⟩ End echoServer : Lift (Chan EchoProtocol⊸LUnit)

echoServer ≡ suspend (ˆλ c. let (message, c) ∶= receive c in let c ∶= send message c in close c)

Meanwhile, a client of the echo server will check that they receive the same message that they sent. Note that EchoProtocol– is equal to Lower String ⟨!⟩ Lower String ⟨?⟩ End.

echoClient : Lift (Chan EchoProtocol– ⊸

Lower Bool)

echoClient ≡ suspend (ˆλ c. let (!message,c) ∶= receive (send "ping" c) in put (message =="ping"))

First class channels. Session types can be used to send channels themselves over a connection. For example, suppose Alice and Bob want to communicate via a session protocol S, but they need a third party to connect them. This intermediary has connections to Alice and Bob, but wants to verify their identities via passwords before connecting them. Here, the typeLMaybe σ is justσ⊕LUnit; we writeLJust forι1 and LNothingforι2().

intermediary : Suspend (Chan (Lower String ⟨?⟩ LMaybe (Chan S) ⟨!⟩ End) ⊸Chan (Lower String ⟨?⟩ LMaybe (Chan S–

) ⟨!⟩ End) ⊸LUnit)

intermediary aliceChan bobChan ≡ suspend (

let (!alicePasswd, aliceChan) ∶= receive aliceChan in let (!bobPasswd, bobChan) ∶= receive bobChan in if verifyAlice alicePasswd && verifyBob bobPasswd

then let c ∶= spawn (ˆλ c'. close (send (LJust c') aliceChan)) in close (send (LJust c) bobChan)

else let () ∶= close (send LNothing aliceChan) in close (send LNothing bobChan) )

Notice that the intermediary can check the validity of Alice’s and Bob’s passwords via arbitrarily complex, non-linear procedures.

As a client, Alice can interact with the intemediary by sending her password and re- ceiving back a channel, with which she can communicate with Bob. We writealiceToBob of typeSuspend (Chan S ⊸ LUnit)for Alice’s communication with Bob.

alice : Suspend (Chan (Lower String ⟨!⟩ LMaybe (Chan S) ⟨?⟩ End)⊸LUnit alice ≡ suspend (ˆλ c. let c ∶= send "my Password" c in

let (b, c) ∶= receive c in let () ∶= close c in case b of

| LJust bobChan → force aliceToBob ˆ bobChan | LNothing → ())

A simple marketplace. Many real-life protocols describe diverging branches of commu- nication, where users have a choice of which branch to take. For example, consider the following protocol for a simple online marketplace:

1. Receive an order from a customer;

2. If the item is in stock:

(a) Send price to customer;

(b) Receive credit card number from customer;

(c) Send receipt to customer;

(d) End transaction.

3. If the item is not in stock, end transaction.

The nested protocol, items 2a–2d, can be easily defined as follows:

InStockProtocol ≡ Lower Int ⟨!⟩ Lower Int ⟨?⟩ Lower String ⟨!⟩ End inStockOp : String→ Lift (Chan InStockProtocol⊸LUnit)

inStockOp item ≡ suspend (λˆ c. let c ∶= send (put (price item)) c in let (!cc,c) ∶= receive c in

let c ∶= send (put "Thank you for your order!") c in close c )

But how can we use session types to represent the choice of whether the item is in stock or not? We can encode this protocol as a session typeS1⟨+⟩S2 that makes a choice between

two protocols. Dually, the session type S1⟨&⟩S2 offers a choice between two protocols.

S1⟨+⟩S2≡ (ChannelS1–⊕ChannelS2–)⟨!⟩End

S1⟨&⟩S2≡ (ChannelS1⊕Channel S2)⟨?⟩End

The protocol of the online marketplace can now be described with the session type MarketProtocol and can be implemented as follows:

MarketProtocol ≡ Lower String ⟨?⟩ ( InStockProtocol ⟨+⟩ End ) marketplace : Lift (Chan MarketProtocol⊸LUnit)

marketplace ≡ suspend (ˆλ c. let (!item,c) ∶= receive c in if inStock item

then close (send (fork (inStockOp item)) c) else close c)

Documento similar