@@ -78,7 +78,7 @@ import Data.Map (Map)
7878import Data.Int (Int32)
7979import Data.Maybe (fromJust)
8080import 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)
8282import qualified Data.ByteString as BSS (ByteString, concat)
8383import qualified Data.ByteString.Lazy as BSL
8484 ( ByteString
@@ -109,7 +109,7 @@ import Control.Distributed.Process.Serializable
109109 )
110110import Control.Distributed.Process.Internal.CQueue (CQueue)
111111import 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
113113
114114--------------------------------------------------------------------------------
115115-- Node and process identifiers --
@@ -265,7 +265,15 @@ data StaticLabel =
265265 | StaticDuplicate StaticLabel TypeRep
266266 deriving (Typeable, Show)
267267
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.
269+--
270+-- You construct static values using 'Control.Distributed.Process.Closure.mkStatic'
271+-- or 'staticApply'. 'Static' has a serializable instance for all /Typeable/ 'a':
272+--
273+-- > instance Typeable a => Serializable (Static a)
274+--
275+-- The 'Typeable' constraint (not present in the original Cloud Haskell paper)
276+-- makes it possible to do a type check during deserialization.
269277newtype Static a = Static StaticLabel
270278 deriving (Typeable, Show)
271279
@@ -518,9 +526,9 @@ instance Binary DiedReason where
518526 4 -> return DiedUnknownId
519527 _ -> fail "DiedReason.get: invalid"
520528
521−instance Binary (Closure a) where
522− put (Closure (Static label) env) = put label >> put env
523− get = Closure <$> (Static <$> get) <*> get
529+instance Typeable a => Binary (Closure a) where
530+ put (Closure static env) = put static >> put env
531+ get = Closure <$> get <*> get
524532
525533instance Binary DidSpawn where
526534 put (DidSpawn ref pid) = put ref >> put pid
@@ -542,17 +550,28 @@ instance Binary Identifier where
542550 2 -> SendPortIdentifier <$> get
543551 _ -> fail "Identifier.get: invalid"
544552
545−instance Binary StaticLabel where
546− put (StaticLabel string typ) = putWord8 0 >> put string >> put typ
547− put (StaticApply label1 label2) = putWord8 1 >> put label1 >> put label2
548− put (StaticDuplicate label typ) = putWord8 2 >> put label >> put typ
553+-- We don't want StaticLabel to be its own Binary instance
554+putStaticLabel :: StaticLabel -> Put
555+putStaticLabel (StaticLabel string typ) = putWord8 0 >> put string >> put typ
556+putStaticLabel (StaticApply label1 label2) = putWord8 1 >> putStaticLabel label1 >> putStaticLabel label2
557+putStaticLabel (StaticDuplicate label typ) = putWord8 2 >> putStaticLabel label >> put typ
558+
559+getStaticLabel :: Get StaticLabel
560+getStaticLabel = do
561+ header <- getWord8
562+ case header of
563+ 0 -> StaticLabel <$> get <*> get
564+ 1 -> StaticApply <$> getStaticLabel <*> getStaticLabel
565+ 2 -> StaticDuplicate <$> getStaticLabel <*> get
566+ _ -> fail "StaticLabel.get: invalid"
567+
568+instance Typeable a => Binary (Static a) where
569+ put (Static label) = putStaticLabel label
549570 get = do
550− header <- getWord8
551− case header of
552− 0 -> StaticLabel <$> get <*> get
553− 1 -> StaticApply <$> get <*> get
554− 2 -> StaticDuplicate <$> get <*> get
555− _ -> fail "StaticLabel.get: invalid"
571+ label <- getStaticLabel
572+ if typeOfStaticLabel label `compareTypeRep` typeOf (undefined :: a)
573+ then return $ Static label
574+ else fail "Static.get: type error"
556575
557576instance Binary WhereIsReply where
558577 put (WhereIsReply label mPid) = put label >> put mPid