@@ -78,7 +78,7 @@ import Data.Map (Map)
78import Data.Int (Int32)
78import Data.Int (Int32)
79import Data.Maybe (fromJust)
79import Data.Maybe (fromJust)
80import Data.Typeable (Typeable, TypeRep, typeOf, funResultTy)
80import Data.Typeable (Typeable, TypeRep, typeOf, funResultTy)
81−import Data.Binary (Binary(put, get), putWord8, getWord8, encode)
81+import Data.Binary (Binary(put, get), putWord8, getWord8, encode, Put, Get)
82import qualified Data.ByteString as BSS (ByteString, concat)
82import qualified Data.ByteString as BSS (ByteString, concat)
83import qualified Data.ByteString.Lazy as BSL
83import qualified Data.ByteString.Lazy as BSL
84 ( ByteString
84 ( ByteString
@@ -109,7 +109,7 @@ import Control.Distributed.Process.Serializable
110import Control.Distributed.Process.Internal.CQueue (CQueue)
110import Control.Distributed.Process.Internal.CQueue (CQueue)
111import Control.Distributed.Process.Internal.Dynamic (Dynamic)
111import Control.Distributed.Process.Internal.Dynamic (Dynamic)
112−import Control.Distributed.Process.Internal.TypeRep () -- Binary instances
112+import Control.Distributed.Process.Internal.TypeRep (compareTypeRep) -- and Binary instances
114--------------------------------------------------------------------------------
114--------------------------------------------------------------------------------
115-- Node and process identifiers --
115-- Node and process identifiers --
@@ -265,7 +265,15 @@ data StaticLabel =
265 | StaticDuplicate StaticLabel TypeRep
265 | StaticDuplicate StaticLabel TypeRep
266 deriving (Typeable, Show)
266 deriving (Typeable, Show)
268−-- | A static value is top-level bound or the application of two static values
268+-- | A static value is top-level bound or the application of two static values.
270+-- You construct static values using 'Control.Distributed.Process.Closure.mkStatic'
271+-- or 'staticApply'. 'Static' has a serializable instance for all /Typeable/ 'a':
273+-- > instance Typeable a => Serializable (Static a)
275+-- The 'Typeable' constraint (not present in the original Cloud Haskell paper)
276+-- makes it possible to do a type check during deserialization.
269newtype Static a = Static StaticLabel
277newtype Static a = Static StaticLabel
270 deriving (Typeable, Show)
278 deriving (Typeable, Show)
@@ -518,9 +526,9 @@ instance Binary DiedReason where
518 4 -> return DiedUnknownId
526 4 -> return DiedUnknownId
519 _ -> fail "DiedReason.get: invalid"
527 _ -> fail "DiedReason.get: invalid"
521−instance Binary (Closure a) where
529+instance Typeable a => Binary (Closure a) where
522− put (Closure (Static label) env) = put label >> put env
530+ put (Closure static env) = put static >> put env
523− get = Closure <$> (Static <$> get) <*> get
531+ get = Closure <$> get <*> get
525instance Binary DidSpawn where
533instance Binary DidSpawn where
526 put (DidSpawn ref pid) = put ref >> put pid
534 put (DidSpawn ref pid) = put ref >> put pid
@@ -542,17 +550,28 @@ instance Binary Identifier where
542 2 -> SendPortIdentifier <$> get
550 2 -> SendPortIdentifier <$> get
543 _ -> fail "Identifier.get: invalid"
551 _ -> fail "Identifier.get: invalid"
545−instance Binary StaticLabel where
553+-- We don't want StaticLabel to be its own Binary instance
546− put (StaticLabel string typ) = putWord8 0 >> put string >> put typ
554+putStaticLabel :: StaticLabel -> Put
547− put (StaticApply label1 label2) = putWord8 1 >> put label1 >> put label2
555+putStaticLabel (StaticLabel string typ) = putWord8 0 >> put string >> put typ
548− put (StaticDuplicate label typ) = putWord8 2 >> put label >> put typ
556+putStaticLabel (StaticApply label1 label2) = putWord8 1 >> putStaticLabel label1 >> putStaticLabel label2
557+putStaticLabel (StaticDuplicate label typ) = putWord8 2 >> putStaticLabel label >> put typ
559+getStaticLabel :: Get StaticLabel
563+ 0 -> StaticLabel <$> get <*> get
564+ 1 -> StaticApply <$> getStaticLabel <*> getStaticLabel
565+ 2 -> StaticDuplicate <$> getStaticLabel <*> get
566+ _ -> fail "StaticLabel.get: invalid"
568+instance Typeable a => Binary (Static a) where
569+ put (Static label) = putStaticLabel label
550− header <- getWord8
571+ label <- getStaticLabel
551− case header of
572+ if typeOfStaticLabel label `compareTypeRep` typeOf (undefined :: a)
552− 0 -> StaticLabel <$> get <*> get
573+ then return $ Static label
553− 1 -> StaticApply <$> get <*> get
574+ else fail "Static.get: type error"
554− 2 -> StaticDuplicate <$> get <*> get
555− _ -> fail "StaticLabel.get: invalid"
557instance Binary WhereIsReply where
576instance Binary WhereIsReply where
558 put (WhereIsReply label mPid) = put label >> put mPid
577 put (WhereIsReply label mPid) = put label >> put mPid