packages feed

typed-session 0.1.3.0 → 0.2.0.0

raw patch · 12 files changed

+102/−1149 lines, 12 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- TypedSession.Core: [Recv] :: forall role' ps (from :: ps) (send :: role') (sps :: ps) (recv :: role') (to :: ps). Msg role' ps from '(send, sps) '(recv, to) -> Recv role' ps recv from to
- TypedSession.Core: data Recv role'1 ps1 (recv :: role') (from :: ps) (to :: ps)
- TypedSession.Codec: Encode :: (forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps). () => Msg role' ps st '(send, st') '(recv, st'') -> bytes) -> Encode role' ps bytes
+ TypedSession.Codec: Encode :: (forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps). () => Msg role' ps st send st' recv st'' -> bytes) -> Encode role' ps bytes
- TypedSession.Codec: [encode] :: Encode role' ps bytes -> forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps). () => Msg role' ps st '(send, st') '(recv, st'') -> bytes
+ TypedSession.Codec: [encode] :: Encode role' ps bytes -> forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps). () => Msg role' ps st send st' recv st'' -> bytes
- TypedSession.Core: [AnyMsg] :: forall role' (recv :: role') ps (st :: ps) (send :: role') (st' :: ps) (st'' :: ps). (SingI recv, SingI st, SingToInt role', SingToInt ps) => Msg role' ps st '(send, st') '(recv, st'') -> AnyMsg role' ps
+ TypedSession.Core: [AnyMsg] :: forall role' (recv :: role') ps (st :: ps) (send :: role') (st' :: ps) (st'' :: ps). (SingI recv, SingI st, SingToInt role', SingToInt ps) => Msg role' ps st send st' recv st'' -> AnyMsg role' ps
- TypedSession.Core: [Await] :: forall role' (r :: role') ps (st :: ps) (m :: Type -> Type) (ia :: ps -> Type). (SingI r, SingI st, SingToInt ps) => (Recv role' ps r st ~> Peer role' ps r m ia) -> Peer role' ps r m ia st
+ TypedSession.Core: [Await] :: forall role' (r :: role') ps (st :: ps) (send :: role') (sps :: ps) (m :: Type -> Type) (ia :: ps -> Type). (SingI r, SingI st, SingToInt ps) => (Msg role' ps st send sps r ~> Peer role' ps r m ia) -> Peer role' ps r m ia st
- TypedSession.Core: [Yield] :: forall role' (recv :: role') ps (st :: ps) (r :: role') (sps :: ps) (rps :: ps) (m :: Type -> Type) (ia :: ps -> Type). (SingI recv, SingI st, SingToInt ps) => Msg role' ps st '(r, sps) '(recv, rps) -> Peer role' ps r m ia sps -> Peer role' ps r m ia st
+ TypedSession.Core: [Yield] :: forall role' (recv :: role') ps (st :: ps) (r :: role') (sps :: ps) (rps :: ps) (m :: Type -> Type) (ia :: ps -> Type). (SingI recv, SingI st, SingToInt ps) => Msg role' ps st r sps recv rps -> Peer role' ps r m ia sps -> Peer role' ps r m ia st
- TypedSession.Core: await :: forall (m :: Type -> Type) role' (recv :: role') ps (from :: ps). (Functor m, SingI recv, SingI from, SingToInt ps) => Peer role' ps recv m (Recv role' ps recv from) from
+ TypedSession.Core: await :: forall (m :: Type -> Type) role' (recv :: role') ps (from :: ps) (send :: role') (sps :: ps). (Functor m, SingI recv, SingI from, SingToInt ps) => Peer role' ps recv m (Msg role' ps from send sps recv) from
- TypedSession.Core: data Msg role' ps (from :: ps) (sendAndSt :: (role', ps)) (recvAndSt :: (role', ps));
+ TypedSession.Core: data Msg role' ps (fromSt :: ps) (sender :: role') (senderNewSt :: ps) (receiver :: role') (receiverNewSt :: ps);
- TypedSession.Core: msgFromStSing :: forall role' ps (st :: ps) (send :: role') (recv :: role') (st' :: ps) (st'' :: ps). (SingI recv, SingI st) => Msg role' ps st '(send, st') '(recv, st'') -> Sing st
+ TypedSession.Core: msgFromStSing :: forall role' ps (st :: ps) (send :: role') (recv :: role') (st' :: ps) (st'' :: ps). (SingI recv, SingI st) => Msg role' ps st send st' recv st'' -> Sing st
- TypedSession.Core: yield :: forall (m :: Type -> Type) role' (recv :: role') ps (from :: ps) (send :: role') (sps :: ps) (rps :: ps). (Functor m, SingI recv, SingI from, SingToInt ps) => Msg role' ps from '(send, sps) '(recv, rps) -> Peer role' ps send m (At () sps) from
+ TypedSession.Core: yield :: forall (m :: Type -> Type) role' (recv :: role') ps (from :: ps) (send :: role') (sps :: ps) (rps :: ps). (Functor m, SingI recv, SingI from, SingToInt ps) => Msg role' ps from send sps recv rps -> Peer role' ps send m (At () sps) from
- TypedSession.Driver: Driver :: (forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps). (SingI recv, SingI st, SingToInt ps, SingToInt role') => Sing recv -> Msg role' ps st '(send, st') '(recv, st'') -> m ()) -> (forall (st' :: ps). SingToInt ps => Sing st' -> m (AnyMsg role' ps)) -> Driver role' ps (m :: Type -> Type)
+ TypedSession.Driver: Driver :: (forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps). (SingI recv, SingI st, SingToInt ps, SingToInt role') => Sing recv -> Msg role' ps st send st' recv st'' -> m ()) -> (forall (st' :: ps). SingToInt ps => Sing st' -> m (AnyMsg role' ps)) -> Driver role' ps (m :: Type -> Type)
- TypedSession.Driver: [sendMsg] :: Driver role' ps (m :: Type -> Type) -> forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps). (SingI recv, SingI st, SingToInt ps, SingToInt role') => Sing recv -> Msg role' ps st '(send, st') '(recv, st'') -> m ()
+ TypedSession.Driver: [sendMsg] :: Driver role' ps (m :: Type -> Type) -> forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps). (SingI recv, SingI st, SingToInt ps, SingToInt role') => Sing recv -> Msg role' ps st send st' recv st'' -> m ()

Files

