packages feed

distributed-process 0.2.3.0 → 0.3.0

raw patch · 16 files changed

+457/−1110 lines, 16 filesdep +distributed-staticdep +rank1dynamicdep +sybPVP ok

version bump matches the API change (PVP)

Dependencies added: distributed-static, rank1dynamic, syb

API changes (from Hackage documentation)

- Control.Distributed.Process.Closure: cpBind :: (Typeable a, Typeable b) => Closure (Process a) -> Closure (a -> Process b) -> Closure (Process b)
- Control.Distributed.Process.Closure: cpCancelL :: Typeable a => CP ((), a) a
- Control.Distributed.Process.Closure: cpCancelR :: Typeable a => CP (a, ()) a
- Control.Distributed.Process.Closure: cpComp :: (Typeable a, Typeable b, Typeable c) => CP a b -> CP b c -> CP a c
- Control.Distributed.Process.Closure: cpElim :: Typeable a => CP () a -> Closure (Process a)
- Control.Distributed.Process.Closure: cpFirst :: (Typeable a, Typeable b, Typeable c) => CP a b -> CP (a, c) (b, c)
- Control.Distributed.Process.Closure: cpId :: Typeable a => CP a a
- Control.Distributed.Process.Closure: cpIntro :: (Typeable a, Typeable b) => Closure (Process b) -> Closure (a -> Process b)
- Control.Distributed.Process.Closure: cpReturn :: Serializable a => Static (SerializableDict a) -> a -> Closure (Process a)
- Control.Distributed.Process.Closure: cpSecond :: (Typeable a, Typeable b, Typeable c) => CP a b -> CP (c, a) (c, b)
- Control.Distributed.Process.Closure: cpSeq :: Closure (Process ()) -> Closure (Process ()) -> Closure (Process ())
- Control.Distributed.Process.Closure: cpSplit :: (Typeable a, Typeable b, Typeable c, Typeable d) => CP a c -> CP b d -> CP (a, b) (c, d)
- Control.Distributed.Process.Closure: staticApply :: Static (a -> b) -> Static a -> Static b
- Control.Distributed.Process.Closure: staticClosure :: Typeable a => Static a -> Closure a
- Control.Distributed.Process.Closure: staticCompose :: (Typeable a, Typeable b, Typeable c) => Static (b -> c) -> Static (a -> b) -> Static (a -> c)
- Control.Distributed.Process.Closure: staticConst :: (Typeable a, Typeable b) => Static (a -> b -> a)
- Control.Distributed.Process.Closure: staticDuplicate :: Typeable a => Static a -> Static (Static a)
- Control.Distributed.Process.Closure: staticFirst :: (Typeable a, Typeable b, Typeable c) => Static ((a -> b) -> (a, c) -> (b, c))
- Control.Distributed.Process.Closure: staticFlip :: (Typeable a, Typeable b, Typeable c) => Static (a -> b -> c) -> Static (b -> a -> c)
- Control.Distributed.Process.Closure: staticFst :: (Typeable a, Typeable b) => Static ((a, b) -> a)
- Control.Distributed.Process.Closure: staticSecond :: (Typeable a, Typeable b, Typeable c) => Static ((a -> b) -> (c, a) -> (c, b))
- Control.Distributed.Process.Closure: staticSnd :: (Typeable a, Typeable b) => Static ((a, b) -> b)
- Control.Distributed.Process.Closure: staticSplit :: (Typeable a, Typeable b, Typeable c, Typeable d) => Static (a -> c) -> Static (b -> d) -> Static ((a, b) -> (c, d))
- Control.Distributed.Process.Closure: staticUnit :: Static ()
- Control.Distributed.Process.Closure: toClosure :: Serializable a => Static (SerializableDict a) -> a -> Closure a
- Control.Distributed.Process.Internal.Closure.CP: __remoteTable :: RemoteTable -> RemoteTable
- Control.Distributed.Process.Internal.Closure.CP: cpBind :: (Typeable a, Typeable b) => Closure (Process a) -> Closure (a -> Process b) -> Closure (Process b)
- Control.Distributed.Process.Internal.Closure.CP: cpCancelL :: Typeable a => CP ((), a) a
- Control.Distributed.Process.Internal.Closure.CP: cpCancelR :: Typeable a => CP (a, ()) a
- Control.Distributed.Process.Internal.Closure.CP: cpComp :: (Typeable a, Typeable b, Typeable c) => CP a b -> CP b c -> CP a c
- Control.Distributed.Process.Internal.Closure.CP: cpElim :: Typeable a => CP () a -> Closure (Process a)
- Control.Distributed.Process.Internal.Closure.CP: cpExpect :: Typeable a => Static (SerializableDict a) -> Closure (Process a)
- Control.Distributed.Process.Internal.Closure.CP: cpFirst :: (Typeable a, Typeable b, Typeable c) => CP a b -> CP (a, c) (b, c)
- Control.Distributed.Process.Internal.Closure.CP: cpId :: Typeable a => CP a a
- Control.Distributed.Process.Internal.Closure.CP: cpIntro :: (Typeable a, Typeable b) => Closure (Process b) -> Closure (a -> Process b)
- Control.Distributed.Process.Internal.Closure.CP: cpLink :: ProcessId -> Closure (Process ())
- Control.Distributed.Process.Internal.Closure.CP: cpNewChan :: Typeable a => Static (SerializableDict a) -> Closure (Process (SendPort a, ReceivePort a))
- Control.Distributed.Process.Internal.Closure.CP: cpReturn :: Serializable a => Static (SerializableDict a) -> a -> Closure (Process a)
- Control.Distributed.Process.Internal.Closure.CP: cpSecond :: (Typeable a, Typeable b, Typeable c) => CP a b -> CP (c, a) (c, b)
- Control.Distributed.Process.Internal.Closure.CP: cpSend :: Typeable a => Static (SerializableDict a) -> ProcessId -> Closure (a -> Process ())
- Control.Distributed.Process.Internal.Closure.CP: cpSeq :: Closure (Process ()) -> Closure (Process ()) -> Closure (Process ())
- Control.Distributed.Process.Internal.Closure.CP: cpSplit :: (Typeable a, Typeable b, Typeable c, Typeable d) => CP a c -> CP b d -> CP (a, b) (c, d)
- Control.Distributed.Process.Internal.Closure.CP: cpUnlink :: ProcessId -> Closure (Process ())
- Control.Distributed.Process.Internal.Closure.CP: type CP a b = Closure (a -> Process b)
- Control.Distributed.Process.Internal.Closure.MkClosure: mkClosure :: Name -> Q Exp
- Control.Distributed.Process.Internal.Closure.Resolution: resolveClosure :: RemoteTable -> Static a -> ByteString -> Maybe Dynamic
- Control.Distributed.Process.Internal.Closure.Static: __remoteTable :: RemoteTable -> RemoteTable
- Control.Distributed.Process.Internal.Closure.Static: sdictProcessId :: Static (SerializableDict ProcessId)
- Control.Distributed.Process.Internal.Closure.Static: sdictSendPort :: Typeable a => Static (SerializableDict a) -> Static (SerializableDict (SendPort a))
- Control.Distributed.Process.Internal.Closure.Static: sdictUnit :: Static (SerializableDict ())
- Control.Distributed.Process.Internal.Closure.Static: staticClosure :: Typeable a => Static a -> Closure a
- Control.Distributed.Process.Internal.Closure.Static: staticCompose :: (Typeable a, Typeable b, Typeable c) => Static (b -> c) -> Static (a -> b) -> Static (a -> c)
- Control.Distributed.Process.Internal.Closure.Static: staticConst :: (Typeable a, Typeable b) => Static (a -> b -> a)
- Control.Distributed.Process.Internal.Closure.Static: staticDecode :: Typeable a => Static (SerializableDict a) -> Static (ByteString -> a)
- Control.Distributed.Process.Internal.Closure.Static: staticFirst :: (Typeable a, Typeable b, Typeable c) => Static ((a -> b) -> (a, c) -> (b, c))
- Control.Distributed.Process.Internal.Closure.Static: staticFlip :: (Typeable a, Typeable b, Typeable c) => Static (a -> b -> c) -> Static (b -> a -> c)
- Control.Distributed.Process.Internal.Closure.Static: staticFst :: (Typeable a, Typeable b) => Static ((a, b) -> a)
- Control.Distributed.Process.Internal.Closure.Static: staticSecond :: (Typeable a, Typeable b, Typeable c) => Static ((a -> b) -> (c, a) -> (c, b))
- Control.Distributed.Process.Internal.Closure.Static: staticSnd :: (Typeable a, Typeable b) => Static ((a, b) -> b)
- Control.Distributed.Process.Internal.Closure.Static: staticSplit :: (Typeable a, Typeable b, Typeable c, Typeable d) => Static (a -> c) -> Static (b -> d) -> Static ((a, b) -> (c, d))
- Control.Distributed.Process.Internal.Closure.Static: staticUnit :: Static ()
- Control.Distributed.Process.Internal.Closure.Static: toClosure :: Serializable a => Static (SerializableDict a) -> a -> Closure a
- Control.Distributed.Process.Internal.Dynamic: Dynamic :: TypeRep -> Any -> Dynamic
- Control.Distributed.Process.Internal.Dynamic: data Dynamic
- Control.Distributed.Process.Internal.Dynamic: dynApp :: Dynamic -> Dynamic -> Dynamic
- Control.Distributed.Process.Internal.Dynamic: dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
- Control.Distributed.Process.Internal.Dynamic: dynBind :: TyCon -> (forall a b. m a -> (a -> m b) -> m b) -> Dynamic -> Dynamic -> Maybe Dynamic
- Control.Distributed.Process.Internal.Dynamic: dynBind' :: TyCon -> (forall a b. m a -> (a -> m b) -> m b) -> Dynamic -> Dynamic -> Dynamic
- Control.Distributed.Process.Internal.Dynamic: dynKleisli :: TyCon -> (forall a b c. (a -> m b) -> (b -> m c) -> a -> m c) -> Dynamic -> Dynamic -> Maybe Dynamic
- Control.Distributed.Process.Internal.Dynamic: dynTypeRep :: Dynamic -> TypeRep
- Control.Distributed.Process.Internal.Dynamic: fromDyn :: Typeable a => Dynamic -> a -> a
- Control.Distributed.Process.Internal.Dynamic: fromDynamic :: Typeable a => Dynamic -> Maybe a
- Control.Distributed.Process.Internal.Dynamic: instance Show Dynamic
- Control.Distributed.Process.Internal.Dynamic: instance Typeable Dynamic
- Control.Distributed.Process.Internal.Dynamic: toDyn :: Typeable a => a -> Dynamic
- Control.Distributed.Process.Internal.Dynamic: unsafeCoerce# :: a -> b
- Control.Distributed.Process.Internal.TypeRep: compareTypeRep :: TypeRep -> TypeRep -> Bool
- Control.Distributed.Process.Internal.TypeRep: instance Binary Fingerprint
- Control.Distributed.Process.Internal.TypeRep: instance Binary TyCon
- Control.Distributed.Process.Internal.TypeRep: instance Binary TypeRep
- Control.Distributed.Process.Internal.Types: Closure :: (Static (ByteString -> a)) -> ByteString -> Closure a
- Control.Distributed.Process.Internal.Types: RemoteTable :: Map String Dynamic -> RemoteTable
- Control.Distributed.Process.Internal.Types: SerializableDict :: SerializableDict a
- Control.Distributed.Process.Internal.Types: Static :: StaticLabel -> Static a
- Control.Distributed.Process.Internal.Types: StaticApply :: StaticLabel -> StaticLabel -> StaticLabel
- Control.Distributed.Process.Internal.Types: StaticDuplicate :: StaticLabel -> TypeRep -> StaticLabel
- Control.Distributed.Process.Internal.Types: StaticLabel :: String -> TypeRep -> StaticLabel
- Control.Distributed.Process.Internal.Types: _remoteTableLabels :: RemoteTable -> Map String Dynamic
- Control.Distributed.Process.Internal.Types: data Closure a
- Control.Distributed.Process.Internal.Types: data RemoteTable
- Control.Distributed.Process.Internal.Types: data SerializableDict a
- Control.Distributed.Process.Internal.Types: data StaticLabel
- Control.Distributed.Process.Internal.Types: instance Show (Closure a)
- Control.Distributed.Process.Internal.Types: instance Show (Static a)
- Control.Distributed.Process.Internal.Types: instance Show StaticLabel
- Control.Distributed.Process.Internal.Types: instance Typeable StaticLabel
- Control.Distributed.Process.Internal.Types: instance Typeable a => Binary (Closure a)
- Control.Distributed.Process.Internal.Types: instance Typeable a => Binary (Static a)
- Control.Distributed.Process.Internal.Types: instance Typeable1 Closure
- Control.Distributed.Process.Internal.Types: instance Typeable1 SerializableDict
- Control.Distributed.Process.Internal.Types: instance Typeable1 Static
- Control.Distributed.Process.Internal.Types: newtype Static a
- Control.Distributed.Process.Internal.Types: remoteTableLabel :: String -> Accessor RemoteTable (Maybe Dynamic)
- Control.Distributed.Process.Internal.Types: remoteTableLabels :: Accessor RemoteTable (Map String Dynamic)
- Control.Distributed.Process.Internal.Types: staticApply :: Static (a -> b) -> Static a -> Static b
- Control.Distributed.Process.Internal.Types: staticDuplicate :: Typeable a => Static a -> Static (Static a)
- Control.Distributed.Process.Internal.Types: staticTypeOf :: Typeable a => a -> Static a
- Control.Distributed.Process.Internal.Types: typeOfStaticLabel :: StaticLabel -> TypeRep
+ Control.Distributed.Process.Closure: bindCP :: (Typeable a, Typeable b) => Closure (Process a) -> CP a b -> Closure (Process b)
+ Control.Distributed.Process.Closure: idCP :: Typeable a => CP a a
+ Control.Distributed.Process.Closure: returnCP :: Serializable a => Static (SerializableDict a) -> a -> Closure (Process a)
+ Control.Distributed.Process.Closure: seqCP :: (Typeable a, Typeable b) => Closure (Process a) -> Closure (Process b) -> Closure (Process b)
+ Control.Distributed.Process.Closure: splitCP :: (Typeable a, Typeable b, Typeable c, Typeable d) => CP a c -> CP b d -> CP (a, b) (c, d)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: bindCP :: (Typeable a, Typeable b) => Closure (Process a) -> CP a b -> Closure (Process b)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: cpExpect :: Typeable a => Static (SerializableDict a) -> Closure (Process a)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: cpLink :: ProcessId -> Closure (Process ())
+ Control.Distributed.Process.Internal.Closure.BuiltIn: cpNewChan :: Typeable a => Static (SerializableDict a) -> Closure (Process (SendPort a, ReceivePort a))
+ Control.Distributed.Process.Internal.Closure.BuiltIn: cpSend :: Typeable a => Static (SerializableDict a) -> ProcessId -> CP a ()
+ Control.Distributed.Process.Internal.Closure.BuiltIn: cpUnlink :: ProcessId -> Closure (Process ())
+ Control.Distributed.Process.Internal.Closure.BuiltIn: idCP :: Typeable a => CP a a
+ Control.Distributed.Process.Internal.Closure.BuiltIn: remoteTable :: RemoteTable -> RemoteTable
+ Control.Distributed.Process.Internal.Closure.BuiltIn: returnCP :: Serializable a => Static (SerializableDict a) -> a -> Closure (Process a)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: sdictProcessId :: Static (SerializableDict ProcessId)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: sdictSendPort :: Typeable a => Static (SerializableDict a) -> Static (SerializableDict (SendPort a))
+ Control.Distributed.Process.Internal.Closure.BuiltIn: sdictUnit :: Static (SerializableDict ())
+ Control.Distributed.Process.Internal.Closure.BuiltIn: seqCP :: (Typeable a, Typeable b) => Closure (Process a) -> Closure (Process b) -> Closure (Process b)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: sndStatic :: Static ((a, b) -> b)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: splitCP :: (Typeable a, Typeable b, Typeable c, Typeable d) => CP a c -> CP b d -> CP (a, b) (c, d)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: staticDecode :: Typeable a => Static (SerializableDict a) -> Static (ByteString -> a)
+ Control.Distributed.Process.Internal.Closure.BuiltIn: type CP a b = Closure (a -> Process b)
+ Control.Distributed.Process.Internal.Closure.TH: mkClosure :: Name -> Q Exp
+ Control.Distributed.Process.Serializable: SerializableDict :: SerializableDict a
+ Control.Distributed.Process.Serializable: data SerializableDict a
+ Control.Distributed.Process.Serializable: instance Typeable1 SerializableDict
- Control.Distributed.Process: Closure :: (Static (ByteString -> a)) -> ByteString -> Closure a
+ Control.Distributed.Process: Closure :: Static (ByteString -> a) -> ByteString -> Closure a
- Control.Distributed.Process: data Closure a
+ Control.Distributed.Process: data Closure a :: * -> *
- Control.Distributed.Process: data RemoteTable
+ Control.Distributed.Process: data RemoteTable :: *
- Control.Distributed.Process: data Static a
+ Control.Distributed.Process: data Static a :: * -> *
- Control.Distributed.Process.Closure: cpSend :: Typeable a => Static (SerializableDict a) -> ProcessId -> Closure (a -> Process ())
+ Control.Distributed.Process.Closure: cpSend :: Typeable a => Static (SerializableDict a) -> ProcessId -> CP a ()

