{-# LANGUAGE DataKinds #-} {-# LANGUAGE EmptyCase #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RebindableSyntax #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-} {-# OPTIONS_GHC -fno-warn-unused-top-binds #-} -- | -- Module : Control.Protocol.Example -- Copyright : (c) Evgeny Poberezkin -- License : BSD3 -- -- Maintainer : evgeny@poberezkin.com -- Stability : experimental -- Portability : non-portable -- -- Example command and protocol definition. module Control.Protocol.Example ( MyProtocol, MyCommand (..), scenario, Party (..), ChannelState (..), ) where import Control.Protocol import Control.XMonad.Do import Data.Singletons.TH import Prelude hiding ((>>), (>>=)) $( singletons [d| data Party = Recipient | Broker | Sender deriving (Show, Eq) |] ) -- | Example type defining the possible resource states, in this case some communication channel. data ChannelState = None | Ready | Busy deriving (Show, Eq) -- | Example command data type of kind @'Command' 'Party' 'ChannelState'@. data MyCommand :: Command Party ChannelState where Create :: MyCommand '(Recipient, None, Ready) '(Broker, None, Ready) () Notify :: MyCommand '(Recipient, Ready, Ready) '(Sender, None, Ready) () Send :: String -> MyCommand '(Sender, Ready, Ready) '(Broker, Ready, Busy) () Forward :: MyCommand '(Broker, Busy, Ready) '(Recipient, Ready, Ready) String -- | Example protocol type. type MyProtocol = Protocol MyCommand '[Recipient, Broker, Sender] r :: Sing Recipient r = SRecipient b :: Sing Broker b = SBroker s :: Sing Sender s = SSender -- | Example protocol scenario. -- -- If you modify this scenario to 'Send' before channel is 'Create'd or -- to 'Send' two messages in a row without forwarding them, the scenario will not compile. scenario :: String -> MyProtocol '[None, None, None] '[Ready, Ready, Ready] String scenario str = do r ->: b $ Create r ->: s $ Notify s ->: b $ Send str -- s ->: b $ Send str b ->: r $ Forward