úÎ2ü.°1      !"#$%&'()*+,-./0123TChan| has three operations: 45134513456789:689:689: F(:?:)| are declared right associative and with higher precedence than  |(:+:)| and |(:&:)|.} EIf the process on one end of a channel speaks a particular protocol, G its correspondant at the other end of the channel must be prepared to L understand it. For example, if one process speaks |Int :!: Bool :?: Eps|, 4 the other process must implement the dual protocol F |Int :?: Bool :!: Eps|. We encode the duality relation using a type < class with multiple parameters and functional dependencies  c#itep{Jones1997Type,Jones2000Type}.      ; @Session| is implemented as the composition of the IO monad with , a reader monad carrying a untyped channel. <=a :!: r| to |r|. + In its implementation, |unsafeWriteUChan| H indiscriminately transmits values of any type over an untyped channel. J Thus, if we fail to ensure that the receiving process expects a value of ) type |a|, things can go very wrong. In Sectionref{sec:theory}, we  argue that this cannot happen. HPredictably, |recv| requires the capability to receive an |a|, which it  then produces: @Session|, this does not jeopardize safety in the sense that any F messages received will still have the expected representation. Some I formulations of session types guarantee that a session, once initiated, C will run to completion, but this seems unrealistic for real-world F programs. Handling exceptions from within a session remains an open  problem. paragraph{Alternation.} GThe session actions |sel1|, |sel2|, and |offer| implement alternation. + Action |sel1| selects the left side of an ``internal choice'', D thereby replacing a session |r :+: s| with the session |r|; |sel2| O selects the right side. On the other side of the channel, |offer| combines a A |Session| computation for |r| with a computation for |s| into a ! computation that can handle |r :&(: s|. Dynamically, |sel1| sends |True| H over the channel, whereas |sel2| sends |False|, and |offer| dispatches  on the boolean value received. >Rec|, representing an environment that closes over |r|. Upon C encountering a variable occurence |Var |$n$, where $n$ is a Peano  numeral, we restore the F $n$th session type from the stack and return the stack to its former 3 state, using $n$ expressed with |zero| and |suc|: @request| receives a new, untyped channel from |accept| over the G |Rendezvous| channel and then runs the computation using the channel. ,>?@ABCDEFGHIJKLM     NOPQ !"#$%&'()*+,Aswap| may be combined to exchange any two adjacent capabilities. -./0RS/>?@ABCDEFGHIJKLM  !"#$%&'()*+,-./0)*!%"#$&'(+,- ./0 !"#$%&'()*+,-./0T      !"#$% !&'()*+,(-./012312412512612712812912:12;12<1=>1=?1=@1=A1=B1=C0"DEFsimple-sessions-0.1-Control.Concurrent.SimpleSession.SessionTypes)Control.Concurrent.SimpleSession.Implicit+Control.Concurrent.SimpleSession.Positional&Control.Concurrent.SimpleSession.TChan&Control.Concurrent.SimpleSession.UChanVarRec:&::+:DualEps:?::!:SZ RendezvousPoppopCapSessionsendrecvcloseiosel1sel2offerenterzerosuc newRendezvousacceptrequestChanneldigswap forkSession runSessionTChanCCnewTChan writeTChan readTChanUChannewUChanunsafeWriteUChanunsafeReadUChan unSessioncategory-extras-0.53.5Control.Monad.Indexed iapIxMonad=<<<>>>=ijoinibindIxMonadimzero IxMonadZeroimplus IxMonadPlusControl.Functor.Indexedimap IxFunctoriap IxApplicativeireturn IxPointedsend_caprecv_cap