Files

distributed-process.cabal view
@@ -1,5 +1,5 @@ Name:          distributed-process -Version:       0.2.3.0+Version:       0.3.0 Cabal-Version: >=1.8 Build-Type:    Simple License:       BSD3 @@ -43,21 +43,19 @@                      time >= 1.2 && < 1.5,                      template-haskell >= 2.6 && < 2.8,                      random >= 1.0 && < 1.1,-                     ghc-prim >= 0.2 && < 0.3+                     ghc-prim >= 0.2 && < 0.3,+                     distributed-static >= 0.1 && < 0.2,+                     rank1dynamic >= 0.1 && < 0.2,+                     syb >= 0.3 && < 0.4   Exposed-modules:   Control.Distributed.Process,                      Control.Distributed.Process.Serializable,                      Control.Distributed.Process.Closure,                      Control.Distributed.Process.Node,                      Control.Distributed.Process.Internal.Primitives,                      Control.Distributed.Process.Internal.CQueue,-                     Control.Distributed.Process.Internal.Dynamic,-                     Control.Distributed.Process.Internal.TypeRep,                      Control.Distributed.Process.Internal.Types,-                     Control.Distributed.Process.Internal.Closure.Static,-                     Control.Distributed.Process.Internal.Closure.MkClosure,-                     Control.Distributed.Process.Internal.Closure.CP,                      Control.Distributed.Process.Internal.Closure.TH,-                     Control.Distributed.Process.Internal.Closure.Resolution,+                     Control.Distributed.Process.Internal.Closure.BuiltIn,                      Control.Distributed.Process.Internal.Node   Extensions:        RankNTypes,                      ScopedTypeVariables,@@ -67,7 +65,6 @@                      GADTs,                      GeneralizedNewtypeDeriving,                      DeriveDataTypeable,-                     TemplateHaskell,                      CPP   ghc-options:       -Wall   HS-Source-Dirs:    src@@ -90,7 +87,9 @@                      template-haskell >= 2.6 && < 2.8,                      random >= 1.0 && < 1.1,                      ghc-prim >= 0.2 && < 0.3,-                     ansi-terminal >= 0.5 && < 0.6+                     ansi-terminal >= 0.5 && < 0.6,+                     distributed-static >= 0.1 && < 0.2,+                     rank1dynamic >= 0.1 && < 0.2   Extensions:        RankNTypes,                      ScopedTypeVariables,                      FlexibleInstances,@@ -99,7 +98,6 @@                      GADTs,                      GeneralizedNewtypeDeriving,                      DeriveDataTypeable,-                     TemplateHaskell,                      CPP   ghc-options:       -Wall -threaded -rtsopts -with-rtsopts=-N -fno-warn-unused-do-bind    HS-Source-Dirs:    tests src@@ -122,7 +120,10 @@                      template-haskell >= 2.6 && < 2.8,                      random >= 1.0 && < 1.1,                      ghc-prim >= 0.2 && < 0.3,-                     ansi-terminal >= 0.5 && < 0.6+                     ansi-terminal >= 0.5 && < 0.6,+                     distributed-static >= 0.1 && < 0.2,+                     rank1dynamic >= 0.1 && < 0.2,+                     syb >= 0.3 && < 0.4   Other-modules:     TestAuxiliary   Extensions:        RankNTypes,                      ScopedTypeVariables,
src/Control/Distributed/Process.hs view
@@ -100,7 +100,6 @@   , spawnChannelLocal   ) where - #if ! MIN_VERSION_base(4,6,0) import Prelude hiding (catch) #endif@@ -109,13 +108,15 @@ import Control.Monad.IO.Class (liftIO) import Control.Applicative ((<$>)) import Control.Monad.Reader (ask)+import Control.Distributed.Static +  ( Closure(..)+  , Static+  , RemoteTable+  ) import Control.Distributed.Process.Internal.Types -  ( RemoteTable-  , NodeId(..)+  ( NodeId(..)   , ProcessId(..)   , Process(..)-  , Closure(..)-  , Static   , MonitorRef(..)   , ProcessMonitorNotification(..)   , NodeMonitorNotification(..)@@ -126,29 +127,28 @@   , DiedReason(..)   , SpawnRef(..)   , DidSpawn(..)-  , Closure(..)   , SendPort(..)   , ReceivePort(..)-  , SerializableDict(..)   , SendPortId(..)   , WhereIsReply(..)   , LocalProcess(processNode)   )-import Control.Distributed.Process.Internal.Closure.CP-  ( cpSeq-  , cpBind-  , cpSend -  , cpExpect+import Control.Distributed.Process.Serializable (SerializableDict)+import Control.Distributed.Process.Internal.Closure.BuiltIn+  ( sdictUnit +  , sdictSendPort+  , sndStatic+  , idCP+  , seqCP +  , bindCP +  , splitCP   , cpLink   , cpUnlink+  , cpExpect+  , cpSend   , cpNewChan-  , cpCancelL-  , cpSplit   )-import Control.Distributed.Process.Internal.Closure.Static -  ( sdictUnit-  , sdictSendPort-  )+import Control.Distributed.Static (closureCompose, staticClosure) import Control.Distributed.Process.Internal.Primitives   ( -- Basic messaging     send @@ -289,9 +289,9 @@   -- that was already set up   mRef <- monitorNode nid   sRef <- spawnAsync nid $ cpLink us -                   `cpSeq` cpExpect sdictUnit -                   `cpSeq` cpUnlink us-                   `cpSeq` proc+                   `seqCP` cpExpect sdictUnit +                   `seqCP` cpUnlink us+                   `seqCP` proc   mPid <- receiveWait      [ matchIf (\(DidSpawn ref _) -> ref == sRef)               (\(DidSpawn _ pid) -> return $ Just pid)@@ -333,7 +333,7 @@ call :: Serializable a => Static (SerializableDict a) -> NodeId -> Closure (Process a) -> Process a call dict nid proc = do    us <- getSelfPid-  (_, mRef) <- spawnMonitor nid (proc `cpBind` cpSend dict us)+  (_, mRef) <- spawnMonitor nid (proc `bindCP` cpSend dict us)   -- We are guaranteed to receive the reply before the monitor notification   -- (if a reply is sent at all)   -- NOTE: This might not be true if we switch to unreliable delivery.@@ -353,7 +353,7 @@                 -> Process (ProcessId, MonitorRef) spawnSupervised nid proc = do   us   <- getSelfPid-  them <- spawn nid (cpLink us `cpSeq` proc) +  them <- spawn nid (cpLink us `seqCP` proc)    ref  <- monitor them   return (them, ref) @@ -370,10 +370,10 @@   where     go :: ProcessId -> Closure (Process ())     go pid = cpNewChan dict -           `cpBind` -             (cpSend (sdictSendPort dict) pid `cpSplit` proc)-           `cpBind`-             cpCancelL+           `bindCP` +             (cpSend (sdictSendPort dict) pid `splitCP` proc)+           `bindCP`+             (idCP `closureCompose` staticClosure sndStatic)   -------------------------------------------------------------------------------- -- Local versions of spawn                                                    --
src/Control/Distributed/Process/Closure.hs view
@@ -1,11 +1,14 @@--- | Static values and Closures+-- | /Towards Haskell in the Cloud/ (Epstein et al., Haskell Symposium 2011)+-- proposes a new type construct called 'static' that characterizes values that+-- are known statically. Cloud Haskell uses the+-- 'Control.Distributed.Static.Static' implementation from+-- "Control.Distributed.Static". That module comes with its own extensive+-- documentation, which you should read if you want to know the details.  Here+-- we explain the Template Haskell support only. -- -- [Static values] ----- /Towards Haskell in the Cloud/ (Epstein et al., Haskell Symposium 2011) --- proposes a new type construct called 'static' that characterizes values that--- are known statically. There is no support for 'static' in ghc yet, however,--- so we emulate it using Template Haskell. Given a top-level definition+-- Given a top-level (possibly polymorphic, but unqualified) definition -- -- > f :: forall a1 .. an. T -- > f = ...@@ -42,55 +45,13 @@ -- -- then you need to enable the @ScopedTypeVariables@ language extension. ----- [Dealing with type class qualifiers]--- --- Although 'mkStatic' supports polymorphic types, it does not support--- qualified types. For instance, you cannot call 'mkStatic' on------ > decode :: Serializable a => ByteString -> a------ Instead, you will need to reify the type class dictionary. Cloud Haskell--- comes with a reified version of 'Serializable':------ > data SerializableDict a where--- >   SerializableDict :: Serializable a => SerializableDict a------ Using the reified dictionary you can define --- --- > decodeDict :: SerializableDict a -> ByteString -> a--- > decodeDict SerializableDict = decode------ where 'decodeDict' is a normal (unqualified) polymorphic value and hence--- can be passed as an argument to remotable:------ > $(mkStatic 'decodeDict) :: Typeable a => Static (SerializableDict a -> ByteString -> a)------ [Composing static values]------ The version of 'static' provided by this implementation of Cloud Haskell is--- strictly more expressive than the one proposed in the paper, and additionally--- supports ------ > staticApply :: Static (a -> b) -> Static a -> Static b------ This is extremely useful. For example, Cloud Haskell comes with--- 'staticDecode' defined as ------ > staticDecode :: Typeable a => Static (SerializableDict a) -> Static (ByteString -> a)--- > staticDecode dict = $(mkStatic 'decodeDict) `staticApply` dict ------ 'staticDecode' is used when defining closures (see below), and makes--- essential use of 'staticApply'. +-- [Static serialization dictionaries] ----- Support for 'staticApply' also makes it possible to define a rich set of--- combinators on 'static' values, a number of which are provided in this--- module. +-- Some Cloud Haskell primitives require static serialization dictionaries (**): ----- [Static serialization dictionaries]+-- > call :: Serializable a => Static (SerializableDict a) -> NodeId -> Closure (Process a) -> Process a ----- Many Cloud Haskell primitives (like 'staticDecode', above) require static--- serialization dictionaries. In principle these dictionaries require nothing--- special; for instance, given some serializable type 'T' you can define +-- Given some serializable type 'T' you can define  -- -- > sdictT :: SerializableDict T -- > sdictT = SerializableDict@@ -135,33 +96,10 @@ -- -- > $(mkClosure 'f) :: T1 -> Closure T2 ----- provided that 'T1' is serializable (*).------ [Creating closures manually]------ You don't /need/ to use 'mkClosure', however.  Closures are defined exactly--- as described in /Towards Haskell in the Cloud/:--- --- > data Closure a = Closure (Static (ByteString -> a)) ByteString------ The splice @$(mkClosure 'isPrime)@ above expands to (prettified a bit): --- --- > let decoder :: Static (ByteString -> Process Bool) --- >     decoder = $(mkStatic 'isPrime) --- >             `staticCompose`  --- >               staticDecode $(functionSDict 'isPrime)--- > in Closure decoder (encode n)------ where 'staticCompose' is composition of static functions. Note that--- 'mkClosure' makes use of the static serialization dictionary --- ('functionSDict') created by 'remotable'.------ [Combinators on Closures]+-- provided that 'T1' is serializable (*) (remember to pass 'f' to 'remotable'). ----- Support for 'staticApply' (described above) also means that we can define--- combinators on Closures, and we provide a number of them in this module,--- the most important of which is 'cpBind'. Have a look at the implementation--- of 'Control.Distributed.Process.call' for an example use.+-- (You can also create closures manually--see the documentation of +-- "Control.Distributed.Static" for examples.) -- -- [Example] --@@ -211,119 +149,65 @@ --     a priori if 'T1' is serializable or not due to a bug in the Template --     Haskell libraries (<http://hackage.haskell.org/trac/ghc/ticket/7066>) ----- (**) Even though 'staticDecode' is passed an explicit serialization ---      dictionary, we still need the 'Typeable' constraint because +-- (**) Even though 'call' is passed an explicit serialization +--      dictionary, we still need the 'Serializable' constraint because  --      'Static' is not the /true/ static. If it was, we could 'unstatic' --      the dictionary and pattern match on it to bring the 'Typeable' --      instance into scope, but unless proper 'static' support is added to --      ghc we need both the type class argument and the explicit dictionary.  module Control.Distributed.Process.Closure -  ( -- * Creating static values+  ( -- * Template Haskell support for creating static values and closures      remotable   , mkStatic-    -- * Template-Haskell support for creating closures   , mkClosure   , functionSDict   , functionTDict-    -- * Primitive operations on static values-  , staticApply-  , staticDuplicate-    -- * Static functionals-  , staticConst-  , staticFlip-  , staticFst-  , staticSnd-  , staticCompose-  , staticFirst-  , staticSecond-  , staticSplit-    -- * Static constants-  , staticUnit-    -- * Creating closures-  , staticDecode-  , staticClosure-  , toClosure     -- * Serialization dictionaries (and their static versions)   , SerializableDict(..)+  , staticDecode   , sdictUnit   , sdictProcessId   , sdictSendPort-    -- * Definition of CP and the generalized arrow combinators+    -- * The CP type and associated combinators    , CP-  , cpIntro-  , cpElim-  , cpId-  , cpComp-  , cpFirst-  , cpSecond-  , cpSplit-  , cpCancelL-  , cpCancelR-    -- * Closure versions of CH primitives+  , idCP+  , splitCP+  , returnCP+  , bindCP +  , seqCP +    -- * CP versions of Cloud Haskell primitives     , cpLink   , cpUnlink   , cpSend   , cpExpect   , cpNewChan-    -- * @Closure (Process a)@ as a not-quite-monad-  , cpReturn -  , cpBind-  , cpSeq   ) where  -import Control.Distributed.Process.Internal.Types -  ( SerializableDict(..)-  , staticApply-  , staticDuplicate-  )+import Control.Distributed.Process.Serializable (SerializableDict(..)) import Control.Distributed.Process.Internal.Closure.TH    ( remotable   , mkStatic   , functionSDict   , functionTDict+  , mkClosure   )-import Control.Distributed.Process.Internal.Closure.Static-  ( -- Static functionals-    staticConst-  , staticFlip-  , staticFst-  , staticSnd-  , staticCompose-  , staticFirst-  , staticSecond-  , staticSplit-    -- Static constants-  , staticUnit-    -- Creating closures-  , staticDecode-  , staticClosure-  , toClosure-    -- Serialization dictionaries (and their static versions)+import Control.Distributed.Process.Internal.Closure.BuiltIn+  ( -- Static dictionaries and associated operations+    staticDecode   , sdictUnit   , sdictProcessId   , sdictSendPort-  )-import Control.Distributed.Process.Internal.Closure.MkClosure (mkClosure)-import Control.Distributed.Process.Internal.Closure.CP-  ( -- Definition of CP and the generalized arrow combinators-    CP-  , cpIntro-  , cpElim-  , cpId-  , cpComp-  , cpFirst-  , cpSecond-  , cpSplit-  , cpCancelL-  , cpCancelR-    -- Closure versions of CH primitives+    -- The CP type and associated combinators +  , CP+  , idCP+  , splitCP+  , returnCP+  , bindCP +  , seqCP +    -- CP versions of Cloud Haskell primitives     , cpLink   , cpUnlink   , cpSend   , cpExpect   , cpNewChan-    -- @Closure (Process a)@ as a not-quite-monad-  , cpReturn -  , cpBind-  , cpSeq   )
+ src/Control/Distributed/Process/Internal/Closure/BuiltIn.hs view
@@ -0,0 +1,237 @@+module Control.Distributed.Process.Internal.Closure.BuiltIn +  ( -- * Remote table +    remoteTable+    -- * Static dictionaries and associated operations+  , staticDecode+  , sdictUnit+  , sdictProcessId+  , sdictSendPort+    -- * Some static values+  , sndStatic+    -- * The CP type and associated combinators +  , CP+  , idCP+  , splitCP+  , returnCP+  , bindCP +  , seqCP +    -- * CP versions of Cloud Haskell primitives  +  , cpLink+  , cpUnlink+  , cpSend+  , cpExpect+  , cpNewChan+  ) where++import Data.ByteString.Lazy (ByteString)  +import Data.Binary (decode, encode)+import Data.Rank1Typeable (Typeable, ANY, ANY1, ANY2, ANY3, ANY4)+import Data.Rank1Dynamic (toDynamic)+import Control.Distributed.Static +  ( RemoteTable+  , registerStatic+  , Static+  , staticLabel+  , staticApply+  , Closure(Closure)+  , closureApplyStatic+  , closureApply+  , staticCompose+  , staticClosure+  )+import Control.Distributed.Process.Serializable +  ( SerializableDict(..)+  , Serializable+  )+import Control.Distributed.Process.Internal.Types +  ( Process+  , ProcessId+  , SendPort+  , ReceivePort+  )+import Control.Distributed.Process.Internal.Primitives +  ( link+  , unlink+  , send+  , expect+  , newChan+  )++--------------------------------------------------------------------------------+-- Remote table                                                               --+--------------------------------------------------------------------------------++remoteTable :: RemoteTable -> RemoteTable+remoteTable = +      registerStatic "$decodeDict"      (toDynamic (decodeDict       :: SerializableDict ANY -> ByteString -> ANY))+    . registerStatic "$sdictUnit"       (toDynamic (SerializableDict :: SerializableDict ()))+    . registerStatic "$sdictProcessId"  (toDynamic (SerializableDict :: SerializableDict ProcessId)) +    . registerStatic "$sdictSendPort_"  (toDynamic (sdictSendPort_   :: SerializableDict ANY -> SerializableDict (SendPort ANY)))+    . registerStatic "$returnProcess"   (toDynamic (return           :: ANY -> Process ANY))+    . registerStatic "$seqProcess"      (toDynamic ((>>)             :: Process ANY1 -> Process ANY2 -> Process ANY2))+    . registerStatic "$bindProcess"     (toDynamic ((>>=)            :: Process ANY1 -> (ANY1 -> Process ANY2) -> Process ANY2))+    . registerStatic "$decodeProcessId" (toDynamic (decode           :: ByteString -> ProcessId))+    . registerStatic "$link"            (toDynamic link)+    . registerStatic "$unlink"          (toDynamic unlink)+    . registerStatic "$sendDict"        (toDynamic (sendDict         :: SerializableDict ANY -> ProcessId -> ANY -> Process ()))+    . registerStatic "$expectDict"      (toDynamic (expectDict       :: SerializableDict ANY -> Process ANY))+    . registerStatic "$newChanDict"     (toDynamic (newChanDict      :: SerializableDict ANY -> Process (SendPort ANY, ReceivePort ANY)))+    . registerStatic "$cpSplit"         (toDynamic (cpSplit          :: (ANY1 -> Process ANY3) -> (ANY2 -> Process ANY4) -> (ANY1, ANY2) -> Process (ANY3, ANY4)))+    . registerStatic "$snd"             (toDynamic (snd              :: (ANY1, ANY2) -> ANY2))+  where+    decodeDict :: forall a. SerializableDict a -> ByteString -> a+    decodeDict SerializableDict = decode++    sdictSendPort_ :: forall a. SerializableDict a -> SerializableDict (SendPort a)+    sdictSendPort_ SerializableDict = SerializableDict++    sendDict :: forall a. SerializableDict a -> ProcessId -> a -> Process ()+    sendDict SerializableDict = send++    expectDict :: forall a. SerializableDict a -> Process a+    expectDict SerializableDict = expect++    newChanDict :: forall a. SerializableDict a -> Process (SendPort a, ReceivePort a)+    newChanDict SerializableDict = newChan++    cpSplit :: forall a b c d. (a -> Process c) -> (b -> Process d) -> (a, b) -> Process (c, d)+    cpSplit f g (a, b) = do+      c <- f a+      d <- g b+      return (c, d)++--------------------------------------------------------------------------------+-- Static dictionaries and associated operations                              --+--------------------------------------------------------------------------------++-- | Static decoder, given a static serialization dictionary.+--+-- See module documentation of "Control.Distributed.Process.Closure" for an+-- example.+staticDecode :: Typeable a => Static (SerializableDict a) -> Static (ByteString -> a)+staticDecode dict = decodeDictStatic `staticApply` dict +  where+    decodeDictStatic :: Typeable a => Static (SerializableDict a -> ByteString -> a)+    decodeDictStatic = staticLabel "$decodeDict"++-- | Serialization dictionary for '()' +sdictUnit :: Static (SerializableDict ())+sdictUnit = staticLabel "$sdictUnit" ++-- | Serialization dictionary for 'ProcessId' +sdictProcessId :: Static (SerializableDict ProcessId)+sdictProcessId = staticLabel "$sdictProcessId" ++-- | Serialization dictionary for 'SendPort'+sdictSendPort :: Typeable a +              => Static (SerializableDict a) -> Static (SerializableDict (SendPort a))+sdictSendPort = staticApply (staticLabel "$sdictSendPort_") ++--------------------------------------------------------------------------------+-- Static values                                                              --+--------------------------------------------------------------------------------++sndStatic :: Static ((a, b) -> b)+sndStatic = staticLabel "$snd"++--------------------------------------------------------------------------------+-- The CP type and associated combinators                                     --+--------------------------------------------------------------------------------++-- | @CP a b@ is a process with input of type @a@ and output of type @b@+type CP a b = Closure (a -> Process b)++returnProcessStatic :: Typeable a => Static (a -> Process a)+returnProcessStatic = staticLabel "$returnProcess"++-- | 'CP' version of 'Control.Category.id' +idCP :: Typeable a => CP a a+idCP = staticClosure returnProcessStatic++-- | 'CP' version of ('Control.Arrow.***')+splitCP :: (Typeable a, Typeable b, Typeable c, Typeable d) +        => CP a c -> CP b d -> CP (a, b) (c, d)+splitCP p q = cpSplitStatic `closureApplyStatic` p `closureApply` q+  where+    cpSplitStatic :: Static ((a -> Process c) -> (b -> Process d) -> (a, b) -> Process (c, d))+    cpSplitStatic = staticLabel "$cpSplit" ++-- | 'CP' version of 'Control.Monad.return'+returnCP :: forall a. Serializable a +         => Static (SerializableDict a) -> a -> Closure (Process a)+returnCP dict x = Closure decoder (encode x)+  where+    decoder :: Static (ByteString -> Process a)+    decoder = returnProcessStatic+            `staticCompose`+              staticDecode dict++-- | 'CP' version of ('Control.Monad.>>')+seqCP :: (Typeable a, Typeable b)+      => Closure (Process a) -> Closure (Process b) -> Closure (Process b)+seqCP p q = seqProcessStatic `closureApplyStatic` p `closureApply` q +  where+    seqProcessStatic :: (Typeable a, Typeable b)+                     => Static (Process a -> Process b -> Process b)+    seqProcessStatic = staticLabel "$seqProcess"++-- | (Not quite the) 'CP' version of ('Control.Monad.>>=') +bindCP :: forall a b. (Typeable a, Typeable b)+       => Closure (Process a) -> CP a b -> Closure (Process b)+bindCP x f = bindProcessStatic `closureApplyStatic` x `closureApply` f +  where+    bindProcessStatic :: (Typeable a, Typeable b) +                      => Static (Process a -> (a -> Process b) -> Process b)+    bindProcessStatic = staticLabel "$bindProcess"++--------------------------------------------------------------------------------+-- CP versions of Cloud Haskell primitives                                    --+--------------------------------------------------------------------------------++decodeProcessIdStatic :: Static (ByteString -> ProcessId)+decodeProcessIdStatic = staticLabel "$decodeProcessId"++-- | 'CP' version of 'link'+cpLink :: ProcessId -> Closure (Process ())+cpLink = Closure (linkStatic `staticCompose` decodeProcessIdStatic) . encode +  where+    linkStatic :: Static (ProcessId -> Process ())+    linkStatic = staticLabel "$link"++-- | 'CP' version of 'unlink'+cpUnlink :: ProcessId -> Closure (Process ())+cpUnlink = Closure (unlinkStatic `staticCompose` decodeProcessIdStatic) . encode+  where+    unlinkStatic :: Static (ProcessId -> Process ())+    unlinkStatic = staticLabel "$unlink"++-- | 'CP' version of 'send'+cpSend :: forall a. Typeable a +       => Static (SerializableDict a) -> ProcessId -> CP a () +cpSend dict pid = Closure decoder (encode pid)+  where+    decoder :: Static (ByteString -> a -> Process ())+    decoder = (sendDictStatic `staticApply` dict)+            `staticCompose` +              decodeProcessIdStatic ++    sendDictStatic :: Typeable a +                   => Static (SerializableDict a -> ProcessId -> a -> Process ())+    sendDictStatic = staticLabel "$sendDict" ++-- | 'CP' version of 'expect'+cpExpect :: Typeable a => Static (SerializableDict a) -> Closure (Process a)+cpExpect dict = staticClosure (expectDictStatic `staticApply` dict)+  where+    expectDictStatic :: Typeable a => Static (SerializableDict a -> Process a)+    expectDictStatic = staticLabel "$expectDict"++-- | 'CP' version of 'newChan'+cpNewChan :: Typeable a +          => Static (SerializableDict a) +          -> Closure (Process (SendPort a, ReceivePort a))+cpNewChan dict = staticClosure (newChanDictStatic `staticApply` dict)+  where+    newChanDictStatic :: Typeable a +                      => Static (SerializableDict a -> Process (SendPort a, ReceivePort a))+    newChanDictStatic = staticLabel "$newChanDict"                  
− src/Control/Distributed/Process/Internal/Closure/CP.hs
@@ -1,330 +0,0 @@--- | Combinator for process closures -{-# LANGUAGE MagicHash #-}-module Control.Distributed.Process.Internal.Closure.CP-  ( -- * Definition of CP and the generalized arrow combinators-    CP-  , cpIntro-  , cpElim-  , cpId-  , cpComp-  , cpFirst-  , cpSecond-  , cpSplit-  , cpCancelL-  , cpCancelR-    -- * Closure versions of CH primitives-  , cpLink-  , cpUnlink-  , cpSend-  , cpExpect-  , cpNewChan-    -- * @Closure (Process a)@ as a not-quite-monad-  , cpReturn -  , cpBind-  , cpSeq-    -- * Runtime support-  , __remoteTable-  ) where--import Data.Binary (encode)-import Data.ByteString.Lazy (ByteString)-import Data.Typeable (Typeable, typeOf, typeRepTyCon, TyCon)-import Control.Applicative ((<$>))-import Control.Monad ((>=>))-import Control.Monad.Reader (ask)-import Control.Distributed.Process.Serializable (Serializable)-import Control.Distributed.Process.Internal.Types-  ( Closure(Closure)-  , SerializableDict(SerializableDict)-  , Static(Static)-  , Process-  , staticApply-  , staticDuplicate-  , staticTypeOf-  , typeOfStaticLabel-  , ProcessId-  , LocalNode(remoteTable)-  , LocalProcess(processNode)-  , SendPort-  , ReceivePort-  )-import Control.Distributed.Process.Internal.Primitives -  ( link-  , unlink-  , send-  , expect-  , newChan-  )-import Control.Distributed.Process.Internal.Closure.TH (remotable, mkStatic)-import Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure)-import Control.Distributed.Process.Internal.Closure.Static -  ( staticCompose-  , staticDecode-  , staticClosure-  , staticSplit-  , staticConst-  , staticUnit-  , staticFlip-  , staticFst-  , staticSnd-  , sdictProcessId-  )-import Control.Distributed.Process.Internal.Closure.MkClosure (mkClosure)-import Control.Distributed.Process.Internal.Dynamic -  ( Dynamic(Dynamic)-  , unsafeCoerce#-  , dynTypeRep-  , dynKleisli-  )-import Control.Distributed.Process.Internal.TypeRep (compareTypeRep)------------------------------------------------------------------------------------- Setup: A number of functions that we will pass to 'remotable'              ----------------------------------------------------------------------------------------- Type specializations of monadic operations on Processes ---------------------returnProcess :: a -> Process a-returnProcess = return--bindProcess :: Process a -> (a -> Process b) -> Process b-bindProcess = (>>=) --kleisliProcess :: (a -> Process b) -> (b -> Process c) -> a -> Process c-kleisliProcess = (>=>)--parJoinProcess :: Process (a -> Process b) -> a -> Process b-parJoinProcess proc a = proc >>= ($ a)------ Variations on standard or CH functions with an explicit dictionary arg ------sendDict :: SerializableDict a -> ProcessId -> a -> Process ()-sendDict SerializableDict = send--expectDict :: SerializableDict a -> Process a-expectDict SerializableDict = expect--newChanDict :: SerializableDict a -> Process (SendPort a, ReceivePort a)-newChanDict SerializableDict = newChan------ Serialization dictionaries ---------------------------------------------------- | Specialized serialization dictionary required in 'cpBind'-sdictComp :: SerializableDict (ByteString, ByteString)-sdictComp = SerializableDict------ Some specialised processes necessary to implement the combinators ------------- | Resolve a closure-unClosure :: Static a -> ByteString -> Process Dynamic-unClosure static env = do-  rtable <- remoteTable . processNode <$> ask -  case resolveClosure rtable static env of-    Nothing  -> fail "Derived.unClosure: resolveClosure failed"-    Just dyn -> return dyn---- | Remove a 'Dynamic' constructor, provided that the recorded type matches the--- type of the first static argument (the value of that argument is not used)-unDynamic :: Static a -> Process Dynamic -> Process a-unDynamic (Static label) pdyn = do-  Dynamic typ val <- pdyn-  if typ `compareTypeRep` typeOfStaticLabel label -    then return (unsafeCoerce# val)-    else fail $ "unDynamic: cannot match " -             ++ show typ-             ++ " against expected type " -             ++ show (typeOfStaticLabel label)---- | Dynamic kleisli composition------ The first argument stops remotable from trying to generate a SerializableDict--- for (Process Dynamic, Process Dynamic)-kleisliCompDyn :: () -> (Process Dynamic, Process Dynamic) -> Process Dynamic-kleisliCompDyn () (pf, pg) = do-    f <- pf -- a -> Process b-    g <- pg -- b -> Process c-    case dynKleisli tyConProcess kleisliProcess f g of-      Just dyn -> return dyn-      Nothing  -> fail $ "kleisliCompDyn: could not compose "-                      ++ show (dynTypeRep f)-                      ++ " with "-                      ++ show (dynTypeRep g)-  where-    tyConProcess :: TyCon-    tyConProcess = typeRepTyCon (typeOf (undefined :: Process ()))--cpFirstAux :: (a -> Process b) -> (a, c) -> Process (b, c)-cpFirstAux f (a, c) = f a >>= \b -> return (b, c) --cpSecondAux :: (a -> Process b) -> (c, a) -> Process (c, b)-cpSecondAux f (c, a) = f a >>= \b -> return (c, b) ------ Finally, the call to remotable ----------------------------------------------remotable [ -- Monadic operations-            'returnProcess-          , 'bindProcess-          , 'parJoinProcess-            -- CH primitives -          , 'link-          , 'unlink-            -- Explicit dictionaries-          , 'sendDict-          , 'expectDict-          , 'newChanDict-            -- Serialization dictionaries-          , 'sdictComp-            -- Specialized processes-          , 'unClosure-          , 'unDynamic-          , 'kleisliCompDyn-          , 'cpFirstAux-          , 'cpSecondAux-          ]------------------------------------------------------------------------------------- Some derived static functions                                              -------------------------------------------------------------------------------------staticUndynamic :: Typeable a => Static (Process Dynamic -> Process a)-staticUndynamic = -  $(mkStatic 'unDynamic) `staticApply` staticDuplicate (staticTypeOf (undefined :: a))--staticKleisliCompDyn :: Static ((Process Dynamic, Process Dynamic) -> Process Dynamic)-staticKleisliCompDyn = $(mkStatic 'kleisliCompDyn) `staticApply` staticUnit ------------------------------------------------------------------------------------- Definition of CP and the generalized arrow combinators                     --------------------------------------------------------------------------------------- | 'CP a b' represents the closure of a process parameterized by 'a' and--- returning 'b'. 'CP a b' forms a (restricted) generalized arrow--- (<http://www.cs.berkeley.edu/~megacz/garrows/>)-type CP a b = Closure (a -> Process b)---- | 'CP' introduction form -cpIntro :: forall a b. (Typeable a, Typeable b)-        => Closure (Process b) -> Closure (a -> Process b)-cpIntro (Closure static env) = Closure decoder env -  where-    decoder :: Static (ByteString -> a -> Process b)-    decoder = staticConst `staticCompose` static---- | 'CP' elimination form-cpElim :: forall a. Typeable a => CP () a -> Closure (Process a)-cpElim (Closure static env) = Closure decoder env-  where-    decoder :: Static (ByteString -> Process a)-    decoder = staticFlip static `staticApply` staticUnit ---- | Identity ('Closure' version of 'return')-cpId :: Typeable a => CP a a-cpId = staticClosure $(mkStatic 'returnProcess)---- | Left-to-right composition ('Closure' version of '>=>')-cpComp :: forall a b c. (Typeable a, Typeable b, Typeable c)-       => CP a b -> CP b c -> CP a c-cpComp (Closure fstatic fenv) (Closure gstatic genv) =-    Closure decoder (encode (fenv, genv))-  where-    decoder :: Static (ByteString -> a -> Process c)-    decoder = $(mkStatic 'parJoinProcess)-            `staticCompose`-              staticUndynamic-            `staticCompose`-              staticKleisliCompDyn-            `staticCompose`-              (staticUnclosure fstatic `staticSplit` staticUnclosure gstatic)-            `staticCompose`-              staticDecode $(mkStatic 'sdictComp)    ---- | First-cpFirst :: forall a b c. (Typeable a, Typeable b, Typeable c)-        => CP a b -> CP (a, c) (b, c)-cpFirst (Closure static env) = Closure decoder env-  where-    decoder :: Static (ByteString -> (a, c) -> Process (b, c))-    decoder = $(mkStatic 'cpFirstAux) `staticCompose` static---- | Second -cpSecond :: forall a b c. (Typeable a, Typeable b, Typeable c)-        => CP a b -> CP (c, a) (c, b)-cpSecond (Closure static env) = Closure decoder env-  where-    decoder :: Static (ByteString -> (c, a) -> Process (c, b))-    decoder = $(mkStatic 'cpSecondAux) `staticCompose` static---- | Split (Like 'Control.Arrow.***')-cpSplit :: (Typeable a, Typeable b, Typeable c, Typeable d)-        => CP a c -> CP b d -> CP (a, b) (c, d)-cpSplit f g = cpFirst f `cpComp` cpSecond g---- | Left cancellation-cpCancelL :: Typeable a => CP ((), a) a--- Closure (((), a) -> Process a)-cpCancelL = staticClosure ($(mkStatic 'returnProcess) `staticCompose` staticSnd) ---- | Right cancellation-cpCancelR :: Typeable a => CP (a, ()) a-cpCancelR = staticClosure ($(mkStatic 'returnProcess) `staticCompose` staticFst)------------------------------------------------------------------------------------- Closure versions of CH primitives                                          --------------------------------------------------------------------------------------- | Closure version of 'link'-cpLink :: ProcessId -> Closure (Process ())-cpLink = $(mkClosure 'link)---- | Closure version of 'unlink'-cpUnlink :: ProcessId -> Closure (Process ())-cpUnlink = $(mkClosure 'unlink)---- | Closure version of 'send'-cpSend :: forall a. Typeable a -       => Static (SerializableDict a) -> ProcessId -> Closure (a -> Process ())-cpSend dict pid = Closure decoder (encode pid)-  where-    decoder :: Static (ByteString -> a -> Process ())-    decoder = ($(mkStatic 'sendDict) `staticApply` dict)-            `staticCompose` -              staticDecode sdictProcessId ---- | Closure version of 'expect'-cpExpect :: Typeable a => Static (SerializableDict a) -> Closure (Process a)-cpExpect dict = staticClosure ($(mkStatic 'expectDict) `staticApply` dict)---- | Closure version of 'newChan'-cpNewChan :: Typeable a -          => Static (SerializableDict a) -          -> Closure (Process (SendPort a, ReceivePort a))-cpNewChan dict = staticClosure ($(mkStatic 'newChanDict) `staticApply` dict)------------------------------------------------------------------------------------- (Closure . Process) as a not-quite-monad                                   --------------------------------------------------------------------------------------- | Not-quite-monadic 'return'-cpReturn :: forall a. Serializable a -         => Static (SerializableDict a) -> a -> Closure (Process a)-cpReturn dict x = Closure decoder (encode x)-  where-    decoder :: Static (ByteString -> Process a)-    decoder = $(mkStatic 'returnProcess) -            `staticCompose`-              staticDecode dict---staticUnclosure :: Typeable a -                => Static a -> Static (ByteString -> Process Dynamic)-staticUnclosure s = -  $(mkStatic 'unClosure) `staticApply` staticDuplicate s ---- | Not-quite-monadic bind ('>>=')-cpBind :: forall a b. (Typeable a, Typeable b)-       => Closure (Process a) -> Closure (a -> Process b) -> Closure (Process b)-cpBind x f = cpElim (cpIntro x `cpComp` f)---- | Monadic sequencing ('>>')-cpSeq :: Closure (Process ()) -> Closure (Process ()) -> Closure (Process ())-cpSeq p q = p `cpBind` cpIntro q
− src/Control/Distributed/Process/Internal/Closure/MkClosure.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}-module Control.Distributed.Process.Internal.Closure.MkClosure (mkClosure) where--import Data.Binary (encode)-import Language.Haskell.TH (Q, Exp, Name)-import Control.Distributed.Process.Internal.Types (Closure(Closure))-import Control.Distributed.Process.Internal.Closure.TH -  ( mkStatic-  , functionSDict-  )-import Control.Distributed.Process.Internal.Closure.Static -  ( staticCompose-  , staticDecode-  )---- | Create a closure------ If @f : T1 -> T2@ is a /monomorphic/ function --- then @$(mkClosure 'f) :: T1 -> Closure T2@.--- Be sure to pass 'f' to 'remotable'. -mkClosure :: Name -> Q Exp-mkClosure n = -  [|   Closure ($(mkStatic n) `staticCompose` staticDecode $(functionSDict n)) -     . encode-  |]
− src/Control/Distributed/Process/Internal/Closure/Resolution.hs
@@ -1,34 +0,0 @@-{-# LANGUAGE MagicHash #-}-module Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure) where--import Data.Accessor ((^.))-import Data.ByteString.Lazy (ByteString)-import Control.Distributed.Process.Internal.Types-  ( RemoteTable-  , remoteTableLabel-  , Static(Static)-  , StaticLabel(..)-  )-import Control.Distributed.Process.Internal.Dynamic-  ( Dynamic(Dynamic)-  , toDyn-  , dynApply-  , unsafeCoerce#-  )-import Control.Distributed.Process.Internal.TypeRep () -- Binary instances  --resolveStatic :: RemoteTable -> Static a -> Maybe Dynamic-resolveStatic rtable (Static (StaticLabel string typ)) = do-  Dynamic _ val <- rtable ^. remoteTableLabel string-  return (Dynamic typ val)-resolveStatic rtable (Static (StaticApply static1 static2)) = do-  f <- resolveStatic rtable (Static static1)-  x <- resolveStatic rtable (Static static2)-  f `dynApply` x-resolveStatic _rtable (Static (StaticDuplicate static typ)) = -  return $ Dynamic typ (unsafeCoerce# (Static static))--resolveClosure :: RemoteTable -> Static a -> ByteString -> Maybe Dynamic-resolveClosure rtable static env = do-  decoder <- resolveStatic rtable static-  decoder `dynApply` toDyn env
− src/Control/Distributed/Process/Internal/Closure/Static.hs
@@ -1,190 +0,0 @@--- | Combinators on static values -{-# LANGUAGE MagicHash #-}-module Control.Distributed.Process.Internal.Closure.Static-  ( -- * Static functionals-    staticConst-  , staticFlip-  , staticFst-  , staticSnd-  , staticCompose-  , staticFirst-  , staticSecond-  , staticSplit-    -- * Static constants-  , staticUnit-    -- * Creating closures-  , staticDecode-  , staticClosure-  , toClosure-    -- * Serialization dictionaries (and their static versions)-  , sdictUnit-  , sdictProcessId-  , sdictSendPort-    -- * Runtime support-  , __remoteTable-  ) where--import Data.Binary (encode, decode)-import Data.ByteString.Lazy (ByteString, empty)-import Data.Typeable (Typeable)-import Control.Distributed.Process.Serializable (Serializable)-import Control.Distributed.Process.Internal.Types-  ( Closure(Closure)-  , SerializableDict(SerializableDict)-  , Static-  , staticApply-  , ProcessId-  , SendPort-  )-import Control.Distributed.Process.Internal.Closure.TH (remotable, mkStatic)-import qualified Control.Arrow as Arrow (first, second, (***))------------------------------------------------------------------------------------- Setup: A number of functions that we will pass to 'remotable'              ----------------------------------------------------------------------------------------- Functionals -----------------------------------------------------------------compose :: (b -> c) -> (a -> b) -> a -> c-compose = (.)--first :: (a -> b) -> (a, c) -> (b, c)-first = Arrow.first --second :: (a -> b) -> (c, a) -> (c, b)-second = Arrow.second--split :: (a -> b) -> (a' -> b') -> (a, a') -> (b, b')-split = (Arrow.***)------ Constants -------------------------------------------------------------------unit :: ()-unit = ()------ Variations on standard or CH functions with an explicit dictionary arg ------decodeDict :: SerializableDict a -> ByteString -> a-decodeDict SerializableDict = decode------ Serialization dictionaries --------------------------------------------------sdictUnit_ :: SerializableDict ()-sdictUnit_ = SerializableDict--sdictProcessId_ :: SerializableDict ProcessId-sdictProcessId_ = SerializableDict--sdictSendPort_ :: SerializableDict a -> SerializableDict (SendPort a)-sdictSendPort_ SerializableDict = SerializableDict------ Finally, the call to remotable ----------------------------------------------remotable [ -- Functionals (predefined)-            'const-          , 'flip-          , 'fst-          , 'snd-            -- Functionals (defined above)-          , 'compose-          , 'first-          , 'second-          , 'split-            -- Constants-          , 'unit-            -- Explicit dictionaries-          , 'decodeDict-            -- Serialization dictionaries-          , 'sdictUnit_-          , 'sdictProcessId_-          , 'sdictSendPort_-          ]------------------------------------------------------------------------------------- Static versions of the functionals                                         -- --- (We give these explicit names because they are useful outside this module) --------------------------------------------------------------------------------------- | Static version of 'const'-staticConst :: (Typeable a, Typeable b) => Static (a -> b -> a)-staticConst = $(mkStatic 'const)---- | Static version of 'flip'-staticFlip :: (Typeable a, Typeable b, Typeable c) -           => Static (a -> b -> c) -> Static (b -> a -> c)-staticFlip f = $(mkStatic 'flip) `staticApply` f           ---- | Static version of 'fst'-staticFst :: (Typeable a, Typeable b)-          => Static ((a, b) -> a)-staticFst = $(mkStatic 'fst)---- | Static version of 'snd'-staticSnd :: (Typeable a, Typeable b)-          => Static ((a, b) -> b)-staticSnd = $(mkStatic 'snd)---- | Static version of ('Prelude..')-staticCompose :: (Typeable a, Typeable b, Typeable c) -              => Static (b -> c) -> Static (a -> b) -> Static (a -> c)-staticCompose f x = $(mkStatic 'compose) `staticApply` f `staticApply` x ---- | Static version of 'Control.Arrow.first'-staticFirst :: (Typeable a, Typeable b, Typeable c)-            => Static ((a -> b) -> (a, c) -> (b, c))-staticFirst = $(mkStatic 'first)---- | Static version of 'Control.Arrow.second'-staticSecond :: (Typeable a, Typeable b, Typeable c)-             => Static ((a -> b) -> (c, a) -> (c, b))-staticSecond = $(mkStatic 'second)---- | Static version of ('Control.Arrow.***')-staticSplit :: (Typeable a, Typeable b, Typeable c, Typeable d) -            => Static (a -> c) -> Static (b -> d) -> Static ((a, b) -> (c, d))-staticSplit f g = $(mkStatic 'split) `staticApply` f `staticApply` g ------------------------------------------------------------------------------------- Constants                                                                  --------------------------------------------------------------------------------------- | Static version of '()'-staticUnit :: Static ()-staticUnit = $(mkStatic 'unit)------------------------------------------------------------------------------------- Dictionaries                                                               --------------------------------------------------------------------------------------- | Serialization dictionary for '()' -sdictUnit :: Static (SerializableDict ())-sdictUnit = $(mkStatic 'sdictUnit_)---- | Serialization dictionary for 'ProcessId' -sdictProcessId :: Static (SerializableDict ProcessId)-sdictProcessId = $(mkStatic 'sdictProcessId_)---- | Serialization dictionary for 'SendPort'-sdictSendPort :: Typeable a -              => Static (SerializableDict a) -> Static (SerializableDict (SendPort a))-sdictSendPort = staticApply $(mkStatic 'sdictSendPort_) ------------------------------------------------------------------------------------- Creating closures                                                          --------------------------------------------------------------------------------------- | Static decoder, given a static serialization dictionary.------ See module documentation of "Control.Distributed.Process.Closure" for an--- example.-staticDecode :: Typeable a => Static (SerializableDict a) -> Static (ByteString -> a)-staticDecode dict = $(mkStatic 'decodeDict) `staticApply` dict ---- | Convert a static value into a closure.-staticClosure :: forall a. Typeable a => Static a -> Closure a-staticClosure static = Closure (staticConst `staticApply` static) empty---- | Convert a serializable value into a closure.-toClosure :: forall a. Serializable a -          => Static (SerializableDict a) -> a -> Closure a-toClosure dict x = Closure (staticDecode dict) (encode x) 
src/Control/Distributed/Process/Internal/Closure/TH.hs view
@@ -1,18 +1,15 @@ -- | Template Haskell support------ (In a separate file for convenience)-{-# LANGUAGE MagicHash #-}+{-# LANGUAGE TemplateHaskell #-} module Control.Distributed.Process.Internal.Closure.TH    ( -- * User-level API     remotable   , mkStatic   , functionSDict   , functionTDict+  , mkClosure   ) where -import Prelude hiding (lookup)-import Data.Accessor ((^=))-import Data.Typeable (typeOf)+import Prelude hiding (succ, any) import Control.Applicative ((<$>)) import Language.Haskell.TH    ( -- Q monad and operations@@ -42,19 +39,27 @@   , funD   , sigD   )-import Control.Distributed.Process.Internal.Types+import Data.Binary (encode)+import Data.Generics (everywhereM, mkM, gmapM)+import Data.Rank1Dynamic (toDynamic)+import Data.Rank1Typeable+  ( Zero+  , Succ+  , TypVar+  )+import Control.Distributed.Static    ( RemoteTable-  , Static(Static)-  , StaticLabel(StaticLabel)-  , remoteTableLabel-  , SerializableDict(SerializableDict)-  , Process+  , registerStatic+  , Static+  , staticLabel+  , Closure(Closure)+  , staticCompose   )-import Control.Distributed.Process.Internal.Dynamic -  ( Dynamic(..)-  , unsafeCoerce#-  , toDyn+import Control.Distributed.Process.Internal.Types (Process)+import Control.Distributed.Process.Serializable +  ( SerializableDict(SerializableDict)   )+import Control.Distributed.Process.Internal.Closure.BuiltIn (staticDecode)  -------------------------------------------------------------------------------- -- User-level API                                                             --@@ -90,6 +95,12 @@ functionTDict :: Name -> Q Exp functionTDict = varE . tdictName +mkClosure :: Name -> Q Exp+mkClosure n = +  [|   Closure ($(mkStatic n) `staticCompose` staticDecode $(functionSDict n)) +     . encode+  |]+ -------------------------------------------------------------------------------- -- Internal (Template Haskell)                                                -- --------------------------------------------------------------------------------@@ -140,10 +151,8 @@     makeStatic origName typVars typ = do        static <- generateStatic origName typVars typ       let dyn = case typVars of -                  [] -> [| toDyn $(varE origName) |]-                  _  -> [| Dynamic (error "Polymorphic value") -                                   (unsafeCoerce# $(varE origName)) -                         |]+                  [] -> [| toDynamic $(varE origName) |]+                  _  -> [| toDynamic ($(varE origName) :: $(monomorphize typVars typ)) |]       return ( static              , [ [| registerStatic $(stringE (show origName)) $dyn |] ]              )@@ -151,15 +160,38 @@     makeDict :: Name -> Type -> Q ([Dec], [Q Exp])      makeDict dictName typ = do       sdict <- generateDict dictName typ -      let dyn = [| toDyn (SerializableDict :: SerializableDict $(return typ)) |]+      let dyn = [| toDynamic (SerializableDict :: SerializableDict $(return typ)) |]       return ( sdict              , [ [| registerStatic $(stringE (show dictName)) $dyn |] ]               )-       -registerStatic :: String -> Dynamic -> RemoteTable -> RemoteTable-registerStatic label dyn = remoteTableLabel label ^= Just dyn +-- | Turn a polymorphic type into a monomorphic type using ANY and co+monomorphize :: [TyVarBndr] -> Type -> Q Type+monomorphize tvs = +    let subst = zip (map tyVarBndrName tvs) anys +    in everywhereM (mkM (applySubst subst))+  where+    anys :: [Q Type]+    anys = map typVar (iterate succ zero) +    typVar :: Q Type -> Q Type+    typVar t = [t| TypVar $t |]++    zero :: Q Type+    zero = [t| Zero |]+    +    succ :: Q Type -> Q Type+    succ t = [t| Succ $t |]+ +    applySubst :: [(Name, Q Type)] -> Type -> Q Type+    applySubst s (VarT n) = +      case lookup n s of  +        Nothing -> return (VarT n)+        Just t  -> t+    applySubst s t = gmapM (mkM (applySubst s)) t++    + -- | Generate a static value  generateStatic :: Name -> [TyVarBndr] -> Type -> Q [Dec] generateStatic n xs typ = do@@ -170,27 +202,18 @@                   (map typeable xs)                    (staticTyp `AppT` typ)           )-      , sfnD (staticName n) -          [| Static $ StaticLabel -               $(stringE (show n)) -               (typeOf (undefined :: $(return typ)))-           |]+      , sfnD (staticName n) [| staticLabel $(stringE (show n)) |]       ]   where     typeable :: TyVarBndr -> Pred-    typeable (PlainTV v)    = ClassP (mkName "Typeable") [VarT v] -    typeable (KindedTV v _) = ClassP (mkName "Typeable") [VarT v]+    typeable tv = ClassP (mkName "Typeable") [VarT (tyVarBndrName tv)]   -- | Generate a serialization dictionary with name 'n' for type 'typ'  generateDict :: Name -> Type -> Q [Dec] generateDict n typ = do     sequence       [ sigD n $ [t| Static (SerializableDict $(return typ)) |]-      , sfnD n -         [| Static $ StaticLabel -              $(stringE (show n)) -              (typeOf (undefined :: SerializableDict $(return typ)))-          |]+      , sfnD n [| staticLabel $(stringE (show n))  |]       ]  staticName :: Name -> Name@@ -227,3 +250,8 @@ -- | Variation on 'funD' which takes a single expression to define the function sfnD :: Name -> Q Exp -> Q Dec sfnD n e = funD n [clause [] (normalB e) []] +    +-- | The name of a type variable binding occurrence    +tyVarBndrName :: TyVarBndr -> Name+tyVarBndrName (PlainTV n)    = n+tyVarBndrName (KindedTV n _) = n
− src/Control/Distributed/Process/Internal/Dynamic.hs
@@ -1,112 +0,0 @@--- | Reimplementation of Dynamic that supports dynBind------ We don't have access to the internal representation of Dynamic, otherwise--- we would not have to redefine it completely. Note that we use this only--- internally, so the incompatibility with "our" Dynamic from the standard --- Dynamic is not important.-{-# LANGUAGE MagicHash #-}-module Control.Distributed.Process.Internal.Dynamic -  ( Dynamic(..)-  , toDyn-  , fromDyn-  , fromDynamic-  , dynTypeRep-  , dynApply-  , dynApp-  , dynBind-  , dynBind'-  , dynKleisli-  , GHC.unsafeCoerce#-  ) where--import Data.Typeable -  ( Typeable-  , TypeRep-  , typeOf-  , funResultTy-  , TyCon-  , splitTyConApp-  , mkFunTy-  )-import Data.Typeable.Internal (funTc)-import qualified GHC.Prim as GHC (Any, unsafeCoerce#)-import Data.Maybe (fromMaybe)--data Dynamic = Dynamic TypeRep GHC.Any-  deriving Typeable--toDyn :: Typeable a => a -> Dynamic-toDyn x = Dynamic (typeOf x) (GHC.unsafeCoerce# x)--fromDyn :: Typeable a => Dynamic -> a -> a-fromDyn (Dynamic rep val) a =-  if rep == typeOf a -    then GHC.unsafeCoerce# val-    else a--fromDynamic :: forall a. Typeable a => Dynamic -> Maybe a-fromDynamic (Dynamic rep val) = -  if rep == typeOf (undefined :: a)-    then Just (GHC.unsafeCoerce# val)-    else Nothing--dynTypeRep :: Dynamic -> TypeRep-dynTypeRep (Dynamic t _) = t--instance Show Dynamic where-  show = show . dynTypeRep--dynApply :: Dynamic -> Dynamic -> Maybe Dynamic-dynApply (Dynamic t1 f) (Dynamic t2 x) =-  case funResultTy t1 t2 of-    Just t3 -> Just (Dynamic t3 (GHC.unsafeCoerce# f x))-    Nothing -> Nothing--dynApp :: Dynamic -> Dynamic -> Dynamic-dynApp f x = fromMaybe (error typeError) (dynApply f x)-  where-    typeError  = "Type error in dynamic application.\n" -              ++ "Can't apply function " ++ show f-              ++ " to argument " ++ show x--dynBind :: TyCon -> (forall a b. m a -> (a -> m b) -> m b) -> Dynamic -> Dynamic -> Maybe Dynamic-dynBind m bind (Dynamic t1 x) (Dynamic t2 f) = -  case splitTyConApp t1 of-    (m', [a]) | m' == m ->-      case funResultTy t2 a of-        Just mb -> Just (Dynamic mb (GHC.unsafeCoerce# bind x f))-        _  -> Nothing-    _ -> Nothing --dynBind' :: TyCon -> (forall a b. m a -> (a -> m b) -> m b) -> Dynamic -> Dynamic -> Dynamic-dynBind' m bind x f = fromMaybe (error typeError) (dynBind m bind x f)-  where-    typeError = "Type error in dynamic bind.\nCan't bind " ++ show x ++ " to " ++ show f------- | Dynamically typed Kleisli composition-dynKleisli :: TyCon  -           -> (forall a b c. (a -> m b) -> (b -> m c) -> a -> m c) -           -> Dynamic -           -> Dynamic -           -> Maybe Dynamic-dynKleisli m comp (Dynamic tf f) (Dynamic tg g) = -  case splitTyConApp tf of-    (arr1, [a, mb]) | arr1 == funTc -> -      case splitTyConApp tg of-        (arr2, [b, mc]) | arr2 == funTc ->-          case splitTyConApp mb of-            (m', [b']) | m' == m && b' == b ->-              case splitTyConApp mc of-                (m'', [_c]) | m'' == m ->-                  Just (Dynamic (mkFunTy a mc) (GHC.unsafeCoerce# comp f g))  -                _ -> -                  Nothing-            _ ->-              Nothing-        _ ->-          Nothing-    _ ->-      Nothing
src/Control/Distributed/Process/Internal/Primitives.hs view
@@ -66,14 +66,13 @@ #endif  import Data.Binary (decode)-import Data.Typeable (Typeable, typeOf) import Data.Time.Clock (getCurrentTime) import Data.Time.Format (formatTime) import System.Locale (defaultTimeLocale) import Control.Monad.Reader (ask) import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Applicative ((<$>))-import Control.Exception (Exception, throw, throwIO, SomeException)+import Control.Exception (Exception, throwIO, SomeException) import qualified Control.Exception as Ex (catch, mask) import Control.Concurrent.MVar (modifyMVar) import Control.Concurrent.Chan (writeChan)@@ -90,13 +89,15 @@ import Control.Distributed.Process.Internal.CQueue (dequeue, BlockSpec(..)) import Control.Distributed.Process.Serializable (Serializable, fingerprint) import Data.Accessor ((^.), (^:), (^=))+import Control.Distributed.Static (Closure)+import Data.Rank1Typeable (Typeable)+import qualified Control.Distributed.Static as Static (unclosure) import Control.Distributed.Process.Internal.Types    ( NodeId(..)   , ProcessId(..)   , LocalNode(..)   , LocalProcess(..)   , Process(..)-  , Closure(..)   , Message(..)   , MonitorRef(..)   , SpawnRef(..)@@ -104,7 +105,6 @@   , ProcessSignal(..)   , monitorCounter    , spawnCounter-  , Closure(..)   , SendPort(..)   , ReceivePort(..)   , channelCounter@@ -121,8 +121,6 @@   , runLocalProcess   ) import Control.Distributed.Process.Internal.Node (sendMessage, sendBinary) -import Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure)-import Control.Distributed.Process.Internal.Dynamic (fromDyn, dynTypeRep)  -------------------------------------------------------------------------------- -- Basic messaging                                                            --@@ -502,15 +500,11 @@  -- | Deserialize a closure unClosure :: forall a. Typeable a => Closure a -> Process a-unClosure (Closure static env) = do-    rtable <- remoteTable . processNode <$> ask -    case resolveClosure rtable static env of-      Nothing  -> error $ "Unregistered closure " ++ show static -      Just dyn -> return $ fromDyn dyn (throw (typeError dyn))-  where-    typeError dyn = userError $ "lookupStatic type error: " -                 ++ "cannot match " ++ show (dynTypeRep dyn) -                 ++ " against " ++ show (typeOf (undefined :: a))+unClosure closure = do+  rtable <- remoteTable . processNode <$> ask +  case Static.unclosure rtable closure of+    Left err -> fail $ "Could not resolve closure: " ++ err +    Right x  -> return x  -------------------------------------------------------------------------------- -- Auxiliary functions                                                        --
− src/Control/Distributed/Process/Internal/TypeRep.hs
@@ -1,33 +0,0 @@--- | 'Binary' instances for 'TypeRep', and 'TypeRep' equality (bug workaround)-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Control.Distributed.Process.Internal.TypeRep (compareTypeRep) where--import Control.Applicative ((<$>), (<*>))-import Data.Binary (Binary(get, put))-import Data.Typeable.Internal (TypeRep(..), TyCon(..))-import GHC.Fingerprint.Type (Fingerprint(..))--instance Binary Fingerprint where-  put (Fingerprint hi lo) = put hi >> put lo-  get = Fingerprint <$> get <*> get --instance Binary TypeRep where-  put (TypeRep fp tyCon ts) = put fp >> put tyCon >> put ts-  get = TypeRep <$> get <*> get <*> get--instance Binary TyCon where-  put (TyCon hash package modul name) = put hash >> put package >> put modul >> put name-  get = TyCon <$> get <*> get <*> get <*> get---- | Compare two type representations------ For base >= 4.6 this compares fingerprints, but older versions of base--- have a bug in the fingerprint construction --- (<http://hackage.haskell.org/trac/ghc/ticket/5962>)-compareTypeRep :: TypeRep -> TypeRep -> Bool-#if ! MIN_VERSION_base(4,6,0)-compareTypeRep (TypeRep _ con ts) (TypeRep _ con' ts') -  = con == con' && all (uncurry compareTypeRep) (zip ts ts')-#else-compareTypeRep = (==)-#endif
src/Control/Distributed/Process/Internal/Types.hs view
@@ -3,7 +3,6 @@ -- We collect all types used internally in a single module because  -- many of these data types are mutually recursive and cannot be split across -- modules.-{-# LANGUAGE MagicHash #-} module Control.Distributed.Process.Internal.Types   ( -- * Node and process identifiers      NodeId(..)@@ -24,16 +23,6 @@   , TypedChannel(..)   , SendPort(..)   , ReceivePort(..)-    -- * Closures-  , StaticLabel(..)-  , Static(..) -  , staticApply-  , staticDuplicate-  , staticTypeOf-  , typeOfStaticLabel-  , Closure(..)-  , RemoteTable(..)-  , SerializableDict(..)     -- * Messages    , Message(..)   , createMessage@@ -70,15 +59,12 @@   , channelCounter   , typedChannels   , typedChannelWithId-  , remoteTableLabels-  , remoteTableLabel   ) where  import Data.Map (Map) import Data.Int (Int32)-import Data.Maybe (fromJust)-import Data.Typeable (Typeable, TypeRep, typeOf, funResultTy)-import Data.Binary (Binary(put, get), putWord8, getWord8, encode, Put, Get)+import Data.Typeable (Typeable)+import Data.Binary (Binary(put, get), putWord8, getWord8, encode) import qualified Data.ByteString as BSS (ByteString, concat) import qualified Data.ByteString.Lazy as BSL    ( ByteString@@ -108,9 +94,11 @@   , showFingerprint   ) import Control.Distributed.Process.Internal.CQueue (CQueue)-import Control.Distributed.Process.Internal.Dynamic (Dynamic) -import Control.Distributed.Process.Internal.TypeRep (compareTypeRep) -- and Binary instances+import Control.Distributed.Static (RemoteTable, Closure) +-- import Control.Distributed.Process.Internal.Dynamic (Dynamic) +-- import Control.Distributed.Process.Internal.TypeRep (compareTypeRep) -- and Binary instances+ -------------------------------------------------------------------------------- -- Node and process identifiers                                               -- --------------------------------------------------------------------------------@@ -256,62 +244,6 @@   deriving Typeable  ----------------------------------------------------------------------------------- Closures                                                                   -------------------------------------------------------------------------------------data StaticLabel =-    StaticLabel String TypeRep-  | StaticApply StaticLabel StaticLabel-  | StaticDuplicate StaticLabel TypeRep-  deriving (Typeable, Show)---- | A static value is top-level bound or the application of two static values.------ You construct static values using 'Control.Distributed.Process.Closure.mkStatic'--- or 'staticApply'. 'Static' has a serializable instance for all /Typeable/ 'a':------ > instance Typeable a => Serializable (Static a) ------ The 'Typeable' constraint (not present in the original Cloud Haskell paper)--- makes it possible to do a type check during deserialization.-newtype Static a = Static StaticLabel -  deriving (Typeable, Show)---- | Apply two static values-staticApply :: Static (a -> b) -> Static a -> Static b-staticApply (Static f) (Static x) = Static (StaticApply f x)---- | Co-monadic 'duplicate' for static values-staticDuplicate :: forall a. Typeable a => Static a -> Static (Static a)-staticDuplicate (Static x) = -  Static (StaticDuplicate x (typeOf (undefined :: Static a)))--staticTypeOf :: forall a. Typeable a => a -> Static a -staticTypeOf _ = Static (StaticLabel "undefined" (typeOf (undefined :: a)))--typeOfStaticLabel :: StaticLabel -> TypeRep-typeOfStaticLabel (StaticLabel _ typ) -  = typ -typeOfStaticLabel (StaticApply f x) -  = fromJust $ funResultTy (typeOfStaticLabel f) (typeOfStaticLabel x)-typeOfStaticLabel (StaticDuplicate _ typ)-  = typ---- | A closure is a static value and an encoded environment-data Closure a = Closure (Static (BSL.ByteString -> a)) BSL.ByteString-  deriving (Typeable, Show)---- | Runtime dictionary for 'unstatic' lookups -data RemoteTable = RemoteTable {-    _remoteTableLabels :: Map String Dynamic -  }---- | Reification of 'Serializable' (see "Control.Distributed.Process.Closure")-data SerializableDict a where-    SerializableDict :: Serializable a => SerializableDict a-  deriving (Typeable)---------------------------------------------------------------------------------- -- Messages                                                                   -- -------------------------------------------------------------------------------- @@ -526,10 +458,6 @@       4 -> return DiedUnknownId        _ -> fail "DiedReason.get: invalid" -instance Typeable a => Binary (Closure a) where-  put (Closure static env) = put static >> put env-  get = Closure <$> get <*> get - instance Binary DidSpawn where   put (DidSpawn ref pid) = put ref >> put pid   get = DidSpawn <$> get <*> get@@ -550,29 +478,6 @@       2 -> SendPortIdentifier <$> get        _ -> fail "Identifier.get: invalid" --- We don't want StaticLabel to be its own Binary instance-putStaticLabel :: StaticLabel -> Put-putStaticLabel (StaticLabel string typ)    = putWord8 0 >> put string >> put typ -putStaticLabel (StaticApply label1 label2) = putWord8 1 >> putStaticLabel label1 >> putStaticLabel label2-putStaticLabel (StaticDuplicate label typ) = putWord8 2 >> putStaticLabel label >> put typ--getStaticLabel :: Get StaticLabel-getStaticLabel = do-  header <- getWord8-  case header of-    0 -> StaticLabel <$> get <*> get-    1 -> StaticApply <$> getStaticLabel <*> getStaticLabel-    2 -> StaticDuplicate <$> getStaticLabel <*> get-    _ -> fail "StaticLabel.get: invalid" --instance Typeable a => Binary (Static a) where-  put (Static label) = putStaticLabel label-  get = do-    label <- getStaticLabel-    if typeOfStaticLabel label `compareTypeRep` typeOf (undefined :: a)-      then return $ Static label -      else fail "Static.get: type error"- instance Binary WhereIsReply where   put (WhereIsReply label mPid) = put label >> put mPid   get = WhereIsReply <$> get <*> get@@ -613,9 +518,3 @@  typedChannelWithId :: LocalSendPortId -> Accessor LocalProcessState (Maybe TypedChannel) typedChannelWithId cid = typedChannels >>> DAC.mapMaybe cid--remoteTableLabels :: Accessor RemoteTable (Map String Dynamic)-remoteTableLabels = accessor _remoteTableLabels (\ls tbl -> tbl { _remoteTableLabels = ls })--remoteTableLabel :: String -> Accessor RemoteTable (Maybe Dynamic)-remoteTableLabel label = remoteTableLabels >>> DAC.mapMaybe label
src/Control/Distributed/Process/Node.hs view
@@ -9,7 +9,6 @@   , localNodeId   ) where - #if ! MIN_VERSION_base(4,6,0) import Prelude hiding (catch) #endif@@ -31,7 +30,7 @@ import Data.Set (Set) import qualified Data.Set as Set (empty, insert, delete, member, (\\), fromList) import Data.Foldable (forM_)-import Data.Maybe (isJust, fromMaybe)+import Data.Maybe (isJust) import Data.Typeable (Typeable) import Control.Category ((>>>)) import Control.Applicative ((<$>))@@ -69,9 +68,10 @@ import Data.Accessor (Accessor, accessor, (^.), (^=), (^:)) import qualified Data.Accessor.Container as DAC (mapDefault, mapMaybe) import System.Random (randomIO)+import Control.Distributed.Static (RemoteTable, Closure)+import qualified Control.Distributed.Static as Static (unclosure) import Control.Distributed.Process.Internal.Types -  ( RemoteTable-  , NodeId(..)+  ( NodeId(..)   , LocalProcessId(..)   , ProcessId(..)   , LocalNode(..)@@ -98,7 +98,6 @@   , DidUnlinkPort(..)   , SpawnRef   , DidSpawn(..)-  , Closure(..)   , Message   , TypedChannel(..)   , Identifier(..)@@ -107,31 +106,26 @@   , typedChannelWithId   , WhereIsReply(..)   , messageToPayload-  , RemoteTable(..)   , payloadToMessage   , createMessage   , runLocalProcess   ) import Control.Distributed.Process.Serializable (Serializable)-import Control.Distributed.Process.Internal.Dynamic (fromDynamic)-import Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure)  import Control.Distributed.Process.Internal.Node    ( sendBinary   , sendMessage   , sendPayload   ) import Control.Distributed.Process.Internal.Primitives (expect, register, finally)-import qualified Control.Distributed.Process.Internal.Closure.Static as Static (__remoteTable)-import qualified Control.Distributed.Process.Internal.Closure.CP as CP (__remoteTable)+import qualified Control.Distributed.Process.Internal.Closure.BuiltIn as BuiltIn (remoteTable)+import qualified Control.Distributed.Static as Static (initRemoteTable)  -------------------------------------------------------------------------------- -- Initialization                                                             -- --------------------------------------------------------------------------------  initRemoteTable :: RemoteTable-initRemoteTable = Static.__remoteTable-                . CP.__remoteTable -                $ RemoteTable Map.empty+initRemoteTable = BuiltIn.remoteTable Static.initRemoteTable   -- | Initialize a new local node.  newLocalNode :: NT.Transport -> RemoteTable -> IO LocalNode@@ -509,7 +503,9 @@   mProc <- unClosure cProc   -- If the closure does not exist, we spawn a process that throws an exception   -- This allows the remote node to find out what's happening-  let proc = fromMaybe (fail $ "Error: unknown closure " ++ show cProc) mProc+  let proc = case mProc of+               Left err -> fail $ "Error: Could not resolve closure: " ++ err+               Right p  -> p   node <- ask   pid' <- liftIO $ forkProcess node proc   liftIO $ sendMessage node@@ -603,10 +599,10 @@ isLocal nid ident = nodeOf ident == localNodeId nid  -- | Lookup a local closure -unClosure :: Typeable a => Closure a -> NC (Maybe a)-unClosure (Closure static env) = do+unClosure :: Typeable a => Closure a -> NC (Either String a)+unClosure closure = do   rtable <- remoteTable <$> ask-  return (resolveClosure rtable static env >>= fromDynamic)+  return (Static.unclosure rtable closure)  -- | Check if an identifier refers to a valid local object isValidLocalIdentifier :: Identifier -> NC Bool
src/Control/Distributed/Process/Serializable.hs view
@@ -6,6 +6,7 @@   , sizeOfFingerprint   , Fingerprint   , showFingerprint+  , SerializableDict(SerializableDict)   ) where  import Data.Binary (Binary)@@ -22,6 +23,11 @@                                                  ) import Foreign.Storable (pokeByteOff, peekByteOff, sizeOf) import Foreign.ForeignPtr (withForeignPtr)++-- | Reification of 'Serializable' (see "Control.Distributed.Process.Closure")+data SerializableDict a where+    SerializableDict :: Serializable a => SerializableDict a+  deriving (Typeable)  -- | Objects that can be sent across the network class (Binary a, Typeable a) => Serializable a
tests/TestClosure.hs view
@@ -1,7 +1,7 @@ module Main where  import Data.ByteString.Lazy (empty)-import Data.Typeable (Typeable, typeOf)+import Data.Typeable (Typeable) import Control.Monad (join, replicateM, forever) import Control.Exception (IOException, throw) import Control.Concurrent (forkIO, threadDelay)@@ -12,9 +12,12 @@ import Control.Distributed.Process import Control.Distributed.Process.Closure import Control.Distributed.Process.Node-import Control.Distributed.Process.Internal.Types (Static(Static), StaticLabel(StaticLabel))+import Control.Distributed.Static (staticLabel, staticClosure) import TestAuxiliary +quintuple :: a -> b -> c -> d -> e -> (a, b, c, d, e)+quintuple a b c d e = (a, b, c, d, e)+ sdictInt :: SerializableDict Int sdictInt = SerializableDict @@ -41,6 +44,7 @@   where     sieve :: [Integer] -> [Integer]     sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0]+    sieve [] = error "Uh oh -- we've run out of primes"  -- | First argument indicates empty closure environment typedPingServer :: () -> ReceivePort (SendPort ()) -> Process ()@@ -56,8 +60,14 @@           , 'wait           , 'typedPingServer           , 'isPrime+          , 'quintuple           ] +-- Just try creating a static polymorphic value+staticQuintuple :: (Typeable a, Typeable b, Typeable c, Typeable d, Typeable e)+                => Static (a -> b -> c -> d -> e -> (a, b, c, d, e))+staticQuintuple = $(mkStatic 'quintuple)+ factorialClosure :: Int -> Closure (Process Int) factorialClosure = $(mkClosure 'factorial)  @@ -71,13 +81,13 @@ sendPidClosure = $(mkClosure 'sendPid)   sendFac :: Int -> ProcessId -> Closure (Process ())-sendFac n pid = factorialClosure n `cpBind` cpSend $(mkStatic 'sdictInt) pid +sendFac n pid = factorialClosure n `bindCP` cpSend $(mkStatic 'sdictInt) pid   factorialOf :: Closure (Int -> Process Int) factorialOf = staticClosure $(mkStatic 'factorial)  factorial' :: Int -> Closure (Process Int)-factorial' n = cpReturn $(mkStatic 'sdictInt) n `cpBind` factorialOf +factorial' n = returnCP $(mkStatic 'sdictInt) n `bindCP` factorialOf   waitClosure :: Int -> Closure (Process ()) waitClosure = $(mkClosure 'wait) @@ -85,18 +95,22 @@ testUnclosure :: Transport -> RemoteTable -> IO () testUnclosure transport rtable = do   node <- newLocalNode transport rtable-  runProcess node $ do+  done <- newEmptyMVar+  forkProcess node $ do     120 <- join . unClosure $ factorialClosure 5-    return ()+    liftIO $ putMVar done ()+  takeMVar done  testBind :: Transport -> RemoteTable -> IO () testBind transport rtable = do   node <- newLocalNode transport rtable+  done <- newEmptyMVar   runProcess node $ do     us <- getSelfPid     join . unClosure $ sendFac 6 us      (720 :: Int) <- expect -    return ()+    liftIO $ putMVar done ()+  takeMVar done  testSendPureClosure :: Transport -> RemoteTable -> IO () testSendPureClosure transport rtable = do@@ -227,12 +241,14 @@ testSeq :: Transport -> RemoteTable -> IO () testSeq transport rtable = do   node <- newLocalNode transport rtable+  done <- newEmptyMVar   runProcess node $ do     us <- getSelfPid-    join . unClosure $ sendFac 5 us `cpSeq` sendFac 6 us+    join . unClosure $ sendFac 5 us `seqCP` sendFac 6 us     120 :: Int <- expect     720 :: Int <- expect-    return ()+    liftIO $ putMVar done ()+  takeMVar done  -- Test 'spawnSupervised' --@@ -272,29 +288,34 @@ testSpawnInvalid :: Transport -> RemoteTable -> IO () testSpawnInvalid transport rtable = do   node <- newLocalNode transport rtable-  runProcess node $ do-    (pid, ref) <- spawnMonitor (localNodeId node) (Closure (Static (StaticLabel "ThisDoesNotExist" (typeOf ()))) empty)+  done <- newEmptyMVar+  forkProcess node $ do+    (pid, ref) <- spawnMonitor (localNodeId node) (Closure (staticLabel "ThisDoesNotExist") empty)     ProcessMonitorNotification ref' pid' _reason <- expect      -- Depending on the exact interleaving, reason might be NoProc or the exception thrown by the absence of the static closure     True <- return $ ref' == ref && pid == pid'  -    return ()+    liftIO $ putMVar done ()+  takeMVar done  testClosureExpect :: Transport -> RemoteTable -> IO () testClosureExpect transport rtable = do   node <- newLocalNode transport rtable+  done <- newEmptyMVar   runProcess node $ do     nodeId <- getSelfNode     us     <- getSelfPid-    them   <- spawn nodeId $ cpExpect $(mkStatic 'sdictInt) `cpBind` cpSend $(mkStatic 'sdictInt) us+    them   <- spawn nodeId $ cpExpect $(mkStatic 'sdictInt) `bindCP` cpSend $(mkStatic 'sdictInt) us     send them (1234 :: Int)     (1234 :: Int) <- expect-    return ()+    liftIO $ putMVar done ()+  takeMVar done  testSpawnChannel :: Transport -> RemoteTable -> IO () testSpawnChannel transport rtable = do+  done <- newEmptyMVar   [node1, node2] <- replicateM 2 $ newLocalNode transport rtable -  runProcess node1 $ do+  forkProcess node1 $ do     pingServer <- spawnChannel                      (sdictSendPort sdictUnit)                     (localNodeId node2)  @@ -302,13 +323,18 @@     (sendReply, receiveReply) <- newChan     sendChan pingServer sendReply     receiveChan receiveReply+    liftIO $ putMVar done () +  takeMVar done+ testTDict :: Transport -> RemoteTable -> IO () testTDict transport rtable = do+  done <- newEmptyMVar   [node1, node2] <- replicateM 2 $ newLocalNode transport rtable-  runProcess node1 $ do+  forkProcess node1 $ do     True <- call $(functionTDict 'isPrime) (localNodeId node2) ($(mkClosure 'isPrime) (79 :: Integer))-    return ()+    liftIO $ putMVar done ()+  takeMVar done  main :: IO () main = do