{-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeOperators #-} {-| Module: Control.Remote.Monad.Packet.Applicative Copyright: (C) 2016, The University of Kansas License: BSD-style (see the file LICENSE) Maintainer: Andy Gill Stability: Alpha Portability: GHC -} module Control.Remote.Monad.Packet.Applicative ( -- * The remote applicative ApplicativePacket(..) -- * Utility , superCommand ) where import Control.Monad.Trans.Class import Control.Monad.Trans.State.Strict import qualified Control.Remote.Monad.Packet.Strong as Strong import Control.Natural -- | A Remote Applicative, that can encode both commands and procedures, bundled together. data ApplicativePacket (c :: *) (p :: * -> *) (a :: *) where Command :: ApplicativePacket c p b -> c -> ApplicativePacket c p b Procedure :: ApplicativePacket c p (a -> b) -> p a -> ApplicativePacket c p b Pure :: a -> ApplicativePacket c p a instance Functor (ApplicativePacket c p) where fmap f (Command g c) = Command (fmap f g) c fmap f (Procedure g p) = Procedure (fmap (f .) g) p fmap f (Pure a) = Pure (f a) instance Applicative (ApplicativePacket c p) where pure a = Pure a (Pure f) <*> m = fmap f m (Command g c) <*> (Pure a) = Command (fmap (\ f -> f a) g) c (Procedure g p) <*> (Pure a) = Procedure (fmap (\ f a1 -> f a1 a) g) p m <*> (Command g2 c2) = Command (m <*> g2) c2 m <*> (Procedure g2 p2) = Procedure (fmap (.) m <*> g2) p2 -- | This simulates a 'ApplicativePacket', to see if it only contains commands, and if so, -- returns the static result. The commands still need executed. The term super-command -- is a play on Hughes' super-combinator terminology. superCommand :: ApplicativePacket c p a -> Maybe a superCommand (Pure a) = Just a superCommand (Command g _) = superCommand g superCommand (Procedure _ _) = Nothing