CHANGELOG.md view
@@ -1,4 +1,6 @@ # Revision history for typed-session+## 0.2.0.0+* Remove data Recv  ## 0.1.1.0 * add protocol TH
src/TypedSession/Codec.hs view
@@ -21,7 +21,7 @@ newtype Encode role' ps bytes = Encode   { encode       :: forall (send :: role') (recv :: role') (st :: ps) (st' :: ps) (st'' :: ps)-       . Msg role' ps st '(send, st') '(recv, st'')+       . Msg role' ps st send st' recv st''       -> bytes   } 
src/TypedSession/Core.hs view
@@ -72,15 +72,25 @@ Describe the state of each role when it terminates.  @-data Msg role' ps (from :: ps) (sendAndSt :: (role', ps)) (recvAndSt :: (role', ps))+data+  Msg+    role'+    ps+    (fromSt :: ps)+    (sender :: role')+    (senderNewSt :: ps)+    (receiver :: role')+    (receiverNewSt :: ps) @ * role': the type of the role. * ps: the type of the state machine.-* ​​from: when sending a message, the sender is in this state,+* ​​fromSt: when sending a message, the sender is in this state, where the receiver may be in this state, or a more generalized state related to this state. For example, the sender is in state (S1 [True]), and the receiver is in state (S1 s).-* sendAndSt: the role that sends the message and the state of the role after sending the message.-* recvAndSt: the role that receives the message and the state of the role after receiving the message.+* sender: the role that sends the message+* senderNewSt: the state of the role after sending the message+* receiver: the role that receives the message+* receiverNewSt: the state of the role after receiving the message  There are two principles to follow when designing the state of Msg: @@ -101,20 +111,15 @@ -} class (SingToInt role', SingToInt ps) => Protocol role' ps where   type Done (sr :: role') :: ps-  data Msg role' ps (from :: ps) (sendAndSt :: (role', ps)) (recvAndSt :: (role', ps))--{- |-Package Msg and extract the required type.--@-Msg  role' ps from '(send, sps) '(recv,     rps)-Recv role' ps                     recv from rps-@--}-data Recv role' ps recv from to where-  Recv-    :: Msg role' ps from '(send, sps) '(recv, rps)-    -> Recv role' ps recv from rps+  data+    Msg+      role'+      ps+      (fromSt :: ps)+      (sender :: role')+      (senderNewSt :: ps)+      (receiver :: role')+      (receiverNewSt :: ps)  {- | Messages received from the outside are placed in MsgCache. When interpreting@@ -132,13 +137,13 @@        , SingToInt role'        , SingToInt ps        )-    => Msg role' ps st '(send, st') '(recv, st'')+    => Msg role' ps st send st' recv st''     -> AnyMsg role' ps  msgFromStSing   :: forall role' ps st send recv st' st''    . (SingI recv, SingI st)-  => Msg role' ps st '(send, st') '(recv, st'')+  => Msg role' ps st send st' recv st''   -> Sing st msgFromStSing _ = sing @st @@ -178,7 +183,7 @@      , SingI from      , SingToInt ps      )-  => (Recv role' ps recv from ~> Peer role' ps recv m ia)+  => (Msg role' ps from send sps recv ~> Peer role' ps recv m ia)   -> Peer role' ps recv m ia from @ @@ -194,7 +199,7 @@        , SingI from        , SingToInt ps        )-    => Msg role' ps from '(send, sps) '(recv, rps)+    => Msg role' ps from send sps recv rps     -> Peer role' ps send m ia sps     -> Peer role' ps send m ia from   Await@@ -202,7 +207,7 @@        , SingI from        , SingToInt ps        )-    => (Recv role' ps recv from ~> Peer role' ps recv m ia)+    => (Msg role' ps from send sps recv ~> Peer role' ps recv m ia)     -> Peer role' ps recv m ia from  instance (Functor m) => IMonadFail (Peer role' ps r m) where@@ -232,7 +237,7 @@      , SingI from      , SingToInt ps      )-  => Msg role' ps from '(send, sps) '(recv, rps)+  => Msg role' ps from send sps recv rps   -> Peer role' ps send m (At () sps) from yield msg = Yield msg (returnAt ()) @@ -245,7 +250,7 @@      , SingI from      , SingToInt ps      )-  => Peer role' ps recv m (Recv role' ps recv from) from+  => Peer role' ps recv m (Msg role' ps from send sps recv) from await = Await ireturn  {- |
src/TypedSession/Driver.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -10,7 +11,6 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wno-unused-do-bind #-}-{-# LANGUAGE NumericUnderscores #-}  {- | Schematic diagram of the communication structure of three roles through typed-session:@@ -56,7 +56,7 @@          , SingToInt role'          )       => Sing recv-      -> Msg role' ps st '(send, st') '(recv, st'')+      -> Msg role' ps st send st' recv st''       -> m ()   , recvMsg       :: forall (st' :: ps)@@ -85,12 +85,12 @@     -> m a   go (IReturn (At a)) = pure a   go (LiftM k) = k >>= go-  go (Yield (msg :: Msg role' ps (st' :: ps) '(r, sps) '(recv :: role', rps)) k) = do+  go (Yield (msg :: Msg role' ps st' r sps recv rps) k) = do     sendMsg (sing @recv) msg     go k-  go (Await (k :: (Recv role' ps r st' I.~> Peer role' ps r m ia))) = do+  go (Await (k :: (Msg role' ps st' send sps r I.~> Peer role' ps r m ia))) = do     AnyMsg msg <- recvMsg (sing @st')-    go (k $ unsafeCoerce (Recv msg))+    go (k $ unsafeCoerce msg)  {- | A wrapper around AnyMsg that represents sending and receiving Msg.@@ -158,7 +158,7 @@        , SingToInt role'        )     => Sing recv-    -> Msg role' ps from '(send, st) '(recv, st1)+    -> Msg role' ps from send st recv st1     -> m ()   sendMsg role msg = liftFun $ do     case IntMap.lookup (singToInt role) sendMap of
src/TypedSession/TH.hs view
@@ -231,8 +231,10 @@                   , ConT roleName                   , ConT protName                   , tAnyToType s a-                  , typeListT [PromotedTupleT 2, PromotedT (mkName (show from)), tAnyToType s b]-                  , typeListT [PromotedTupleT 2, PromotedT (mkName (show to)), tAnyToType s c]+                  , PromotedT (mkName (show from))+                  , tAnyToType s b+                  , PromotedT (mkName (show to))+                  , tAnyToType s c                   ]           let val =                 let gadtc =@@ -256,35 +258,40 @@   instMsgDesc <- mkDataInstanceMsg ssVar (msgT1)   fromVar <- newName "from"   sendVar <- newName "send"+  sendNewStVar <- newName "sendNewSt"   recvVar <- newName "recv"+  receiverNewStVar <- newName "receiverNewSt"   let instanceMsg =         [ InstanceD             Nothing             []             (AppT (AppT (ConT ''TSC.Protocol) (ConT roleName)) (ConT protName))             ( instDoneDesc-                ++ let ct1 = (AppT (AppT (TupleT 2) (ConT roleName)) (ConT protName))-                    in [ DataInstD-                          []-                          ( Just-                              [ KindedTV fromVar () (ConT protName)-                              , KindedTV sendVar () ct1-                              , KindedTV recvVar () ct1-                              ]-                          )-                          ( typeListT-                              [ ConT ''TSC.Msg-                              , ConT roleName-                              , ConT protName-                              , (SigT (VarT fromVar) (ConT protName))-                              , (SigT (VarT sendVar) ct1)-                              , (SigT (VarT recvVar) ct1)-                              ]-                          )-                          Nothing-                          instMsgDesc-                          []-                       ]+                ++ [ DataInstD+                      []+                      ( Just+                          [ KindedTV fromVar () (ConT protName)+                          , KindedTV sendVar () (ConT roleName)+                          , KindedTV sendNewStVar () (ConT protName)+                          , KindedTV recvVar () (ConT roleName)+                          , KindedTV receiverNewStVar () (ConT protName)+                          ]+                      )+                      ( typeListT+                          [ ConT ''TSC.Msg+                          , ConT roleName+                          , ConT protName+                          , (SigT (VarT fromVar) (ConT protName))+                          , (SigT (VarT sendVar) (ConT roleName))+                          , (SigT (VarT sendNewStVar) (ConT protName))+                          , (SigT (VarT recvVar) (ConT roleName))+                          , (SigT (VarT receiverNewStVar) (ConT protName))+                          ]+                      )+                      Nothing+                      instMsgDesc+                      []+                   ]             )         ] 
− test/Book.hs
@@ -1,232 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE QualifiedDo #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -Wno-unused-do-bind #-}--module Book where--import Control.Concurrent.Class.MonadSTM-import Control.Monad-import Control.Monad.Class.MonadFork (MonadFork, forkIO)-import Control.Monad.Class.MonadSay-import Control.Monad.Class.MonadThrow (MonadThrow)-import Data.IFunctor (At (..), Sing, SingI, ireturn, returnAt)-import qualified Data.IFunctor as I-import qualified Data.IntMap as IntMap-import Data.Kind-import GHC.Exts (dataToTag#)-import GHC.Int (Int (I#))-import TypedSession.Codec-import TypedSession.Core-import TypedSession.Driver-import Control.Monad.Class.MonadTimer (MonadDelay)--{------------------------------------------------------------------------------    Buyer                                                      Seller-    :S0                                                        :S0-     <                     Title String  ->                     >-    :S1                                                        :S1-     <                     <-  Price Int                         >-    :S12 s                                                     :S12 s--   ----------------------------------------------------------------------   |:S12 EnoughBudget                                          :S12 s-   | <                  Afford ->                               >-   |:S3                                                        :S3-   | <                  <- Data Int                             >-   |:End                                                       :End-   -----------------------------------------------------------------------   ----------------------------------------------------------------------   |:S12 NotEnoughBuget                                        :S12 s-   | <                  NotBuy ->                               >-   |:End                                                       :End-   ---------------------------------------------------------------------- -}--data Role = Buyer | Seller-  deriving (Show, Eq, Ord)--data SRole :: Role -> Type where-  SBuyer :: SRole Buyer-  SSeller :: SRole Seller--type instance Sing = SRole--instance SingI Buyer where-  sing = SBuyer--instance SingI Seller where-  sing = SSeller--data BudgetSt-  = EnoughBudget-  | NotEnoughBuget--data BookSt-  = S0-  | S1-  | S12 BudgetSt-  | S3-  | End--data SBookSt :: BookSt -> Type where-  SS0 :: SBookSt S0-  SS1 :: SBookSt S1-  SS12 :: SBookSt (S12 (s :: BudgetSt))-  SS3 :: SBookSt S3-  SEnd :: SBookSt End--type instance Sing = SBookSt--instance SingI S0 where-  sing = SS0--instance SingI S1 where-  sing = SS1--instance SingI (S12 s) where-  sing = SS12--instance SingI S3 where-  sing = SS3--instance SingI End where-  sing = SEnd--type Date = Int--instance SingToInt Role where-  singToInt x = I# (dataToTag# x)--instance SingToInt BookSt where-  singToInt x = I# (dataToTag# x)--instance Protocol Role BookSt where-  type Done Buyer = End-  type Done Seller = End--  data Msg Role BookSt from send recv where-    Title :: String -> Msg Role BookSt S0 '(Buyer, S1) '(Seller, S1)-    Price :: Int -> Msg Role BookSt S1 '(Seller, S12 s) '(Buyer, S12 s)-    Afford :: Msg Role BookSt (S12 EnoughBudget) '(Buyer, S3) '(Seller, S3)-    Date :: Date -> Msg Role BookSt S3 '(Seller, End) '(Buyer, End)-    NotBuy :: Msg Role BookSt (S12 NotEnoughBuget) '(Buyer, End) '(Seller, End)--encodeMsg :: Encode Role BookSt (AnyMsg Role BookSt)-encodeMsg = Encode $ \x -> case x of-  Title{} -> AnyMsg x-  Price{} -> AnyMsg x-  Afford{} -> AnyMsg x-  Date{} -> AnyMsg x-  NotBuy{} -> AnyMsg x--decodeMsg-  :: DecodeStep-      (AnyMsg Role BookSt)-      CodecFailure-      (AnyMsg Role BookSt)-decodeMsg =-  DecodePartial $ \case-    Nothing -> DecodeFail (CodecFailure "expected more data")-    Just anyMsg -> DecodeDone anyMsg Nothing--budget :: Int-budget = 100--data CheckPriceResult :: BookSt -> Type where-  Yes :: CheckPriceResult (S12 EnoughBudget)-  No :: CheckPriceResult (S12 NotEnoughBuget)--checkPrice :: (Monad m) => Int -> Peer Role BookSt Buyer m CheckPriceResult (S12 s)-checkPrice i =-  if i <= budget-    then LiftM $ pure (ireturn Yes)-    else LiftM $ pure (ireturn No)--buyerPeer-  :: (Monad m) => Peer Role BookSt Buyer m (At (Maybe Date) (Done Buyer)) S0-buyerPeer = I.do-  yield (Title "haskell book")-  Recv (Price i) <- await-  res <- checkPrice i-  case res of-    Yes -> I.do-      yield Afford-      Recv (Date d) <- await-      returnAt (Just d)-    No -> I.do-      yield NotBuy-      returnAt Nothing--sellerPeer :: (Functor m) => Peer Role BookSt Seller m (At () (Done Seller)) S0-sellerPeer = I.do-  Recv (Title _name) <- await-  yield (Price 30)-  Recv msg <- await-  case msg of-    Afford -> I.do-      yield (Date 100)-    NotBuy -> I.do-      returnAt ()--mvarsAsChannel-  :: (MonadSTM m)-  => TMVar m a-  -> TMVar m a-  -> Channel m a-mvarsAsChannel bufferRead bufferWrite =-  Channel{send, recv}- where-  send x = atomically (putTMVar bufferWrite x)-  recv = atomically (Just <$> takeTMVar bufferRead)--myTracer :: (MonadSay m) => String -> Tracer Role BookSt m-myTracer st v = say (st <> show v)--instance Show (AnyMsg Role BookSt) where-  show (AnyMsg msg) = case msg of-    Title st -> "Title " <> show st-    Price i -> "Price " <> show i-    Afford -> "Afford"-    Date i -> "Date " <> show i-    NotBuy -> "NotBuy"--runAll :: forall m. (Monad m, MonadDelay m, MonadSTM m, MonadSay m, MonadFork m, MonadThrow m) => m ()-runAll = do-  buyerTMVar <- newEmptyTMVarIO @m @(AnyMsg Role BookSt)-  sellerTMVar <- newEmptyTMVarIO @m @(AnyMsg Role BookSt)-  let buyerChannel = mvarsAsChannel @m buyerTMVar sellerTMVar-      sellerChannel = mvarsAsChannel @m sellerTMVar buyerTMVar-      sendFun bufferWrite x = atomically (putTMVar bufferWrite x)-      sendToRole =-        IntMap.fromList-          [ (singToInt SSeller, sendFun sellerTMVar)-          , (singToInt SBuyer, sendFun buyerTMVar)-          ]-  buyerTvar <- newTVarIO IntMap.empty-  sellerTvar <- newTVarIO IntMap.empty-  let buyerDriver = driverSimple (myTracer "buyer") encodeMsg sendToRole buyerTvar id-      sellerDriver = driverSimple (myTracer "seller") encodeMsg sendToRole sellerTvar id-  -- fork buyer decode thread, seller -> buyer-  forkIO $ decodeLoop (myTracer "buyer") Nothing (Decode decodeMsg) buyerChannel buyerTvar-  -- fork seller decode thread, buyer -> seller-  forkIO $ decodeLoop (myTracer "seller") Nothing (Decode decodeMsg) sellerChannel sellerTvar-  -- fork seller Peer thread-  forkIO $ void $ runPeerWithDriver sellerDriver sellerPeer-  -- run buyer Peer-  void $ runPeerWithDriver buyerDriver buyerPeer
− test/Book1.hs
@@ -1,281 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE QualifiedDo #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -Wno-unused-do-bind #-}--module Book1 where--import Control.Concurrent.Class.MonadSTM-import Control.Monad-import Control.Monad.Class.MonadFork (MonadFork, forkIO)-import Control.Monad.Class.MonadSay-import Control.Monad.Class.MonadThrow (MonadThrow)-import Data.IFunctor (At (..), Sing, SingI, ireturn, returnAt)-import qualified Data.IFunctor as I-import qualified Data.IntMap as IntMap-import Data.Kind-import GHC.Exts (dataToTag#)-import GHC.Int (Int (I#))-import TypedSession.Codec-import TypedSession.Core-import TypedSession.Driver-import Control.Monad.Class.MonadTimer (MonadDelay)--{---------------------------------------------------------------------------------------------------    Buyer                                                      Seller                  Buyer2-    :S0                                                        :S0-     <                     Title String  ->                     >-    :S1                                                        :S1-     <                     <-  Price Int                         >-    :S11                                                       :S12 s                  :S11-     <                                  PriceToBuyer2 Int ->                            >-    :S110                                                                              :S110-     <                                  <- HalfPrice  Int                               >-    :S12 s                                                                             :End--   ----------------------------------------------------------------------   |:S12 EnoughBudget                                          :S12 s-   | <                  Afford ->                               >-   |:S3                                                        :S3-   | <                  <- Data Int                             >-   |:End                                                       :End-   -----------------------------------------------------------------------   ----------------------------------------------------------------------   |:S12  NotEnoughBuget                                       :S12-   | <                  NotBuy ->                               >-   |:End                                                       :End-   -----------------------------------------------------------------------}--data Role = Buyer | Seller | Buyer2-  deriving (Show, Eq, Ord)--data SRole :: Role -> Type where-  SBuyer :: SRole Buyer-  SBuyer2 :: SRole Buyer2-  SSeller :: SRole Seller--type instance Sing = SRole--instance SingI Buyer where-  sing = SBuyer--instance SingI Buyer2 where-  sing = SBuyer2--instance SingI Seller where-  sing = SSeller--data BudgetSt-  = EnoughBudget-  | NotEnoughBuget--data BookSt-  = S0-  | S1-  | S11-  | S110-  | S12 BudgetSt-  | S3-  | End--data SBookSt :: BookSt -> Type where-  SS0 :: SBookSt S0-  SS1 :: SBookSt S1-  SS11 :: SBookSt S11-  SS110 :: SBookSt S110-  SS12 :: SBookSt (S12 (s :: BudgetSt))-  SS3 :: SBookSt S3-  SEnd :: SBookSt End--type instance Sing = SBookSt--instance SingI S0 where-  sing = SS0--instance SingI S1 where-  sing = SS1--instance SingI S11 where-  sing = SS11--instance SingI S110 where-  sing = SS110--instance SingI (S12 s) where-  sing = SS12--instance SingI S3 where-  sing = SS3--instance SingI End where-  sing = SEnd--type Date = Int--instance SingToInt Role where-  singToInt x = I# (dataToTag# x)--instance SingToInt BookSt where-  singToInt x = I# (dataToTag# x)--instance Protocol Role BookSt where-  type Done Buyer = End-  type Done Seller = End-  type Done Buyer2 = End-  data Msg Role BookSt from send recv where-    Title :: String -> Msg Role BookSt S0 '(Buyer, S1) '(Seller, S1)-    Price :: Int -> Msg Role BookSt S1 '(Seller, S12 s) '(Buyer, S11)-    PriceToB2 :: Int -> Msg Role BookSt S11 '(Buyer, S110) '(Buyer2, S110)-    HalfPrice :: Int -> Msg Role BookSt S110 '(Buyer2, End) '(Buyer, S12 s)-    Afford :: Msg Role BookSt (S12 EnoughBudget) '(Buyer, S3) '(Seller, S3)-    Date :: Date -> Msg Role BookSt S3 '(Seller, End) '(Buyer, End)-    NotBuy :: Msg Role BookSt (S12 NotEnoughBuget) '(Buyer, End) '(Seller, End)--encodeMsg :: Encode Role BookSt (AnyMsg Role BookSt)-encodeMsg = Encode $ \x -> case x of-  Title{} -> AnyMsg x-  Price{} -> AnyMsg x-  PriceToB2{} -> AnyMsg x-  HalfPrice{} -> AnyMsg x-  Afford{} -> AnyMsg x-  Date{} -> AnyMsg x-  NotBuy{} -> AnyMsg x--decodeMsg-  :: DecodeStep-      (AnyMsg Role BookSt)-      CodecFailure-      (AnyMsg Role BookSt)-decodeMsg =-  DecodePartial $ \case-    Nothing -> DecodeFail (CodecFailure "expected more data")-    Just anyMsg -> DecodeDone anyMsg Nothing--budget :: Int-budget = 16--data CheckPriceResult :: BookSt -> Type where-  Yes :: CheckPriceResult (S12 EnoughBudget)-  No :: CheckPriceResult (S12 NotEnoughBuget)--checkPrice :: (Monad m) => Int -> Int -> Peer Role BookSt Buyer m CheckPriceResult (S12 s)-checkPrice i h =-  if i <= budget + h-    then LiftM $ pure (ireturn Yes)-    else LiftM $ pure (ireturn No)--buyerPeer-  :: (Monad m) => Peer Role BookSt Buyer m (At (Maybe Date) (Done Buyer)) S0-buyerPeer = I.do-  yield (Title "haskell book")-  Recv (Price i) <- await-  yield (PriceToB2 i)-  Recv (HalfPrice hv) <- await-  res <- checkPrice i hv-  case res of-    Yes -> I.do-      yield Afford-      Recv (Date d) <- await-      returnAt (Just d)-    No -> I.do-      yield NotBuy-      returnAt Nothing--buyer2Peer-  :: (Monad m) => Peer Role BookSt Buyer2 m (At () (Done Buyer2)) S11-buyer2Peer = I.do-  Recv (PriceToB2 i) <- await-  yield (HalfPrice (i `div` 2))--sellerPeer :: (Monad m) => Peer Role BookSt Seller m (At () (Done Seller)) S0-sellerPeer = I.do-  Recv (Title _name) <- await-  yield (Price 30)-  Recv msg <- await-  case msg of-    Afford -> yield (Date 100)-    NotBuy -> returnAt ()--mvarsAsChannel-  :: (MonadSTM m)-  => TMVar m a-  -> TMVar m a-  -> Channel m a-mvarsAsChannel bufferRead bufferWrite =-  Channel{send, recv}- where-  send x = atomically (putTMVar bufferWrite x)-  recv = atomically (Just <$> takeTMVar bufferRead)--myTracer :: (MonadSay m) => String -> Tracer Role BookSt m-myTracer st v = say (st <> show v)--instance Show (AnyMsg Role BookSt) where-  show (AnyMsg msg) = case msg of-    Title st -> "Title " <> show st-    Price i -> "Price " <> show i-    PriceToB2 i -> "PriceToB2 " <> show i-    HalfPrice i -> "HalfPrice " <> show i-    Afford -> "Afford"-    Date i -> "Date " <> show i-    NotBuy -> "NotBuy"--runAll :: forall m. (Monad m, MonadDelay m, MonadSTM m, MonadSay m, MonadFork m, MonadThrow m) => m ()-runAll = do-  buyerTMVar <- newEmptyTMVarIO @m @(AnyMsg Role BookSt)-  buyer2TMVar <- newEmptyTMVarIO @m @(AnyMsg Role BookSt)-  sellerTMVar <- newEmptyTMVarIO @m @(AnyMsg Role BookSt)-  let buyerSellerChannel = mvarsAsChannel @m buyerTMVar sellerTMVar-      buyerBuyer2Channel = mvarsAsChannel @m buyerTMVar buyer2TMVar--      sellerBuyerChannel = mvarsAsChannel @m sellerTMVar buyerTMVar--      buyer2BuyerChannel = mvarsAsChannel @m buyer2TMVar buyerTMVar--      sendFun bufferWrite x = atomically (putTMVar bufferWrite x)-      sendToRole =-        IntMap.fromList-          [ (singToInt SSeller, sendFun sellerTMVar)-          , (singToInt SBuyer, sendFun buyerTMVar)-          , (singToInt SBuyer2, sendFun buyer2TMVar)-          ]-  buyerTvar <- newTVarIO IntMap.empty-  buyer2Tvar <- newTVarIO IntMap.empty-  sellerTvar <- newTVarIO IntMap.empty-  let buyerDriver = driverSimple (myTracer "buyer") encodeMsg sendToRole buyerTvar id-      buyer2Driver = driverSimple (myTracer "buyer2") encodeMsg sendToRole buyer2Tvar id-      sellerDriver = driverSimple (myTracer "seller") encodeMsg sendToRole sellerTvar id-  -- fork buyer decode thread, seller -> buyer-  forkIO $ decodeLoop (myTracer "buyer") Nothing (Decode decodeMsg) buyerSellerChannel buyerTvar-  -- fork buyer decode thread, buyer2 -> buyer-  forkIO $ decodeLoop (myTracer "buyer") Nothing (Decode decodeMsg) buyerBuyer2Channel buyerTvar--  -- fork seller decode thread, buyer -> seller-  forkIO $ decodeLoop (myTracer "seller") Nothing (Decode decodeMsg) sellerBuyerChannel sellerTvar--  -- fork buyer2 decode thread, buyer -> buyer2-  forkIO $ decodeLoop (myTracer "buyer2") Nothing (Decode decodeMsg) buyer2BuyerChannel buyer2Tvar--  -- fork seller Peer thread-  forkIO $ void $ runPeerWithDriver sellerDriver sellerPeer--  -- fork buyer2 Peer thread-  forkIO $ void $ runPeerWithDriver buyer2Driver buyer2Peer-  -- run buyer Peer-  void $ runPeerWithDriver buyerDriver buyerPeer
− test/Book2.hs
@@ -1,342 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE QualifiedDo #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -Wno-unused-do-bind #-}--module Book2 where--import Control.Concurrent.Class.MonadSTM-import Control.Monad-import Control.Monad.Class.MonadFork (MonadFork, forkIO)-import Control.Monad.Class.MonadSay-import Control.Monad.Class.MonadThrow (MonadThrow)-import Control.Monad.Class.MonadTimer (MonadDelay)-import Data.IFunctor (At (..), Sing, SingI, ireturn, returnAt)-import qualified Data.IFunctor as I-import qualified Data.IntMap as IntMap-import Data.Kind-import GHC.Exts (dataToTag#)-import GHC.Int (Int (I#))-import TypedSession.Codec-import TypedSession.Core-import TypedSession.Driver--{--------------------Buyer---------------Seller--------------Buyer2------------------                   S0                  S0                 S1 s-       Title       |        --->       |-                  S2 s                S2 s                S1 s-    ------------------------------BookNotFound-------------------------------                  S2 s          S2 BookNotFound           S1 s-    BookNotFoun    |        <---       |-            S1 BookNotFound           End                 S1 s-  SellerNotFoundB  |                  --->                 |-                  End                 End                 End-                                    Terminal--    -------------------------------BookFound---------------------------------                  S2 s            S2 BookFound            S1 s-       Price       |        <---       |-              S1 BookFound            S3 s                S1 s-   PriceToBuyer2   |                  --->                 |-                   S4                 S3 s                 S4-     HalfPrice     |                  <---                 |-                  S3 s                S3 s                S5 s-        --------------------------EnoughBudget---------------------------            S3 EnoughBudget           S3 s                S5 s-       Afford      |        --->       |-                   S6                  S6                 S5 s-        Data       |        <---       |-            S5 EnoughBudget           End                 S5 s-      Success      |                  --->                 |-                  End                 End                 End-                                    Terminal--        ------------------------NotEnoughBudget--------------------------           S3 NotEnoughBudget         S3 s                S5 s-       NotBuy      |        --->       |-           S5 NotEnoughBudget         End                 S5 s-       Failed      |                  --->                 |-                  End                 End                 End-                                    Terminal--}--data Role = Buyer | Seller | Buyer2-  deriving (Show, Eq, Ord)--data SRole :: Role -> Type where-  SBuyer :: SRole Buyer-  SBuyer2 :: SRole Buyer2-  SSeller :: SRole Seller--type instance Sing = SRole--instance SingI Buyer where-  sing = SBuyer--instance SingI Buyer2 where-  sing = SBuyer2--instance SingI Seller where-  sing = SSeller--data FindBook-  = BookNotFound-  | BookFound--data BudgetSt-  = EnoughBudget-  | NotEnoughBuget--data BookSt-  = S0-  | S1 FindBook-  | S2 FindBook-  | S3 BudgetSt-  | S4-  | S5 BudgetSt-  | S6-  | End--data SBookSt :: BookSt -> Type where-  SS0 :: SBookSt S0-  SS1 :: SBookSt (S1 (s :: FindBook))-  SS2 :: SBookSt (S2 (s :: FindBook))-  SS3 :: SBookSt (S3 (s :: BudgetSt))-  SS4 :: SBookSt S4-  SS5 :: SBookSt (S5 (s :: BudgetSt))-  SS6 :: SBookSt S6-  SEnd :: SBookSt End--type instance Sing = SBookSt--instance SingI S0 where-  sing = SS0--instance SingI (S1 s) where-  sing = SS1--instance SingI (S2 s) where-  sing = SS2--instance SingI (S3 s) where-  sing = SS3--instance SingI S4 where-  sing = SS4--instance SingI (S5 s) where-  sing = SS5--instance SingI S6 where-  sing = SS6--instance SingI End where-  sing = SEnd--type Date = Int--instance SingToInt Role where-  singToInt x = I# (dataToTag# x)--instance SingToInt BookSt where-  singToInt x = I# (dataToTag# x)--instance Protocol Role BookSt where-  type Done Buyer = End-  type Done Seller = End-  type Done Buyer2 = End-  data Msg Role BookSt from send recv where-    Title :: String -> Msg Role BookSt S0 '(Buyer, S2 s) '(Seller, S2 s)-    Price :: Int -> Msg Role BookSt (S2 BookFound) '(Seller, S3 s) '(Buyer, S1 BookFound)-    PriceToB2 :: Int -> Msg Role BookSt (S1 BookFound) '(Buyer, S4) '(Buyer2, S4)-    HalfPrice :: Int -> Msg Role BookSt S4 '(Buyer2, S5 s) '(Buyer, S3 s)-    Afford :: Msg Role BookSt (S3 EnoughBudget) '(Buyer, S6) '(Seller, S6)-    Date :: Date -> Msg Role BookSt S6 '(Seller, End) '(Buyer, S5 EnoughBudget)-    Success :: Int -> Msg Role BookSt (S5 EnoughBudget) '(Buyer, End) '(Buyer2, End)-    NotBuy :: Msg Role BookSt (S3 NotEnoughBuget) '(Buyer, S5 NotEnoughBuget) '(Seller, End)-    Failed :: Msg Role BookSt (S5 NotEnoughBuget) '(Buyer, End) '(Buyer2, End)-    BookNotFoun :: Msg Role BookSt (S2 BookNotFound) '(Seller, End) '(Buyer, S1 BookNotFound)-    SellerNotFoundBook :: Msg Role BookSt (S1 BookNotFound) '(Buyer, End) '(Buyer2, End)--encodeMsg :: Encode Role BookSt (AnyMsg Role BookSt)-encodeMsg = Encode $ \x -> case x of-  Title{} -> AnyMsg x-  Price{} -> AnyMsg x-  PriceToB2{} -> AnyMsg x-  HalfPrice{} -> AnyMsg x-  Afford{} -> AnyMsg x-  Date{} -> AnyMsg x-  Success{} -> AnyMsg x-  NotBuy{} -> AnyMsg x-  Failed{} -> AnyMsg x-  BookNotFoun{} -> AnyMsg x-  SellerNotFoundBook{} -> AnyMsg x--decodeMsg-  :: DecodeStep-      (AnyMsg Role BookSt)-      CodecFailure-      (AnyMsg Role BookSt)-decodeMsg =-  DecodePartial $ \case-    Nothing -> DecodeFail (CodecFailure "expected more data")-    Just anyMsg -> DecodeDone anyMsg Nothing--budget :: Int-budget = 16--data CheckPriceResult :: BookSt -> Type where-  Yes :: CheckPriceResult (S3 EnoughBudget)-  No :: CheckPriceResult (S3 NotEnoughBuget)--checkPrice :: (Monad m) => Int -> Int -> Peer Role BookSt Buyer m CheckPriceResult (S3 s)-checkPrice i h =-  if i <= budget + h-    then LiftM $ pure (ireturn Yes)-    else LiftM $ pure (ireturn No)--buyerPeer-  :: (Monad m) => Peer Role BookSt Buyer m (At (Maybe Date) (Done Buyer)) S0-buyerPeer = I.do-  yield (Title "haskell book")-  Recv msg <- await-  case msg of-    BookNotFoun -> I.do-      yield SellerNotFoundBook-      returnAt Nothing-    Price i -> I.do-      yield (PriceToB2 i)-      Recv (HalfPrice hv) <- await-      res <- checkPrice i hv-      case res of-        Yes -> I.do-          yield Afford-          Recv (Date d) <- await-          yield (Success d)-          returnAt (Just d)-        No -> I.do-          yield NotBuy-          yield Failed-          returnAt Nothing--buyer2Peer-  :: (Monad m) => Peer Role BookSt Buyer2 m (At () (Done Buyer2)) (S1 s)-buyer2Peer = I.do-  Recv msg' <- await-  case msg' of-    SellerNotFoundBook -> returnAt ()-    PriceToB2 i -> I.do-      yield (HalfPrice (i `div` 2))-      Recv msg <- await-      case msg of-        Success _ -> returnAt ()-        Failed -> returnAt ()--data FindBookResult :: BookSt -> Type where-  Found :: FindBookResult (S2 BookFound)-  NotFound :: FindBookResult (S2 BookNotFound)--findBook :: (Monad m) => String -> Peer Role BookSt Seller m FindBookResult (S2 s)-findBook st =-  if st /= ""-    then LiftM $ pure (ireturn Found)-    else LiftM $ pure (ireturn NotFound)--sellerPeer :: (Monad m) => Peer Role BookSt Seller m (At () (Done Seller)) S0-sellerPeer = I.do-  Recv (Title name) <- await-  res <- findBook name-  case res of-    Found -> I.do-      yield (Price 30)-      Recv msg <- await-      case msg of-        Afford -> yield (Date 100)-        NotBuy -> returnAt ()-    NotFound -> yield BookNotFoun--mvarsAsChannel-  :: (MonadSTM m)-  => TMVar m a-  -> TMVar m a-  -> Channel m a-mvarsAsChannel bufferRead bufferWrite =-  Channel{send, recv}- where-  send x = atomically (putTMVar bufferWrite x)-  recv = atomically (Just <$> takeTMVar bufferRead)--myTracer :: (MonadSay m) => String -> Tracer Role BookSt m-myTracer st v = say (st <> show v)--instance Show (AnyMsg Role BookSt) where-  show (AnyMsg msg) = case msg of-    Title st -> "Title " <> show st-    Price i -> "Price " <> show i-    PriceToB2 i -> "PriceToB2 " <> show i-    HalfPrice i -> "HalfPrice " <> show i-    Afford -> "Afford"-    Date i -> "Date " <> show i-    NotBuy -> "NotBuy"-    Success i -> "Success " <> show i-    Failed -> "Failed"-    BookNotFoun -> "BookNotFound"-    SellerNotFoundBook -> "SellerNotFoundBook"--runAll :: forall m. (Monad m, MonadDelay m, MonadSTM m, MonadSay m, MonadFork m, MonadThrow m) => m ()-runAll = do-  buyerTMVar <- newEmptyTMVarIO @m @(AnyMsg Role BookSt)-  buyer2TMVar <- newEmptyTMVarIO @m @(AnyMsg Role BookSt)-  sellerTMVar <- newEmptyTMVarIO @m @(AnyMsg Role BookSt)-  let buyerSellerChannel = mvarsAsChannel @m buyerTMVar sellerTMVar-      buyerBuyer2Channel = mvarsAsChannel @m buyerTMVar buyer2TMVar--      sellerBuyerChannel = mvarsAsChannel @m sellerTMVar buyerTMVar--      buyer2BuyerChannel = mvarsAsChannel @m buyer2TMVar buyerTMVar--      sendFun bufferWrite x = atomically (putTMVar bufferWrite x)-      sendToRole =-        IntMap.fromList-          [ (singToInt SSeller, sendFun sellerTMVar)-          , (singToInt SBuyer, sendFun buyerTMVar)-          , (singToInt SBuyer2, sendFun buyer2TMVar)-          ]-  buyerTvar <- newTVarIO IntMap.empty-  buyer2Tvar <- newTVarIO IntMap.empty-  sellerTvar <- newTVarIO IntMap.empty-  let buyerDriver = driverSimple (myTracer "buyer") encodeMsg sendToRole buyerTvar id-      buyer2Driver = driverSimple (myTracer "buyer2") encodeMsg sendToRole buyer2Tvar id-      sellerDriver = driverSimple (myTracer "seller") encodeMsg sendToRole sellerTvar id-  -- fork buyer decode thread, seller -> buyer-  forkIO $ decodeLoop (myTracer "buyer") Nothing (Decode decodeMsg) buyerSellerChannel buyerTvar-  -- fork buyer decode thread, buyer2 -> buyer-  forkIO $ decodeLoop (myTracer "buyer") Nothing (Decode decodeMsg) buyerBuyer2Channel buyerTvar--  -- fork seller decode thread, buyer -> seller-  forkIO $ decodeLoop (myTracer "seller") Nothing (Decode decodeMsg) sellerBuyerChannel sellerTvar--  -- fork buyer2 decode thread, buyer -> buyer2-  forkIO $ decodeLoop (myTracer "buyer2") Nothing (Decode decodeMsg) buyer2BuyerChannel buyer2Tvar--  -- fork seller Peer thread-  forkIO $ void $ runPeerWithDriver sellerDriver sellerPeer--  -- fork buyer2 Peer thread-  forkIO $ void $ runPeerWithDriver buyer2Driver buyer2Peer-  -- run buyer Peer-  void $ runPeerWithDriver buyerDriver buyerPeer
test/Book3/Peer.hs view
@@ -55,38 +55,33 @@ buyerPeer = I.do   yield (Title "haskell book")   await I.>>= \case-    Recv NoBook -> I.do+    NoBook -> I.do       yield SellerNoBook       returnAt Nothing-    Recv (Price i) -> I.do+    Price i -> I.do       choiceOT i I.>>= \case         BranchSt_One -> I.do           yield OneAccept-          Recv (OneDate d) <- await+          OneDate d <- await           yield (OneSuccess d)           returnAt $ Just d-        BranchSt_Two -> f1- where-  f1-    :: (Has Random sig m)-    => Peer BookRole Book 'Buyer m (At (Maybe Date) (Done Buyer)) ('S1 'Two)-  f1 = I.do-    yield (PriceToBuyer2 300)-    await I.>>= \case-      Recv NotSupport1 -> I.do-        yield TwoNotBuy-        returnAt Nothing-      Recv (SupportVal h) -> I.do-        checkPrice 10 h I.>>= \case-          BranchSt_Enough -> I.do-            yield TwoAccept-            Recv (TwoDate d) <- await-            yield (TwoSuccess d)-            returnAt (Just d)-          BranchSt_NotEnough -> I.do-            yield TwoNotBuy1-            yield TwoFailed-            returnAt Nothing+        BranchSt_Two -> I.do+          yield (PriceToBuyer2 (i `div` 2))+          await I.>>= \case+            NotSupport1 -> I.do+              yield TwoNotBuy+              returnAt Nothing+            SupportVal h -> I.do+              checkPrice 10 h I.>>= \case+                BranchSt_Enough -> I.do+                  yield TwoAccept+                  TwoDate d <- await+                  yield (TwoSuccess d)+                  returnAt (Just d)+                BranchSt_NotEnough -> I.do+                  yield TwoNotBuy1+                  yield TwoFailed+                  returnAt Nothing  choiceB   :: (Has Random sig m)@@ -103,9 +98,9 @@   => Peer BookRole Book Buyer2 m (At (Maybe Date) (Done Buyer2)) (S1 s) buyer2Peer = I.do   await I.>>= \case-    Recv SellerNoBook -> returnAt Nothing-    Recv (OneSuccess d) -> returnAt (Just d)-    Recv (PriceToBuyer2 i) -> I.do+    SellerNoBook -> returnAt Nothing+    (OneSuccess d) -> returnAt (Just d)+    (PriceToBuyer2 i) -> I.do       choiceB i I.>>= \case         BranchSt_NotSupport -> I.do           yield NotSupport1@@ -113,8 +108,8 @@         BranchSt_Support -> I.do           yield (SupportVal (i `div` 2))           await I.>>= \case-            Recv (TwoSuccess d) -> returnAt $ Just d-            Recv TwoFailed -> returnAt Nothing+            TwoSuccess d -> returnAt $ Just d+            TwoFailed -> returnAt Nothing  findBook   :: (Has Random sig m)@@ -130,13 +125,13 @@   :: (Has Random sig m)   => Peer BookRole Book Seller m (At () (Done Seller)) S0 sellerPeer = I.do-  Recv (Title st) <- await+  (Title st) <- await   findBook st I.>>= \case     BranchSt_NotFound -> yield NoBook     BranchSt_Found -> I.do       yield (Price 30)       await I.>>= \case-        Recv OneAccept -> yield (OneDate 100)-        Recv TwoNotBuy -> returnAt ()-        Recv TwoAccept -> yield (TwoDate 100)-        Recv TwoNotBuy1 -> returnAt ()+        OneAccept -> yield (OneDate 100)+        TwoNotBuy -> returnAt ()+        TwoAccept -> yield (TwoDate 100)+        TwoNotBuy1 -> returnAt ()
test/Book3/Protocol.hs view
@@ -17,7 +17,6 @@  import Book3.Type -import Language.Haskell.TH hiding (Type) import TypedSession.Codec import TypedSession.Core 
− test/PingPong.hs
@@ -1,196 +0,0 @@-{-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE QualifiedDo #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS_GHC -Wno-unused-do-bind #-}--module PingPong where--import Control.Concurrent.Class.MonadSTM-import Control.Monad-import Control.Monad.Class.MonadFork (MonadFork, forkIO)-import Control.Monad.Class.MonadSay-import Control.Monad.Class.MonadThrow (MonadThrow)-import Control.Monad.Class.MonadTimer (MonadDelay)-import Data.IFunctor (At (..), Sing, SingI, ireturn, returnAt)-import qualified Data.IFunctor as I-import qualified Data.IntMap as IntMap-import Data.Kind-import GHC.Exts (dataToTag#)-import GHC.Int (Int (I#))-import TypedSession.Codec-import TypedSession.Core-import TypedSession.Driver--{------------------------------------------------------------------------------   Client                               Server-    :S0 s                                 :S0 s-  ------------------------------------------------------------------------  | :S0 True                           :S0 s-  |             Ping    ->-  | :S1                                :S1-  |             <- Pong-  | :S0 s                               :S0 s-  -------------------------------------------------------------------------  ------------------------------------------------------------------------  |  :S0 False                          :S0 s-  |               Stop    ->-  |  :End                               :End-  ------------------------------------------------------------------------ -}--data Role = Client | Server-  deriving (Show, Eq, Ord)--data SRole :: Role -> Type where-  SClient :: SRole Client-  SServer :: SRole Server--type instance Sing = SRole--instance SingI Client where-  sing = SClient--instance SingI Server where-  sing = SServer--data PingPong-  = S0 Bool-  | S1-  | End--data SPingPong :: PingPong -> Type where-  SS0 :: SPingPong (S0 b)-  SS1 :: SPingPong S1-  SEnd :: SPingPong End--type instance Sing = SPingPong--instance SingI (S0 b) where-  sing = SS0--instance SingI S1 where-  sing = SS1--instance SingI End where-  sing = SEnd--instance SingToInt Role where-  singToInt x = I# (dataToTag# x)--instance SingToInt PingPong where-  singToInt x = I# (dataToTag# x)--instance Protocol Role PingPong where-  type Done Client = End-  type Done Server = End-  data Msg Role PingPong from send recv where-    Ping :: Int -> Msg Role PingPong (S0 True) '(Client, S1) '(Server, S1)-    Pong :: Int -> Msg Role PingPong S1 '(Server, S0 s) '(Client, S0 s)-    Stop :: Msg Role PingPong (S0 False) '(Client, End) '(Server, End)--encodeMsg :: Encode Role PingPong (AnyMsg Role PingPong)-encodeMsg = Encode $ \x -> case x of-  Ping{} -> AnyMsg x-  Pong{} -> AnyMsg x-  Stop{} -> AnyMsg x--decodeMsg-  :: DecodeStep-      (AnyMsg Role PingPong)-      CodecFailure-      (AnyMsg Role PingPong)-decodeMsg =-  DecodePartial $ \case-    Nothing -> DecodeFail (CodecFailure "expected more data")-    Just anyMsg -> DecodeDone anyMsg Nothing--data Choice :: PingPong -> Type where-  ST :: Choice (S0 True)-  SF :: Choice (S0 False)--choice :: (Monad m) => Int -> Peer Role PingPong Client m Choice (S0 s)-choice i =-  if i <= 5-    then LiftM $ pure (ireturn ST)-    else LiftM $ pure (ireturn SF)--clientPeer-  :: (Monad m) => Int -> Peer Role PingPong Client m (At () (Done Client)) (S0 s)-clientPeer i = I.do-  res <- choice i-  case res of-    ST -> I.do-      yield (Ping i)-      Recv (Pong i') <- await-      clientPeer i'-    SF -> yield Stop--serverPeer-  :: (Monad m) => Peer Role PingPong Server m (At () (Done Server)) (S0 s)-serverPeer = I.do-  Recv msg <- await-  case msg of-    Ping i -> I.do-      yield (Pong (i + 1))-      serverPeer-    Stop -> returnAt ()--mvarsAsChannel-  :: (MonadSTM m)-  => TMVar m a-  -> TMVar m a-  -> Channel m a-mvarsAsChannel bufferRead bufferWrite =-  Channel{send, recv}- where-  send x = atomically (putTMVar bufferWrite x)-  recv = atomically (Just <$> takeTMVar bufferRead)--myTracer :: (MonadSay m) => String -> Tracer Role PingPong m-myTracer st v = say (st <> show v)--instance Show (AnyMsg Role PingPong) where-  show (AnyMsg msg) = case msg of-    Ping i -> "Ping " <> show i-    Pong i -> "Pong " <> show i-    Stop -> "Stop"--runAll :: forall m. (Monad m, MonadDelay m, MonadSTM m, MonadSay m, MonadFork m, MonadThrow m) => m ()-runAll = do-  clientTMVar <- newEmptyTMVarIO @m @(AnyMsg Role PingPong)-  serverTMVar <- newEmptyTMVarIO @m @(AnyMsg Role PingPong)-  let clientChannel = mvarsAsChannel @m clientTMVar serverTMVar-      serverChannel = mvarsAsChannel @m serverTMVar clientTMVar-      sendFun bufferWrite x = atomically (putTMVar bufferWrite x)-      sendToRole =-        IntMap.fromList-          [ (singToInt SServer, sendFun serverTMVar)-          , (singToInt SClient, sendFun clientTMVar)-          ]-  clientTvar <- newTVarIO IntMap.empty-  serverTvar <- newTVarIO IntMap.empty-  let clientDriver = driverSimple (myTracer "client: ") encodeMsg sendToRole clientTvar id-      serverDriver = driverSimple (myTracer "server: ") encodeMsg sendToRole serverTvar id-  -- fork client decode thread-  forkIO $ decodeLoop (myTracer "client: ") Nothing (Decode decodeMsg) clientChannel clientTvar-  -- fork server decode thread-  forkIO $ decodeLoop (myTracer "server: ") Nothing (Decode decodeMsg) serverChannel serverTvar-  -- fork server Peer thread-  forkIO $ void $ runPeerWithDriver serverDriver serverPeer-  -- run client Peer-  void $ runPeerWithDriver clientDriver (clientPeer 0)
typed-session.cabal view
@@ -20,7 +20,7 @@ -- PVP summary:     +-+------- breaking API changes --                  | | +----- non-breaking API additions --                  | | | +--- code changes with no API change-version:            0.1.3.0+version:            0.2.0.0  -- A short (one-line) description of the package. synopsis: typed session framework@@ -95,14 +95,10 @@     default-language: Haskell2010      -- Modules included in this executable, other than Main.-    other-modules: Book-                 , Book1-                 , Book2-                 , Book3.Type+    other-modules: Book3.Type                  , Book3.Protocol                  , Book3.Peer                  , Book3.Main-                 , PingPong      -- LANGUAGE extensions used by modules in this package.     -- other-extensions: