git.iko.soy/distributed-process
on master help sign in
First steps towards extracting static

This makes 'static' a separate module. Lots of cleaning up still to do, but first I'd like to try and remove the unsafe stuff from Dynamic and properly support polymorphic types.

commit7b5c530d29ebb532c4a093074f359fb50f9cbfb8 authorEdsko de Vries <edsko@edsko.net> dateThu 9 Aug 2012, 10:01 (14 years ago) parentae6097e
20 files changed+727−870
distributed-process/distributed-process.cabal+7−8 distributed-process/src/Control/Distributed/Process.hs+37−18 distributed-process/src/Control/Distributed/Process/Closure.hs+78−28 distributed-process/src/Control/Distributed/Process/Internal/Closure/CP.hs−330 distributed-process/src/Control/Distributed/Process/Internal/Closure/MkClosure.hs+6−1 distributed-process/src/Control/Distributed/Process/Internal/Closure/Resolution.hs−34 distributed-process/src/Control/Distributed/Process/Internal/Closure/Static.hs−190 distributed-process/src/Control/Distributed/Process/Internal/Closure/TH.hs+22−20 distributed-process/src/Control/Distributed/Process/Internal/Dynamic.hs−112 distributed-process/src/Control/Distributed/Process/Internal/Primitives.hs+9−4 distributed-process/src/Control/Distributed/Process/Internal/Types.hs+6−107 distributed-process/src/Control/Distributed/Process/Node.hs+15−11 distributed-process/src/Control/Distributed/Process/Serializable.hs+6 distributed-process/tests/TestClosure.hs+6−6 distributed-static/LICENSE+30 distributed-static/Setup.hs+2 distributed-static/distributed-static.cabal+29 distributed-static/src/Control/Distributed/Static.hs+352 distributed-static/src/Control/Distributed/Static/Internal/Dynamic.hs+121 distributed-process/src/Control/Distributed/Process/Internal/TypeRep.hs → distributed-static/src/Control/Distributed/Static/Internal/TypeRep.hs+1−1
distributed-process/distributed-process.cabal+7−8
@@ -43,21 +43,18 @@ Library
4343 time >= 1.2 && < 1.5,
4444 template-haskell >= 2.6 && < 2.8,
4545 random >= 1.0 && < 1.1,
46− ghc-prim >= 0.2 && < 0.3
46+ ghc-prim >= 0.2 && < 0.3,
47+ distributed-static >= 0.1 && < 0.2
4748 Exposed-modules: Control.Distributed.Process,
4849 Control.Distributed.Process.Serializable,
4950 Control.Distributed.Process.Closure,
5051 Control.Distributed.Process.Node,
5152 Control.Distributed.Process.Internal.Primitives,
5253 Control.Distributed.Process.Internal.CQueue,
53− Control.Distributed.Process.Internal.Dynamic,
54− Control.Distributed.Process.Internal.TypeRep,
5554 Control.Distributed.Process.Internal.Types,
56− Control.Distributed.Process.Internal.Closure.Static,
5755 Control.Distributed.Process.Internal.Closure.MkClosure,
58− Control.Distributed.Process.Internal.Closure.CP,
5956 Control.Distributed.Process.Internal.Closure.TH,
60− Control.Distributed.Process.Internal.Closure.Resolution,
57+ Control.Distributed.Process.Internal.Closure.BuiltIn,
6158 Control.Distributed.Process.Internal.Node
6259 Extensions: RankNTypes,
6360 ScopedTypeVariables,
@@ -90,7 +87,8 @@ Test-Suite TestCH
9087 template-haskell >= 2.6 && < 2.8,
9188 random >= 1.0 && < 1.1,
9289 ghc-prim >= 0.2 && < 0.3,
93− ansi-terminal >= 0.5 && < 0.6
90+ ansi-terminal >= 0.5 && < 0.6,
91+ distributed-static >= 0.1 && < 0.2
9492 Extensions: RankNTypes,
9593 ScopedTypeVariables,
9694 FlexibleInstances,
@@ -122,7 +120,8 @@ Test-Suite TestClosure
122120 template-haskell >= 2.6 && < 2.8,
123121 random >= 1.0 && < 1.1,
124122 ghc-prim >= 0.2 && < 0.3,
125− ansi-terminal >= 0.5 && < 0.6
123+ ansi-terminal >= 0.5 && < 0.6,
124+ distributed-static >= 0.1 && < 0.2
126125 Other-modules: TestAuxiliary
127126 Extensions: RankNTypes,
128127 ScopedTypeVariables,
distributed-process/src/Control/Distributed/Process.hs+37−18
@@ -100,7 +100,6 @@ module Control.Distributed.Process
100100 , spawnChannelLocal
101101 ) where
102102
103−
104103#if ! MIN_VERSION_base(4,6,0)
105104import Prelude hiding (catch)
106105#endif
@@ -109,13 +108,15 @@ import Data.Typeable (Typeable)
109108import Control.Monad.IO.Class (liftIO)
110109import Control.Applicative ((<$>))
111110import Control.Monad.Reader (ask)
111+import Control.Distributed.Static
112+ ( Closure(..)
113+ , Static
114+ , RemoteTable
115+ )
112116import Control.Distributed.Process.Internal.Types
113− ( RemoteTable
114− , NodeId(..)
117+ ( NodeId(..)
115118 , ProcessId(..)
116119 , Process(..)
117− , Closure(..)
118− , Static
119120 , MonitorRef(..)
120121 , ProcessMonitorNotification(..)
121122 , NodeMonitorNotification(..)
@@ -126,17 +127,32 @@ import Control.Distributed.Process.Internal.Types
126127 , DiedReason(..)
127128 , SpawnRef(..)
128129 , DidSpawn(..)
129− , Closure(..)
130130 , SendPort(..)
131131 , ReceivePort(..)
132− , SerializableDict(..)
133132 , SendPortId(..)
134133 , WhereIsReply(..)
135134 , LocalProcess(processNode)
136135 )
136+import Control.Distributed.Process.Serializable (SerializableDict)
137+import Control.Distributed.Process.Internal.Closure.BuiltIn
138+ ( sdictUnit
139+ , sdictSendPort
140+ , idCP
141+ , seqCP
142+ , bindCP
143+ , splitCP
144+ , cpLink
145+ , cpUnlink
146+ , cpExpect
147+ , cpSend
148+ , cpNewChan
149+ )
150+import Control.Distributed.Static (closureCompose, sndStatic, staticClosure)
151+
152+{-
137153import Control.Distributed.Process.Internal.Closure.CP
138− ( cpSeq
139− , cpBind
154+ (
155+ , bindCP
140156 , cpSend
141157 , cpExpect
142158 , cpLink
@@ -145,10 +161,13 @@ import Control.Distributed.Process.Internal.Closure.CP
145161 , cpCancelL
146162 , cpSplit
147163 )
164+-}
165+{-
148166import Control.Distributed.Process.Internal.Closure.Static
149167 ( sdictUnit
150168 , sdictSendPort
151169 )
170+-}
152171import Control.Distributed.Process.Internal.Primitives
153172 ( -- Basic messaging
154173 send
@@ -289,9 +308,9 @@ spawn nid proc = do
289308 -- that was already set up
290309 mRef <- monitorNode nid
291310 sRef <- spawnAsync nid $ cpLink us
292− `cpSeq` cpExpect sdictUnit
293− `cpSeq` cpUnlink us
294− `cpSeq` proc
311+ `seqCP` cpExpect sdictUnit
312+ `seqCP` cpUnlink us
313+ `seqCP` proc
295314 mPid <- receiveWait
296315 [ matchIf (\(DidSpawn ref _) -> ref == sRef)
297316 (\(DidSpawn _ pid) -> return $ Just pid)
@@ -333,7 +352,7 @@ spawnMonitor nid proc = do
333352call :: Serializable a => Static (SerializableDict a) -> NodeId -> Closure (Process a) -> Process a
334353call dict nid proc = do
335354 us <- getSelfPid
336− (_, mRef) <- spawnMonitor nid (proc `cpBind` cpSend dict us)
355+ (_, mRef) <- spawnMonitor nid (proc `bindCP` cpSend dict us)
337356 -- We are guaranteed to receive the reply before the monitor notification
338357 -- (if a reply is sent at all)
339358 -- NOTE: This might not be true if we switch to unreliable delivery.
@@ -353,7 +372,7 @@ spawnSupervised :: NodeId
353372 -> Process (ProcessId, MonitorRef)
354373spawnSupervised nid proc = do
355374 us <- getSelfPid
356− them <- spawn nid (cpLink us `cpSeq` proc)
375+ them <- spawn nid (cpLink us `seqCP` proc)
357376 ref <- monitor them
358377 return (them, ref)
359378
@@ -370,10 +389,10 @@ spawnChannel dict nid proc = do
370389 where
371390 go :: ProcessId -> Closure (Process ())
372391 go pid = cpNewChan dict
373− `cpBind`
374− (cpSend (sdictSendPort dict) pid `cpSplit` proc)
375− `cpBind`
376− cpCancelL
392+ `bindCP`
393+ (cpSend (sdictSendPort dict) pid `splitCP` proc)
394+ `bindCP`
395+ (idCP `closureCompose` staticClosure sndStatic)
377396
378397--------------------------------------------------------------------------------
379398-- Local versions of spawn --
distributed-process/src/Control/Distributed/Process/Closure.hs+78−28
@@ -228,37 +228,32 @@ module Control.Distributed.Process.Closure
228228 -- * Primitive operations on static values
229229 , staticApply
230230 , staticDuplicate
231− -- * Static functionals
232− , staticConst
233− , staticFlip
234− , staticFst
235− , staticSnd
231+ -- * Static values
232+ , idStatic
233+ , composeStatic
234+ , constStatic
235+ , flipStatic
236+ , fstStatic
237+ , sndStatic
238+ , firstStatic
239+ , secondStatic
240+ , splitStatic
241+ , unitStatic
242+ -- * Combinators on static values
236243 , staticCompose
237− , staticFirst
238− , staticSecond
239− , staticSplit
240− -- * Static constants
241− , staticUnit
242− -- * Creating closures
243− , staticDecode
244− , staticClosure
245− , toClosure
246244 -- * Serialization dictionaries (and their static versions)
247245 , SerializableDict(..)
248246 , sdictUnit
249247 , sdictProcessId
250248 , sdictSendPort
249+ -- * Creating closures
250+ , staticDecode
251+ , staticClosure
252+-- , toClosure
251253 -- * Definition of CP and the generalized arrow combinators
252254 , CP
253− , cpIntro
254− , cpElim
255− , cpId
256− , cpComp
257− , cpFirst
258− , cpSecond
259− , cpSplit
260− , cpCancelL
261− , cpCancelR
255+ , idCP
256+ , splitCP
262257 -- * Closure versions of CH primitives
263258 , cpLink
264259 , cpUnlink
@@ -266,22 +261,72 @@ module Control.Distributed.Process.Closure
266261 , cpExpect
267262 , cpNewChan
268263 -- * @Closure (Process a)@ as a not-quite-monad
269− , cpReturn
270− , cpBind
271− , cpSeq
264+ , returnCP
265+ , bindCP
266+ , seqCP
272267 ) where
273268
269+import Control.Distributed.Process.Serializable (SerializableDict(..))
270+
271+import Control.Distributed.Static
272+ ( -- Introducing static values
273+ staticApply
274+ , staticDuplicate
275+ -- Static values
276+ , idStatic
277+ , composeStatic
278+ , constStatic
279+ , flipStatic
280+ , fstStatic
281+ , sndStatic
282+ , firstStatic
283+ , secondStatic
284+ , splitStatic
285+ , unitStatic
286+ -- Combinators on static values
287+ , staticCompose
288+ , staticClosure
289+ , closureSplit
290+ )
291+
292+
293+{-
274294import Control.Distributed.Process.Internal.Types
275− ( SerializableDict(..)
276− , staticApply
295+ ( staticApply
277296 , staticDuplicate
278297 )
298+-}
299+
279300import Control.Distributed.Process.Internal.Closure.TH
280301 ( remotable
281302 , mkStatic
282303 , functionSDict
283304 , functionTDict
284305 )
306+import Control.Distributed.Process.Internal.Closure.BuiltIn
307+ ( -- Remote table
308+ remoteTable
309+ -- Static dictionaries and associated operations
310+ , staticDecode
311+ , sdictUnit
312+ , sdictProcessId
313+ , sdictSendPort
314+ -- The CP type and associated combinators
315+ , CP
316+ , splitCP
317+ , idCP
318+ , returnCP
319+ , seqCP
320+ , bindCP
321+ -- CP versions of Cloud Haskell primitives
322+ , cpLink
323+ , cpUnlink
324+ , cpSend
325+ , cpExpect
326+ , cpNewChan
327+ )
328+
329+{-
285330import Control.Distributed.Process.Internal.Closure.Static
286331 ( -- Static functionals
287332 staticConst
@@ -303,7 +348,11 @@ import Control.Distributed.Process.Internal.Closure.Static
303348 , sdictProcessId
304349 , sdictSendPort
305350 )
351+-}
352+
306353import Control.Distributed.Process.Internal.Closure.MkClosure (mkClosure)
354+
355+{-
307356import Control.Distributed.Process.Internal.Closure.CP
308357 ( -- Definition of CP and the generalized arrow combinators
309358 CP
@@ -327,3 +376,4 @@ import Control.Distributed.Process.Internal.Closure.CP
327376 , cpBind
328377 , cpSeq
329378 )
379+-}
distributed-process/src/Control/Distributed/Process/Internal/Closure/CP.hsdeleted−330
@@ -1,330 +0,0 @@
1−-- | Combinator for process closures
2−{-# LANGUAGE MagicHash #-}
3−module Control.Distributed.Process.Internal.Closure.CP
4− ( -- * Definition of CP and the generalized arrow combinators
5− CP
6− , cpIntro
7− , cpElim
8− , cpId
9− , cpComp
10− , cpFirst
11− , cpSecond
12− , cpSplit
13− , cpCancelL
14− , cpCancelR
15− -- * Closure versions of CH primitives
16− , cpLink
17− , cpUnlink
18− , cpSend
19− , cpExpect
20− , cpNewChan
21− -- * @Closure (Process a)@ as a not-quite-monad
22− , cpReturn
23− , cpBind
24− , cpSeq
25− -- * Runtime support
26− , __remoteTable
27− ) where
28−
29−import Data.Binary (encode)
30−import Data.ByteString.Lazy (ByteString)
31−import Data.Typeable (Typeable, typeOf, typeRepTyCon, TyCon)
32−import Control.Applicative ((<$>))
33−import Control.Monad ((>=>))
34−import Control.Monad.Reader (ask)
35−import Control.Distributed.Process.Serializable (Serializable)
36−import Control.Distributed.Process.Internal.Types
37− ( Closure(Closure)
38− , SerializableDict(SerializableDict)
39− , Static(Static)
40− , Process
41− , staticApply
42− , staticDuplicate
43− , staticTypeOf
44− , typeOfStaticLabel
45− , ProcessId
46− , LocalNode(remoteTable)
47− , LocalProcess(processNode)
48− , SendPort
49− , ReceivePort
50− )
51−import Control.Distributed.Process.Internal.Primitives
52− ( link
53− , unlink
54− , send
55− , expect
56− , newChan
57− )
58−import Control.Distributed.Process.Internal.Closure.TH (remotable, mkStatic)
59−import Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure)
60−import Control.Distributed.Process.Internal.Closure.Static
61− ( staticCompose
62− , staticDecode
63− , staticClosure
64− , staticSplit
65− , staticConst
66− , staticUnit
67− , staticFlip
68− , staticFst
69− , staticSnd
70− , sdictProcessId
71− )
72−import Control.Distributed.Process.Internal.Closure.MkClosure (mkClosure)
73−import Control.Distributed.Process.Internal.Dynamic
74− ( Dynamic(Dynamic)
75− , unsafeCoerce#
76− , dynTypeRep
77− , dynKleisli
78− )
79−import Control.Distributed.Process.Internal.TypeRep (compareTypeRep)
80−
81−--------------------------------------------------------------------------------
82−-- Setup: A number of functions that we will pass to 'remotable' --
83−--------------------------------------------------------------------------------
84−
85−---- Type specializations of monadic operations on Processes -------------------
86−
87−returnProcess :: a -> Process a
88−returnProcess = return
89−
90−bindProcess :: Process a -> (a -> Process b) -> Process b
91−bindProcess = (>>=)
92−
93−kleisliProcess :: (a -> Process b) -> (b -> Process c) -> a -> Process c
94−kleisliProcess = (>=>)
95−
96−parJoinProcess :: Process (a -> Process b) -> a -> Process b
97−parJoinProcess proc a = proc >>= ($ a)
98−
99−---- Variations on standard or CH functions with an explicit dictionary arg ----
100−
101−sendDict :: SerializableDict a -> ProcessId -> a -> Process ()
102−sendDict SerializableDict = send
103−
104−expectDict :: SerializableDict a -> Process a
105−expectDict SerializableDict = expect
106−
107−newChanDict :: SerializableDict a -> Process (SendPort a, ReceivePort a)
108−newChanDict SerializableDict = newChan
109−
110−---- Serialization dictionaries ------------------------------------------------
111−
112−-- | Specialized serialization dictionary required in 'cpBind'
113−sdictComp :: SerializableDict (ByteString, ByteString)
114−sdictComp = SerializableDict
115−
116−---- Some specialised processes necessary to implement the combinators ---------
117−
118−-- | Resolve a closure
119−unClosure :: Static a -> ByteString -> Process Dynamic
120−unClosure static env = do
121− rtable <- remoteTable . processNode <$> ask
122− case resolveClosure rtable static env of
123− Nothing -> fail "Derived.unClosure: resolveClosure failed"
124− Just dyn -> return dyn
125−
126−-- | Remove a 'Dynamic' constructor, provided that the recorded type matches the
127−-- type of the first static argument (the value of that argument is not used)
128−unDynamic :: Static a -> Process Dynamic -> Process a
129−unDynamic (Static label) pdyn = do
130− Dynamic typ val <- pdyn
131− if typ `compareTypeRep` typeOfStaticLabel label
132− then return (unsafeCoerce# val)
133− else fail $ "unDynamic: cannot match "
134− ++ show typ
135− ++ " against expected type "
136− ++ show (typeOfStaticLabel label)
137−
138−-- | Dynamic kleisli composition
139−--
140−-- The first argument stops remotable from trying to generate a SerializableDict
141−-- for (Process Dynamic, Process Dynamic)
142−kleisliCompDyn :: () -> (Process Dynamic, Process Dynamic) -> Process Dynamic
143−kleisliCompDyn () (pf, pg) = do
144− f <- pf -- a -> Process b
145− g <- pg -- b -> Process c
146− case dynKleisli tyConProcess kleisliProcess f g of
147− Just dyn -> return dyn
148− Nothing -> fail $ "kleisliCompDyn: could not compose "
149− ++ show (dynTypeRep f)
150− ++ " with "
151− ++ show (dynTypeRep g)
152− where
153− tyConProcess :: TyCon
154− tyConProcess = typeRepTyCon (typeOf (undefined :: Process ()))
155−
156−cpFirstAux :: (a -> Process b) -> (a, c) -> Process (b, c)
157−cpFirstAux f (a, c) = f a >>= \b -> return (b, c)
158−
159−cpSecondAux :: (a -> Process b) -> (c, a) -> Process (c, b)
160−cpSecondAux f (c, a) = f a >>= \b -> return (c, b)
161−
162−---- Finally, the call to remotable --------------------------------------------
163−
164−remotable [ -- Monadic operations
165− 'returnProcess
166− , 'bindProcess
167− , 'parJoinProcess
168− -- CH primitives
169− , 'link
170− , 'unlink
171− -- Explicit dictionaries
172− , 'sendDict
173− , 'expectDict
174− , 'newChanDict
175− -- Serialization dictionaries
176− , 'sdictComp
177− -- Specialized processes
178− , 'unClosure
179− , 'unDynamic
180− , 'kleisliCompDyn
181− , 'cpFirstAux
182− , 'cpSecondAux
183− ]
184−
185−--------------------------------------------------------------------------------
186−-- Some derived static functions --
187−--------------------------------------------------------------------------------
188−
189−staticUndynamic :: Typeable a => Static (Process Dynamic -> Process a)
190−staticUndynamic =
191− $(mkStatic 'unDynamic) `staticApply` staticDuplicate (staticTypeOf (undefined :: a))
192−
193−staticKleisliCompDyn :: Static ((Process Dynamic, Process Dynamic) -> Process Dynamic)
194−staticKleisliCompDyn = $(mkStatic 'kleisliCompDyn) `staticApply` staticUnit
195−
196−--------------------------------------------------------------------------------
197−-- Definition of CP and the generalized arrow combinators --
198−--------------------------------------------------------------------------------
199−
200−-- | 'CP a b' represents the closure of a process parameterized by 'a' and
201−-- returning 'b'. 'CP a b' forms a (restricted) generalized arrow
202−-- (<http://www.cs.berkeley.edu/~megacz/garrows/>)
203−type CP a b = Closure (a -> Process b)
204−
205−-- | 'CP' introduction form
206−cpIntro :: forall a b. (Typeable a, Typeable b)
207− => Closure (Process b) -> Closure (a -> Process b)
208−cpIntro (Closure static env) = Closure decoder env
209− where
210− decoder :: Static (ByteString -> a -> Process b)
211− decoder = staticConst `staticCompose` static
212−
213−-- | 'CP' elimination form
214−cpElim :: forall a. Typeable a => CP () a -> Closure (Process a)
215−cpElim (Closure static env) = Closure decoder env
216− where
217− decoder :: Static (ByteString -> Process a)
218− decoder = staticFlip static `staticApply` staticUnit
219−
220−-- | Identity ('Closure' version of 'return')
221−cpId :: Typeable a => CP a a
222−cpId = staticClosure $(mkStatic 'returnProcess)
223−
224−-- | Left-to-right composition ('Closure' version of '>=>')
225−cpComp :: forall a b c. (Typeable a, Typeable b, Typeable c)
226− => CP a b -> CP b c -> CP a c
227−cpComp (Closure fstatic fenv) (Closure gstatic genv) =
228− Closure decoder (encode (fenv, genv))
229− where
230− decoder :: Static (ByteString -> a -> Process c)
231− decoder = $(mkStatic 'parJoinProcess)
232− `staticCompose`
233− staticUndynamic
234− `staticCompose`
235− staticKleisliCompDyn
236− `staticCompose`
237− (staticUnclosure fstatic `staticSplit` staticUnclosure gstatic)
238− `staticCompose`
239− staticDecode $(mkStatic 'sdictComp)
240−
241−-- | First
242−cpFirst :: forall a b c. (Typeable a, Typeable b, Typeable c)
243− => CP a b -> CP (a, c) (b, c)
244−cpFirst (Closure static env) = Closure decoder env
245− where
246− decoder :: Static (ByteString -> (a, c) -> Process (b, c))
247− decoder = $(mkStatic 'cpFirstAux) `staticCompose` static
248−
249−-- | Second
250−cpSecond :: forall a b c. (Typeable a, Typeable b, Typeable c)
251− => CP a b -> CP (c, a) (c, b)
252−cpSecond (Closure static env) = Closure decoder env
253− where
254− decoder :: Static (ByteString -> (c, a) -> Process (c, b))
255− decoder = $(mkStatic 'cpSecondAux) `staticCompose` static
256−
257−-- | Split (Like 'Control.Arrow.***')
258−cpSplit :: (Typeable a, Typeable b, Typeable c, Typeable d)
259− => CP a c -> CP b d -> CP (a, b) (c, d)
260−cpSplit f g = cpFirst f `cpComp` cpSecond g
261−
262−-- | Left cancellation
263−cpCancelL :: Typeable a => CP ((), a) a
264−-- Closure (((), a) -> Process a)
265−cpCancelL = staticClosure ($(mkStatic 'returnProcess) `staticCompose` staticSnd)
266−
267−-- | Right cancellation
268−cpCancelR :: Typeable a => CP (a, ()) a
269−cpCancelR = staticClosure ($(mkStatic 'returnProcess) `staticCompose` staticFst)
270−
271−--------------------------------------------------------------------------------
272−-- Closure versions of CH primitives --
273−--------------------------------------------------------------------------------
274−
275−-- | Closure version of 'link'
276−cpLink :: ProcessId -> Closure (Process ())
277−cpLink = $(mkClosure 'link)
278−
279−-- | Closure version of 'unlink'
280−cpUnlink :: ProcessId -> Closure (Process ())
281−cpUnlink = $(mkClosure 'unlink)
282−
283−-- | Closure version of 'send'
284−cpSend :: forall a. Typeable a
285− => Static (SerializableDict a) -> ProcessId -> Closure (a -> Process ())
286−cpSend dict pid = Closure decoder (encode pid)
287− where
288− decoder :: Static (ByteString -> a -> Process ())
289− decoder = ($(mkStatic 'sendDict) `staticApply` dict)
290− `staticCompose`
291− staticDecode sdictProcessId
292−
293−-- | Closure version of 'expect'
294−cpExpect :: Typeable a => Static (SerializableDict a) -> Closure (Process a)
295−cpExpect dict = staticClosure ($(mkStatic 'expectDict) `staticApply` dict)
296−
297−-- | Closure version of 'newChan'
298−cpNewChan :: Typeable a
299− => Static (SerializableDict a)
300− -> Closure (Process (SendPort a, ReceivePort a))
301−cpNewChan dict = staticClosure ($(mkStatic 'newChanDict) `staticApply` dict)
302−
303−--------------------------------------------------------------------------------
304−-- (Closure . Process) as a not-quite-monad --
305−--------------------------------------------------------------------------------
306−
307−-- | Not-quite-monadic 'return'
308−cpReturn :: forall a. Serializable a
309− => Static (SerializableDict a) -> a -> Closure (Process a)
310−cpReturn dict x = Closure decoder (encode x)
311− where
312− decoder :: Static (ByteString -> Process a)
313− decoder = $(mkStatic 'returnProcess)
314− `staticCompose`
315− staticDecode dict
316−
317−
318−staticUnclosure :: Typeable a
319− => Static a -> Static (ByteString -> Process Dynamic)
320−staticUnclosure s =
321− $(mkStatic 'unClosure) `staticApply` staticDuplicate s
322−
323−-- | Not-quite-monadic bind ('>>=')
324−cpBind :: forall a b. (Typeable a, Typeable b)
325− => Closure (Process a) -> Closure (a -> Process b) -> Closure (Process b)
326−cpBind x f = cpElim (cpIntro x `cpComp` f)
327−
328−-- | Monadic sequencing ('>>')
329−cpSeq :: Closure (Process ()) -> Closure (Process ()) -> Closure (Process ())
330−cpSeq p q = p `cpBind` cpIntro q
distributed-process/src/Control/Distributed/Process/Internal/Closure/MkClosure.hs+6−1
@@ -3,15 +3,20 @@ module Control.Distributed.Process.Internal.Closure.MkClosure (mkClosure) where
33
44import Data.Binary (encode)
55import Language.Haskell.TH (Q, Exp, Name)
6−import Control.Distributed.Process.Internal.Types (Closure(Closure))
76import Control.Distributed.Process.Internal.Closure.TH
87 ( mkStatic
98 , functionSDict
109 )
10+import Control.Distributed.Static (Closure(Closure), staticCompose)
11+import Control.Distributed.Process.Internal.Closure.BuiltIn (staticDecode)
12+
13+{-
14+-- import Control.Distributed.Process.Internal.Types (Closure(Closure))
1115import Control.Distributed.Process.Internal.Closure.Static
1216 ( staticCompose
1317 , staticDecode
1418 )
19+-}
1520
1621-- | Create a closure
1722--
distributed-process/src/Control/Distributed/Process/Internal/Closure/Resolution.hsdeleted−34
@@ -1,34 +0,0 @@
1−{-# LANGUAGE MagicHash #-}
2−module Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure) where
3−
4−import Data.Accessor ((^.))
5−import Data.ByteString.Lazy (ByteString)
6−import Control.Distributed.Process.Internal.Types
7− ( RemoteTable
8− , remoteTableLabel
9− , Static(Static)
10− , StaticLabel(..)
11− )
12−import Control.Distributed.Process.Internal.Dynamic
13− ( Dynamic(Dynamic)
14− , toDyn
15− , dynApply
16− , unsafeCoerce#
17− )
18−import Control.Distributed.Process.Internal.TypeRep () -- Binary instances
19−
20−resolveStatic :: RemoteTable -> Static a -> Maybe Dynamic
21−resolveStatic rtable (Static (StaticLabel string typ)) = do
22− Dynamic _ val <- rtable ^. remoteTableLabel string
23− return (Dynamic typ val)
24−resolveStatic rtable (Static (StaticApply static1 static2)) = do
25− f <- resolveStatic rtable (Static static1)
26− x <- resolveStatic rtable (Static static2)
27− f `dynApply` x
28−resolveStatic _rtable (Static (StaticDuplicate static typ)) =
29− return $ Dynamic typ (unsafeCoerce# (Static static))
30−
31−resolveClosure :: RemoteTable -> Static a -> ByteString -> Maybe Dynamic
32−resolveClosure rtable static env = do
33− decoder <- resolveStatic rtable static
34− decoder `dynApply` toDyn env
distributed-process/src/Control/Distributed/Process/Internal/Closure/Static.hsdeleted−190
@@ -1,190 +0,0 @@
1−-- | Combinators on static values
2−{-# LANGUAGE MagicHash #-}
3−module Control.Distributed.Process.Internal.Closure.Static
4− ( -- * Static functionals
5− staticConst
6− , staticFlip
7− , staticFst
8− , staticSnd
9− , staticCompose
10− , staticFirst
11− , staticSecond
12− , staticSplit
13− -- * Static constants
14− , staticUnit
15− -- * Creating closures
16− , staticDecode
17− , staticClosure
18− , toClosure
19− -- * Serialization dictionaries (and their static versions)
20− , sdictUnit
21− , sdictProcessId
22− , sdictSendPort
23− -- * Runtime support
24− , __remoteTable
25− ) where
26−
27−import Data.Binary (encode, decode)
28−import Data.ByteString.Lazy (ByteString, empty)
29−import Data.Typeable (Typeable)
30−import Control.Distributed.Process.Serializable (Serializable)
31−import Control.Distributed.Process.Internal.Types
32− ( Closure(Closure)
33− , SerializableDict(SerializableDict)
34− , Static
35− , staticApply
36− , ProcessId
37− , SendPort
38− )
39−import Control.Distributed.Process.Internal.Closure.TH (remotable, mkStatic)
40−import qualified Control.Arrow as Arrow (first, second, (***))
41−
42−--------------------------------------------------------------------------------
43−-- Setup: A number of functions that we will pass to 'remotable' --
44−--------------------------------------------------------------------------------
45−
46−---- Functionals ---------------------------------------------------------------
47−
48−compose :: (b -> c) -> (a -> b) -> a -> c
49−compose = (.)
50−
51−first :: (a -> b) -> (a, c) -> (b, c)
52−first = Arrow.first
53−
54−second :: (a -> b) -> (c, a) -> (c, b)
55−second = Arrow.second
56−
57−split :: (a -> b) -> (a' -> b') -> (a, a') -> (b, b')
58−split = (Arrow.***)
59−
60−---- Constants -----------------------------------------------------------------
61−
62−unit :: ()
63−unit = ()
64−
65−---- Variations on standard or CH functions with an explicit dictionary arg ----
66−
67−decodeDict :: SerializableDict a -> ByteString -> a
68−decodeDict SerializableDict = decode
69−
70−---- Serialization dictionaries ------------------------------------------------
71−
72−sdictUnit_ :: SerializableDict ()
73−sdictUnit_ = SerializableDict
74−
75−sdictProcessId_ :: SerializableDict ProcessId
76−sdictProcessId_ = SerializableDict
77−
78−sdictSendPort_ :: SerializableDict a -> SerializableDict (SendPort a)
79−sdictSendPort_ SerializableDict = SerializableDict
80−
81−---- Finally, the call to remotable --------------------------------------------
82−
83−remotable [ -- Functionals (predefined)
84− 'const
85− , 'flip
86− , 'fst
87− , 'snd
88− -- Functionals (defined above)
89− , 'compose
90− , 'first
91− , 'second
92− , 'split
93− -- Constants
94− , 'unit
95− -- Explicit dictionaries
96− , 'decodeDict
97− -- Serialization dictionaries
98− , 'sdictUnit_
99− , 'sdictProcessId_
100− , 'sdictSendPort_
101− ]
102−
103−--------------------------------------------------------------------------------
104−-- Static versions of the functionals --
105−-- (We give these explicit names because they are useful outside this module) --
106−--------------------------------------------------------------------------------
107−
108−-- | Static version of 'const'
109−staticConst :: (Typeable a, Typeable b) => Static (a -> b -> a)
110−staticConst = $(mkStatic 'const)
111−
112−-- | Static version of 'flip'
113−staticFlip :: (Typeable a, Typeable b, Typeable c)
114− => Static (a -> b -> c) -> Static (b -> a -> c)
115−staticFlip f = $(mkStatic 'flip) `staticApply` f
116−
117−-- | Static version of 'fst'
118−staticFst :: (Typeable a, Typeable b)
119− => Static ((a, b) -> a)
120−staticFst = $(mkStatic 'fst)
121−
122−-- | Static version of 'snd'
123−staticSnd :: (Typeable a, Typeable b)
124− => Static ((a, b) -> b)
125−staticSnd = $(mkStatic 'snd)
126−
127−-- | Static version of ('Prelude..')
128−staticCompose :: (Typeable a, Typeable b, Typeable c)
129− => Static (b -> c) -> Static (a -> b) -> Static (a -> c)
130−staticCompose f x = $(mkStatic 'compose) `staticApply` f `staticApply` x
131−
132−-- | Static version of 'Control.Arrow.first'
133−staticFirst :: (Typeable a, Typeable b, Typeable c)
134− => Static ((a -> b) -> (a, c) -> (b, c))
135−staticFirst = $(mkStatic 'first)
136−
137−-- | Static version of 'Control.Arrow.second'
138−staticSecond :: (Typeable a, Typeable b, Typeable c)
139− => Static ((a -> b) -> (c, a) -> (c, b))
140−staticSecond = $(mkStatic 'second)
141−
142−-- | Static version of ('Control.Arrow.***')
143−staticSplit :: (Typeable a, Typeable b, Typeable c, Typeable d)
144− => Static (a -> c) -> Static (b -> d) -> Static ((a, b) -> (c, d))
145−staticSplit f g = $(mkStatic 'split) `staticApply` f `staticApply` g
146−
147−--------------------------------------------------------------------------------
148−-- Constants --
149−--------------------------------------------------------------------------------
150−
151−-- | Static version of '()'
152−staticUnit :: Static ()
153−staticUnit = $(mkStatic 'unit)
154−
155−--------------------------------------------------------------------------------
156−-- Dictionaries --
157−--------------------------------------------------------------------------------
158−
159−-- | Serialization dictionary for '()'
160−sdictUnit :: Static (SerializableDict ())
161−sdictUnit = $(mkStatic 'sdictUnit_)
162−
163−-- | Serialization dictionary for 'ProcessId'
164−sdictProcessId :: Static (SerializableDict ProcessId)
165−sdictProcessId = $(mkStatic 'sdictProcessId_)
166−
167−-- | Serialization dictionary for 'SendPort'
168−sdictSendPort :: Typeable a
169− => Static (SerializableDict a) -> Static (SerializableDict (SendPort a))
170−sdictSendPort = staticApply $(mkStatic 'sdictSendPort_)
171−
172−--------------------------------------------------------------------------------
173−-- Creating closures --
174−--------------------------------------------------------------------------------
175−
176−-- | Static decoder, given a static serialization dictionary.
177−--
178−-- See module documentation of "Control.Distributed.Process.Closure" for an
179−-- example.
180−staticDecode :: Typeable a => Static (SerializableDict a) -> Static (ByteString -> a)
181−staticDecode dict = $(mkStatic 'decodeDict) `staticApply` dict
182−
183−-- | Convert a static value into a closure.
184−staticClosure :: forall a. Typeable a => Static a -> Closure a
185−staticClosure static = Closure (staticConst `staticApply` static) empty
186−
187−-- | Convert a serializable value into a closure.
188−toClosure :: forall a. Serializable a
189− => Static (SerializableDict a) -> a -> Closure a
190−toClosure dict x = Closure (staticDecode dict) (encode x)
distributed-process/src/Control/Distributed/Process/Internal/Closure/TH.hs+22−20
@@ -1,7 +1,6 @@
11-- | Template Haskell support
22--
33-- (In a separate file for convenience)
4−{-# LANGUAGE MagicHash #-}
54module Control.Distributed.Process.Internal.Closure.TH
65 ( -- * User-level API
76 remotable
@@ -11,8 +10,6 @@ module Control.Distributed.Process.Internal.Closure.TH
1110 ) where
1211
1312import Prelude hiding (lookup)
14−import Data.Accessor ((^=))
15−import Data.Typeable (typeOf)
1613import Control.Applicative ((<$>))
1714import Language.Haskell.TH
1815 ( -- Q monad and operations
@@ -42,6 +39,21 @@ import Language.Haskell.TH
4239 , funD
4340 , sigD
4441 )
42+
43+import Control.Distributed.Process.Internal.Types (Process)
44+import Control.Distributed.Process.Serializable
45+ ( SerializableDict(SerializableDict)
46+ )
47+import Control.Distributed.Static
48+ ( RemoteTable
49+ , toDyn
50+ , unsafeToDyn
51+ , registerStatic
52+ , Static
53+ , staticLabel
54+ )
55+
56+{-
4557import Control.Distributed.Process.Internal.Types
4658 ( RemoteTable
4759 , Static(Static)
@@ -50,11 +62,15 @@ import Control.Distributed.Process.Internal.Types
5062 , SerializableDict(SerializableDict)
5163 , Process
5264 )
65+-}
66+
67+{-
5368import Control.Distributed.Process.Internal.Dynamic
5469 ( Dynamic(..)
5570 , unsafeCoerce#
5671 , toDyn
5772 )
73+-}
5874
5975--------------------------------------------------------------------------------
6076-- User-level API --
@@ -141,9 +157,7 @@ generateDefs n = do
141157 static <- generateStatic origName typVars typ
142158 let dyn = case typVars of
143159 [] -> [| toDyn $(varE origName) |]
144− _ -> [| Dynamic (error "Polymorphic value")
145− (unsafeCoerce# $(varE origName))
146− |]
160+ _ -> [| unsafeToDyn $(varE origName) |]
147161 return ( static
148162 , [ [| registerStatic $(stringE (show origName)) $dyn |] ]
149163 )
@@ -156,10 +170,6 @@ generateDefs n = do
156170 , [ [| registerStatic $(stringE (show dictName)) $dyn |] ]
157171 )
158172
159−
160−registerStatic :: String -> Dynamic -> RemoteTable -> RemoteTable
161−registerStatic label dyn = remoteTableLabel label ^= Just dyn
162−
163173-- | Generate a static value
164174generateStatic :: Name -> [TyVarBndr] -> Type -> Q [Dec]
165175generateStatic n xs typ = do
@@ -170,11 +180,7 @@ generateStatic n xs typ = do
170180 (map typeable xs)
171181 (staticTyp `AppT` typ)
172182 )
173− , sfnD (staticName n)
174− [| Static $ StaticLabel
175− $(stringE (show n))
176− (typeOf (undefined :: $(return typ)))
177− |]
183+ , sfnD (staticName n) [| staticLabel $(stringE (show n)) |]
178184 ]
179185 where
180186 typeable :: TyVarBndr -> Pred
@@ -186,11 +192,7 @@ generateDict :: Name -> Type -> Q [Dec]
186192generateDict n typ = do
187193 sequence
188194 [ sigD n $ [t| Static (SerializableDict $(return typ)) |]
189− , sfnD n
190− [| Static $ StaticLabel
191− $(stringE (show n))
192− (typeOf (undefined :: SerializableDict $(return typ)))
193− |]
195+ , sfnD n [| staticLabel $(stringE (show n)) |]
194196 ]
195197
196198staticName :: Name -> Name
distributed-process/src/Control/Distributed/Process/Internal/Dynamic.hsdeleted−112
@@ -1,112 +0,0 @@
1−-- | Reimplementation of Dynamic that supports dynBind
2−--
3−-- We don't have access to the internal representation of Dynamic, otherwise
4−-- we would not have to redefine it completely. Note that we use this only
5−-- internally, so the incompatibility with "our" Dynamic from the standard
6−-- Dynamic is not important.
7−{-# LANGUAGE MagicHash #-}
8−module Control.Distributed.Process.Internal.Dynamic
9− ( Dynamic(..)
10− , toDyn
11− , fromDyn
12− , fromDynamic
13− , dynTypeRep
14− , dynApply
15− , dynApp
16− , dynBind
17− , dynBind'
18− , dynKleisli
19− , GHC.unsafeCoerce#
20− ) where
21−
22−import Data.Typeable
23− ( Typeable
24− , TypeRep
25− , typeOf
26− , funResultTy
27− , TyCon
28− , splitTyConApp
29− , mkFunTy
30− )
31−import Data.Typeable.Internal (funTc)
32−import qualified GHC.Prim as GHC (Any, unsafeCoerce#)
33−import Data.Maybe (fromMaybe)
34−
35−data Dynamic = Dynamic TypeRep GHC.Any
36− deriving Typeable
37−
38−toDyn :: Typeable a => a -> Dynamic
39−toDyn x = Dynamic (typeOf x) (GHC.unsafeCoerce# x)
40−
41−fromDyn :: Typeable a => Dynamic -> a -> a
42−fromDyn (Dynamic rep val) a =
43− if rep == typeOf a
44− then GHC.unsafeCoerce# val
45− else a
46−
47−fromDynamic :: forall a. Typeable a => Dynamic -> Maybe a
48−fromDynamic (Dynamic rep val) =
49− if rep == typeOf (undefined :: a)
50− then Just (GHC.unsafeCoerce# val)
51− else Nothing
52−
53−dynTypeRep :: Dynamic -> TypeRep
54−dynTypeRep (Dynamic t _) = t
55−
56−instance Show Dynamic where
57− show = show . dynTypeRep
58−
59−dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
60−dynApply (Dynamic t1 f) (Dynamic t2 x) =
61− case funResultTy t1 t2 of
62− Just t3 -> Just (Dynamic t3 (GHC.unsafeCoerce# f x))
63− Nothing -> Nothing
64−
65−dynApp :: Dynamic -> Dynamic -> Dynamic
66−dynApp f x = fromMaybe (error typeError) (dynApply f x)
67− where
68− typeError = "Type error in dynamic application.\n"
69− ++ "Can't apply function " ++ show f
70− ++ " to argument " ++ show x
71−
72−dynBind :: TyCon -> (forall a b. m a -> (a -> m b) -> m b) -> Dynamic -> Dynamic -> Maybe Dynamic
73−dynBind m bind (Dynamic t1 x) (Dynamic t2 f) =
74− case splitTyConApp t1 of
75− (m', [a]) | m' == m ->
76− case funResultTy t2 a of
77− Just mb -> Just (Dynamic mb (GHC.unsafeCoerce# bind x f))
78− _ -> Nothing
79− _ -> Nothing
80−
81−dynBind' :: TyCon -> (forall a b. m a -> (a -> m b) -> m b) -> Dynamic -> Dynamic -> Dynamic
82−dynBind' m bind x f = fromMaybe (error typeError) (dynBind m bind x f)
83− where
84− typeError = "Type error in dynamic bind.\nCan't bind " ++ show x ++ " to " ++ show f
85−
86−
87−
88−
89−-- | Dynamically typed Kleisli composition
90−dynKleisli :: TyCon
91− -> (forall a b c. (a -> m b) -> (b -> m c) -> a -> m c)
92− -> Dynamic
93− -> Dynamic
94− -> Maybe Dynamic
95−dynKleisli m comp (Dynamic tf f) (Dynamic tg g) =
96− case splitTyConApp tf of
97− (arr1, [a, mb]) | arr1 == funTc ->
98− case splitTyConApp tg of
99− (arr2, [b, mc]) | arr2 == funTc ->
100− case splitTyConApp mb of
101− (m', [b']) | m' == m && b' == b ->
102− case splitTyConApp mc of
103− (m'', [_c]) | m'' == m ->
104− Just (Dynamic (mkFunTy a mc) (GHC.unsafeCoerce# comp f g))
105− _ ->
106− Nothing
107− _ ->
108− Nothing
109− _ ->
110− Nothing
111− _ ->
112− Nothing
distributed-process/src/Control/Distributed/Process/Internal/Primitives.hs+9−4
@@ -90,13 +90,18 @@ import Control.Concurrent.STM
9090import Control.Distributed.Process.Internal.CQueue (dequeue, BlockSpec(..))
9191import Control.Distributed.Process.Serializable (Serializable, fingerprint)
9292import Data.Accessor ((^.), (^:), (^=))
93+import Control.Distributed.Static
94+ ( Closure(Closure)
95+ , resolveClosure
96+ , fromDyn
97+ , dynTypeRep
98+ )
9399import Control.Distributed.Process.Internal.Types
94100 ( NodeId(..)
95101 , ProcessId(..)
96102 , LocalNode(..)
97103 , LocalProcess(..)
98104 , Process(..)
99− , Closure(..)
100105 , Message(..)
101106 , MonitorRef(..)
102107 , SpawnRef(..)
@@ -104,7 +109,6 @@ import Control.Distributed.Process.Internal.Types
104109 , ProcessSignal(..)
105110 , monitorCounter
106111 , spawnCounter
107− , Closure(..)
108112 , SendPort(..)
109113 , ReceivePort(..)
110114 , channelCounter
@@ -121,8 +125,9 @@ import Control.Distributed.Process.Internal.Types
121125 , runLocalProcess
122126 )
123127import Control.Distributed.Process.Internal.Node (sendMessage, sendBinary)
124−import Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure)
125−import Control.Distributed.Process.Internal.Dynamic (fromDyn, dynTypeRep)
128+
129+-- import Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure)
130+-- import Control.Distributed.Process.Internal.Dynamic (fromDyn, dynTypeRep)
126131
127132--------------------------------------------------------------------------------
128133-- Basic messaging --
distributed-process/src/Control/Distributed/Process/Internal/Types.hs+6−107
@@ -3,7 +3,6 @@
33-- We collect all types used internally in a single module because
44-- many of these data types are mutually recursive and cannot be split across
55-- modules.
6−{-# LANGUAGE MagicHash #-}
76module Control.Distributed.Process.Internal.Types
87 ( -- * Node and process identifiers
98 NodeId(..)
@@ -24,16 +23,6 @@ module Control.Distributed.Process.Internal.Types
2423 , TypedChannel(..)
2524 , SendPort(..)
2625 , ReceivePort(..)
27− -- * Closures
28− , StaticLabel(..)
29− , Static(..)
30− , staticApply
31− , staticDuplicate
32− , staticTypeOf
33− , typeOfStaticLabel
34− , Closure(..)
35− , RemoteTable(..)
36− , SerializableDict(..)
3726 -- * Messages
3827 , Message(..)
3928 , createMessage
@@ -70,15 +59,12 @@ module Control.Distributed.Process.Internal.Types
7059 , channelCounter
7160 , typedChannels
7261 , typedChannelWithId
73− , remoteTableLabels
74− , remoteTableLabel
7562 ) where
7663
7764import Data.Map (Map)
7865import Data.Int (Int32)
79−import Data.Maybe (fromJust)
80−import Data.Typeable (Typeable, TypeRep, typeOf, funResultTy)
81−import Data.Binary (Binary(put, get), putWord8, getWord8, encode, Put, Get)
66+import Data.Typeable (Typeable)
67+import Data.Binary (Binary(put, get), putWord8, getWord8, encode)
8268import qualified Data.ByteString as BSS (ByteString, concat)
8369import qualified Data.ByteString.Lazy as BSL
8470 ( ByteString
@@ -108,8 +94,10 @@ import Control.Distributed.Process.Serializable
10894 , showFingerprint
10995 )
11096import Control.Distributed.Process.Internal.CQueue (CQueue)
111−import Control.Distributed.Process.Internal.Dynamic (Dynamic)
112−import Control.Distributed.Process.Internal.TypeRep (compareTypeRep) -- and Binary instances
97+import Control.Distributed.Static (RemoteTable, Closure)
98+
99+-- import Control.Distributed.Process.Internal.Dynamic (Dynamic)
100+-- import Control.Distributed.Process.Internal.TypeRep (compareTypeRep) -- and Binary instances
113101
114102--------------------------------------------------------------------------------
115103-- Node and process identifiers --
@@ -255,62 +243,6 @@ data ReceivePort a =
255243 | ReceivePortRR (TVar [ReceivePort a])
256244 deriving Typeable
257245
258−--------------------------------------------------------------------------------
259−-- Closures --
260−--------------------------------------------------------------------------------
261−
262−data StaticLabel =
263− StaticLabel String TypeRep
264− | StaticApply StaticLabel StaticLabel
265− | StaticDuplicate StaticLabel TypeRep
266− deriving (Typeable, Show)
267−
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.
277−newtype Static a = Static StaticLabel
278− deriving (Typeable, Show)
279−
280−-- | Apply two static values
281−staticApply :: Static (a -> b) -> Static a -> Static b
282−staticApply (Static f) (Static x) = Static (StaticApply f x)
283−
284−-- | Co-monadic 'duplicate' for static values
285−staticDuplicate :: forall a. Typeable a => Static a -> Static (Static a)
286−staticDuplicate (Static x) =
287− Static (StaticDuplicate x (typeOf (undefined :: Static a)))
288−
289−staticTypeOf :: forall a. Typeable a => a -> Static a
290−staticTypeOf _ = Static (StaticLabel "undefined" (typeOf (undefined :: a)))
291−
292−typeOfStaticLabel :: StaticLabel -> TypeRep
293−typeOfStaticLabel (StaticLabel _ typ)
294− = typ
295−typeOfStaticLabel (StaticApply f x)
296− = fromJust $ funResultTy (typeOfStaticLabel f) (typeOfStaticLabel x)
297−typeOfStaticLabel (StaticDuplicate _ typ)
298− = typ
299−
300−-- | A closure is a static value and an encoded environment
301−data Closure a = Closure (Static (BSL.ByteString -> a)) BSL.ByteString
302− deriving (Typeable, Show)
303−
304−-- | Runtime dictionary for 'unstatic' lookups
305−data RemoteTable = RemoteTable {
306− _remoteTableLabels :: Map String Dynamic
307− }
308−
309−-- | Reification of 'Serializable' (see "Control.Distributed.Process.Closure")
310−data SerializableDict a where
311− SerializableDict :: Serializable a => SerializableDict a
312− deriving (Typeable)
313−
314246--------------------------------------------------------------------------------
315247-- Messages --
316248--------------------------------------------------------------------------------
@@ -526,10 +458,6 @@ instance Binary DiedReason where
526458 4 -> return DiedUnknownId
527459 _ -> fail "DiedReason.get: invalid"
528460
529−instance Typeable a => Binary (Closure a) where
530− put (Closure static env) = put static >> put env
531− get = Closure <$> get <*> get
532−
533461instance Binary DidSpawn where
534462 put (DidSpawn ref pid) = put ref >> put pid
535463 get = DidSpawn <$> get <*> get
@@ -550,29 +478,6 @@ instance Binary Identifier where
550478 2 -> SendPortIdentifier <$> get
551479 _ -> fail "Identifier.get: invalid"
552480
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
570− get = do
571− label <- getStaticLabel
572− if typeOfStaticLabel label `compareTypeRep` typeOf (undefined :: a)
573− then return $ Static label
574− else fail "Static.get: type error"
575−
576481instance Binary WhereIsReply where
577482 put (WhereIsReply label mPid) = put label >> put mPid
578483 get = WhereIsReply <$> get <*> get
@@ -613,9 +518,3 @@ typedChannels = accessor _typedChannels (\cs st -> st { _typedChannels = cs })
613518
614519typedChannelWithId :: LocalSendPortId -> Accessor LocalProcessState (Maybe TypedChannel)
615520typedChannelWithId cid = typedChannels >>> DAC.mapMaybe cid
616−
617−remoteTableLabels :: Accessor RemoteTable (Map String Dynamic)
618−remoteTableLabels = accessor _remoteTableLabels (\ls tbl -> tbl { _remoteTableLabels = ls })
619−
620−remoteTableLabel :: String -> Accessor RemoteTable (Maybe Dynamic)
621−remoteTableLabel label = remoteTableLabels >>> DAC.mapMaybe label
distributed-process/src/Control/Distributed/Process/Node.hs+15−11
@@ -69,9 +69,14 @@ import qualified Network.Transport as NT
6969import Data.Accessor (Accessor, accessor, (^.), (^=), (^:))
7070import qualified Data.Accessor.Container as DAC (mapDefault, mapMaybe)
7171import System.Random (randomIO)
72−import Control.Distributed.Process.Internal.Types
72+import Control.Distributed.Static
7373 ( RemoteTable
74− , NodeId(..)
74+ , Closure(Closure)
75+ , resolveClosure
76+ , fromDynamic
77+ )
78+import Control.Distributed.Process.Internal.Types
79+ ( NodeId(..)
7580 , LocalProcessId(..)
7681 , ProcessId(..)
7782 , LocalNode(..)
@@ -98,7 +103,6 @@ import Control.Distributed.Process.Internal.Types
98103 , DidUnlinkPort(..)
99104 , SpawnRef
100105 , DidSpawn(..)
101− , Closure(..)
102106 , Message
103107 , TypedChannel(..)
104108 , Identifier(..)
@@ -107,31 +111,31 @@ import Control.Distributed.Process.Internal.Types
107111 , typedChannelWithId
108112 , WhereIsReply(..)
109113 , messageToPayload
110− , RemoteTable(..)
111114 , payloadToMessage
112115 , createMessage
113116 , runLocalProcess
114117 )
115118import Control.Distributed.Process.Serializable (Serializable)
116−import Control.Distributed.Process.Internal.Dynamic (fromDynamic)
117−import Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure)
118119import Control.Distributed.Process.Internal.Node
119120 ( sendBinary
120121 , sendMessage
121122 , sendPayload
122123 )
123124import Control.Distributed.Process.Internal.Primitives (expect, register, finally)
124−import qualified Control.Distributed.Process.Internal.Closure.Static as Static (__remoteTable)
125−import qualified Control.Distributed.Process.Internal.Closure.CP as CP (__remoteTable)
125+import qualified Control.Distributed.Process.Internal.Closure.BuiltIn as BuiltIn (remoteTable)
126+import qualified Control.Distributed.Static as Static (initRemoteTable)
127+
128+-- import Control.Distributed.Process.Internal.Dynamic (fromDynamic)
129+-- import Control.Distributed.Process.Internal.Closure.Resolution (resolveClosure)
130+-- import qualified Control.Distributed.Process.Internal.Closure.Static as Static (__remoteTable)
131+-- import qualified Control.Distributed.Process.Internal.Closure.CP as CP (__remoteTable)
126132
127133--------------------------------------------------------------------------------
128134-- Initialization --
129135--------------------------------------------------------------------------------
130136
131137initRemoteTable :: RemoteTable
132−initRemoteTable = Static.__remoteTable
133− . CP.__remoteTable
134− $ RemoteTable Map.empty
138+initRemoteTable = BuiltIn.remoteTable Static.initRemoteTable
135139
136140-- | Initialize a new local node.
137141newLocalNode :: NT.Transport -> RemoteTable -> IO LocalNode
distributed-process/src/Control/Distributed/Process/Serializable.hs+6
@@ -6,6 +6,7 @@ module Control.Distributed.Process.Serializable
66 , sizeOfFingerprint
77 , Fingerprint
88 , showFingerprint
9+ , SerializableDict(SerializableDict)
910 ) where
1011
1112import Data.Binary (Binary)
@@ -23,6 +24,11 @@ import qualified Data.ByteString.Internal as BSI ( unsafeCreate
2324import Foreign.Storable (pokeByteOff, peekByteOff, sizeOf)
2425import Foreign.ForeignPtr (withForeignPtr)
2526
27+-- | Reification of 'Serializable' (see "Control.Distributed.Process.Closure")
28+data SerializableDict a where
29+ SerializableDict :: Serializable a => SerializableDict a
30+ deriving (Typeable)
31+
2632-- | Objects that can be sent across the network
2733class (Binary a, Typeable a) => Serializable a
2834instance (Binary a, Typeable a) => Serializable a
distributed-process/tests/TestClosure.hs+6−6
@@ -12,7 +12,7 @@ import Network.Transport.TCP (createTransport, defaultTCPParameters)
1212import Control.Distributed.Process
1313import Control.Distributed.Process.Closure
1414import Control.Distributed.Process.Node
15−import Control.Distributed.Process.Internal.Types (Static(Static), StaticLabel(StaticLabel))
15+import Control.Distributed.Static (staticLabel)
1616import TestAuxiliary
1717
1818sdictInt :: SerializableDict Int
@@ -71,13 +71,13 @@ sendPidClosure :: ProcessId -> Closure (Process ())
7171sendPidClosure = $(mkClosure 'sendPid)
7272
7373sendFac :: Int -> ProcessId -> Closure (Process ())
74−sendFac n pid = factorialClosure n `cpBind` cpSend $(mkStatic 'sdictInt) pid
74+sendFac n pid = factorialClosure n `bindCP` cpSend $(mkStatic 'sdictInt) pid
7575
7676factorialOf :: Closure (Int -> Process Int)
7777factorialOf = staticClosure $(mkStatic 'factorial)
7878
7979factorial' :: Int -> Closure (Process Int)
80−factorial' n = cpReturn $(mkStatic 'sdictInt) n `cpBind` factorialOf
80+factorial' n = returnCP $(mkStatic 'sdictInt) n `bindCP` factorialOf
8181
8282waitClosure :: Int -> Closure (Process ())
8383waitClosure = $(mkClosure 'wait)
@@ -229,7 +229,7 @@ testSeq transport rtable = do
229229 node <- newLocalNode transport rtable
230230 runProcess node $ do
231231 us <- getSelfPid
232− join . unClosure $ sendFac 5 us `cpSeq` sendFac 6 us
232+ join . unClosure $ sendFac 5 us `seqCP` sendFac 6 us
233233 120 :: Int <- expect
234234 720 :: Int <- expect
235235 return ()
@@ -273,7 +273,7 @@ testSpawnInvalid :: Transport -> RemoteTable -> IO ()
273273testSpawnInvalid transport rtable = do
274274 node <- newLocalNode transport rtable
275275 runProcess node $ do
276− (pid, ref) <- spawnMonitor (localNodeId node) (Closure (Static (StaticLabel "ThisDoesNotExist" (typeOf ()))) empty)
276+ (pid, ref) <- spawnMonitor (localNodeId node) (Closure (staticLabel "ThisDoesNotExist") empty)
277277 ProcessMonitorNotification ref' pid' _reason <- expect
278278 -- Depending on the exact interleaving, reason might be NoProc or the exception thrown by the absence of the static closure
279279 True <- return $ ref' == ref && pid == pid'
@@ -285,7 +285,7 @@ testClosureExpect transport rtable = do
285285 runProcess node $ do
286286 nodeId <- getSelfNode
287287 us <- getSelfPid
288− them <- spawn nodeId $ cpExpect $(mkStatic 'sdictInt) `cpBind` cpSend $(mkStatic 'sdictInt) us
288+ them <- spawn nodeId $ cpExpect $(mkStatic 'sdictInt) `bindCP` cpSend $(mkStatic 'sdictInt) us
289289 send them (1234 :: Int)
290290 (1234 :: Int) <- expect
291291 return ()
distributed-static/LICENSEnew file+30
@@ -0,0 +1,30 @@
1+Copyright (c) 2012, Edsko de Vries
2+
3+All rights reserved.
4+
5+Redistribution and use in source and binary forms, with or without
6+modification, are permitted provided that the following conditions are met:
7+
8+ * Redistributions of source code must retain the above copyright
9+ notice, this list of conditions and the following disclaimer.
10+
11+ * Redistributions in binary form must reproduce the above
12+ copyright notice, this list of conditions and the following
13+ disclaimer in the documentation and/or other materials provided
14+ with the distribution.
15+
16+ * Neither the name of Edsko de Vries nor the names of other
17+ contributors may be used to endorse or promote products derived
18+ from this software without specific prior written permission.
19+
20+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
distributed-static/Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
distributed-static/distributed-static.cabalnew file+29
@@ -0,0 +1,29 @@
1+Name: distributed-static
2+Version: 0.1.0.0
3+Synopsis: Workaround the absence of "static" in ghc
4+-- description:
5+Homepage: http://www.github.com/haskell-distributed/distributed-process
6+License: BSD3
7+License-File: LICENSE
8+Author: Edsko de Vries
9+Maintainer: edsko@well-typed.com
10+Copyright: Well-Typed LLP
11+Category: Control
12+Build-Type: Simple
13+Cabal-Version: >=1.8
14+
15+Library
16+ Exposed-Modules: Control.Distributed.Static,
17+ Control.Distributed.Static.Internal.Dynamic,
18+ Control.Distributed.Static.Internal.TypeRep
19+ Build-Depends: base ==4.5.*,
20+ containers >= 0.4 && < 0.5,
21+ bytestring >= 0.0 && < 0.11,
22+ binary >= 0.5 && < 0.6,
23+ ghc-prim >= 0.2 && < 0.3
24+ HS-Source-Dirs: src
25+ Extensions: DeriveDataTypeable,
26+ ScopedTypeVariables,
27+ RankNTypes,
28+ CPP
29+ GHC-Options: -Wall
distributed-static/src/Control/Distributed/Static.hsnew file+352
@@ -0,0 +1,352 @@
1+-- | /Towards Haskell in the Cloud/ introduces a new typing construct called
2+-- @static@. Unfortunately, ghc does not yet include support for @static@. In
3+-- this module we provide a workaround, which at the same time also extends
4+-- the functionality of @static@ as described in the paper and makes it more
5+-- expressive.
6+--
7+-- The main idea (already discussed in /Towards Haskell in the Cloud/, section
8+-- /Faking It/) is to maintain a runtime mapping from labels (strings) to
9+-- values. A basic static value (introduced using 'staticLabel') then is an
10+-- index into this runtime mapping. It is the responsibility of the client code
11+-- to make sure that the corresponding value in the 'RemoteTable' matches the
12+-- type of the label, although we do runtime type checks where possible. For
13+-- this reason, we only work with 'Typeable' values in this module.
14+module Control.Distributed.Static
15+ ( -- * Introducing static values
16+ Static
17+ , staticLabel
18+ , staticApply
19+ , staticDuplicate
20+ , staticTypeOf
21+ -- * Eliminating static values
22+ , RemoteTable
23+ , initRemoteTable
24+ , registerStatic
25+ , resolveStatic
26+ -- * Closures
27+ , Closure(Closure)
28+ , staticClosure
29+ , resolveClosure
30+ -- * Static values
31+ , idStatic
32+ , composeStatic
33+ , constStatic
34+ , flipStatic
35+ , fstStatic
36+ , sndStatic
37+ , firstStatic
38+ , secondStatic
39+ , splitStatic
40+ , unitStatic
41+ , appStatic
42+ -- * Combinators on static values
43+ , staticCompose
44+ , staticSplit
45+ , staticConst
46+ -- * Combinators on closures
47+ , closureApplyStatic
48+ , closureApply
49+ , closureCompose
50+ , closureSplit
51+ -- * Re-exports
52+ , Dynamic
53+ , toDyn
54+ , unsafeToDyn
55+ , fromDyn
56+ , fromDynamic
57+ , dynTypeRep
58+ ) where
59+
60+import Prelude hiding (id, (.))
61+import Data.Typeable
62+ ( Typeable
63+ , TypeRep
64+ , typeOf
65+ , funResultTy
66+ )
67+import Data.Maybe (fromJust)
68+import Data.Binary
69+ ( Binary(get, put)
70+ , Put
71+ , Get
72+ , putWord8
73+ , getWord8
74+ , encode
75+ , decode
76+ )
77+import Data.ByteString.Lazy (ByteString, empty)
78+import Data.Map (Map)
79+import qualified Data.Map as Map (lookup, empty, insert)
80+import Control.Applicative ((<$>), (<*>))
81+import Control.Category (Category(id, (.)))
82+import qualified Control.Arrow as Arrow (first, second, (***), app)
83+import Control.Distributed.Static.Internal.Dynamic
84+ ( Dynamic
85+ , dynApply
86+ , toDyn
87+ , unsafeToDyn
88+ , fromDyn
89+ , dynTypeRep
90+ , fromDynamic
91+ , unsafeCastDyn
92+ )
93+import Control.Distributed.Static.Internal.TypeRep (compareTypeRep)
94+
95+--------------------------------------------------------------------------------
96+-- Introducing static values --
97+--------------------------------------------------------------------------------
98+
99+data StaticLabel =
100+ StaticLabel String TypeRep
101+ | StaticApply StaticLabel StaticLabel
102+ | StaticDuplicate StaticLabel TypeRep
103+ deriving (Typeable, Show)
104+
105+-- | A static value. Static is opaque; see 'staticLabel', 'staticApply',
106+-- 'staticDuplicate' or 'staticTypeOf'.
107+newtype Static a = Static StaticLabel
108+ deriving (Typeable, Show)
109+
110+instance Typeable a => Binary (Static a) where
111+ put (Static label) = putStaticLabel label
112+ get = do
113+ label <- getStaticLabel
114+ if typeOfStaticLabel label `compareTypeRep` typeOf (undefined :: a)
115+ then return $ Static label
116+ else fail "Static.get: type error"
117+
118+-- We don't want StaticLabel to be its own Binary instance
119+putStaticLabel :: StaticLabel -> Put
120+putStaticLabel (StaticLabel string typ) =
121+ putWord8 0 >> put string >> put typ
122+putStaticLabel (StaticApply label1 label2) =
123+ putWord8 1 >> putStaticLabel label1 >> putStaticLabel label2
124+putStaticLabel (StaticDuplicate label typ) =
125+ putWord8 2 >> putStaticLabel label >> put typ
126+
127+getStaticLabel :: Get StaticLabel
128+getStaticLabel = do
129+ header <- getWord8
130+ case header of
131+ 0 -> StaticLabel <$> get <*> get
132+ 1 -> StaticApply <$> getStaticLabel <*> getStaticLabel
133+ 2 -> StaticDuplicate <$> getStaticLabel <*> get
134+ _ -> fail "StaticLabel.get: invalid"
135+
136+-- | Create a primitive static value.
137+--
138+-- It is the responsibility of the client code to make sure the corresponding
139+-- entry in the 'RemoteTable' has the appropriate type.
140+staticLabel :: forall a. Typeable a => String -> Static a
141+staticLabel label = Static (StaticLabel label (typeOf (undefined :: a)))
142+
143+-- | Apply two static values
144+staticApply :: Static (a -> b) -> Static a -> Static b
145+staticApply (Static f) (Static x) = Static (StaticApply f x)
146+
147+-- | Co-monadic 'duplicate' for static values
148+staticDuplicate :: forall a. Typeable a => Static a -> Static (Static a)
149+staticDuplicate (Static x) =
150+ Static (StaticDuplicate x (typeOf (undefined :: Static a)))
151+
152+-- | @staticTypeOf (x :: a)@ mimicks @static (undefined :: a)@ -- even if
153+-- @x@ is not static, the type of @x@ always is.
154+staticTypeOf :: forall a. Typeable a => a -> Static a
155+staticTypeOf _ = Static (StaticLabel "$undefined" (typeOf (undefined :: a)))
156+
157+typeOfStaticLabel :: StaticLabel -> TypeRep
158+typeOfStaticLabel (StaticLabel _ typ)
159+ = typ
160+typeOfStaticLabel (StaticApply f x)
161+ = fromJust $ funResultTy (typeOfStaticLabel f) (typeOfStaticLabel x)
162+typeOfStaticLabel (StaticDuplicate _ typ)
163+ = typ
164+
165+--------------------------------------------------------------------------------
166+-- Eliminating static values --
167+--------------------------------------------------------------------------------
168+
169+-- | Runtime dictionary for 'unstatic' lookups
170+newtype RemoteTable = RemoteTable (Map String Dynamic)
171+
172+-- | Initial remote table
173+initRemoteTable :: RemoteTable
174+initRemoteTable =
175+ registerStatic "$id" (unsafeToDyn identity)
176+ . registerStatic "$compose" (unsafeToDyn compose)
177+ . registerStatic "$const" (unsafeToDyn const)
178+ . registerStatic "$flip" (unsafeToDyn flip)
179+ . registerStatic "$fst" (unsafeToDyn fst)
180+ . registerStatic "$snd" (unsafeToDyn snd)
181+ . registerStatic "$first" (unsafeToDyn first)
182+ . registerStatic "$second" (unsafeToDyn second)
183+ . registerStatic "$split" (unsafeToDyn split)
184+ . registerStatic "$unit" (toDyn ())
185+ . registerStatic "$app" (unsafeToDyn app)
186+ . registerStatic "$decodeEnvPair" (toDyn decodeEnvPair)
187+ $ RemoteTable Map.empty
188+ where
189+ identity :: a -> a
190+ identity = id
191+
192+ compose :: (b -> c) -> (a -> b) -> a -> c
193+ compose = (.)
194+
195+ first :: (a -> b) -> (a, c) -> (b, c)
196+ first = Arrow.first
197+
198+ second :: (a -> b) -> (c, a) -> (c, b)
199+ second = Arrow.second
200+
201+ split :: (a -> b) -> (a' -> b') -> (a, a') -> (b, b')
202+ split = (Arrow.***)
203+
204+ decodeEnvPair :: ByteString -> (ByteString, ByteString)
205+ decodeEnvPair = decode
206+
207+ app :: (a -> b, a) -> b
208+ app = Arrow.app
209+
210+-- | Register a static label
211+registerStatic :: String -> Dynamic -> RemoteTable -> RemoteTable
212+registerStatic label dyn (RemoteTable rtable)
213+ = RemoteTable (Map.insert label dyn rtable)
214+
215+-- | Resolve a Static value.
216+resolveStatic :: RemoteTable -> Static a -> Maybe Dynamic
217+resolveStatic (RemoteTable rtable) (Static (StaticLabel string typ)) = do
218+ unsafeCastDyn (const typ) <$> Map.lookup string rtable
219+resolveStatic rtable (Static (StaticApply static1 static2)) = do
220+ f <- resolveStatic rtable (Static static1)
221+ x <- resolveStatic rtable (Static static2)
222+ f `dynApply` x
223+resolveStatic _rtable (Static (StaticDuplicate static typ)) =
224+ return . unsafeCastDyn (const typ) $ unsafeToDyn (Static static)
225+
226+--------------------------------------------------------------------------------
227+-- Closures --
228+--------------------------------------------------------------------------------
229+
230+-- | A closure is a static value and an encoded environment
231+data Closure a = Closure (Static (ByteString -> a)) ByteString
232+ deriving (Typeable, Show)
233+
234+instance Typeable a => Binary (Closure a) where
235+ put (Closure static env) = put static >> put env
236+ get = Closure <$> get <*> get
237+
238+-- | Convert a static value into a closure.
239+staticClosure :: forall a. Typeable a => Static a -> Closure a
240+staticClosure static = Closure (staticConst static) empty
241+
242+-- | Resolve a Closure
243+resolveClosure :: RemoteTable -> Static a -> ByteString -> Maybe Dynamic
244+resolveClosure rtable static env = do
245+ decoder <- resolveStatic rtable static
246+ decoder `dynApply` toDyn env
247+
248+--------------------------------------------------------------------------------
249+-- Predefined static values --
250+--------------------------------------------------------------------------------
251+
252+-- | Static version of 'id'
253+idStatic :: (Typeable a)
254+ => Static (a -> a)
255+idStatic = staticLabel "$id"
256+
257+-- | Static version of ('Prelude..')
258+composeStatic :: (Typeable a, Typeable b, Typeable c)
259+ => Static ((b -> c) -> (a -> b) -> a -> c)
260+composeStatic = staticLabel "$compose"
261+
262+-- | Static version of 'const'
263+constStatic :: (Typeable a, Typeable b)
264+ => Static (a -> b -> a)
265+constStatic = staticLabel "$const"
266+
267+-- | Static version of 'flip'
268+flipStatic :: (Typeable a, Typeable b, Typeable c)
269+ => Static ((a -> b -> c) -> b -> a -> c)
270+flipStatic = staticLabel "$flip"
271+
272+-- | Static version of 'fst'
273+fstStatic :: (Typeable a, Typeable b)
274+ => Static ((a, b) -> a)
275+fstStatic = staticLabel "$fst"
276+
277+-- | Static version of 'snd'
278+sndStatic :: (Typeable a, Typeable b)
279+ => Static ((a, b) -> b)
280+sndStatic = staticLabel "$snd"
281+
282+-- | Static version of 'Arrow.first'
283+firstStatic :: (Typeable a, Typeable b, Typeable c)
284+ => Static ((a -> b) -> (a, c) -> (b, c))
285+firstStatic = staticLabel "$first"
286+
287+-- | Static version of 'Arrow.second'
288+secondStatic :: (Typeable a, Typeable b, Typeable c)
289+ => Static ((a -> b) -> (c, a) -> (c, b))
290+secondStatic = staticLabel "$second"
291+
292+-- | Static version of ('Arrow.***')
293+splitStatic :: (Typeable a, Typeable a', Typeable b, Typeable b')
294+ => Static ((a -> b) -> (a' -> b') -> (a, a') -> (b, b'))
295+splitStatic = staticLabel "$split"
296+
297+-- | Static version of @()@
298+unitStatic :: Static ()
299+unitStatic = staticLabel "$unit"
300+
301+-- | Static version of 'Arrow.app'
302+appStatic :: (Typeable a, Typeable b)
303+ => Static ((a -> b, a) -> b)
304+appStatic = staticLabel "$app"
305+
306+--------------------------------------------------------------------------------
307+-- Combinators on static values --
308+--------------------------------------------------------------------------------
309+
310+staticCompose :: (Typeable a, Typeable b, Typeable c)
311+ => Static (b -> c) -> Static (a -> b) -> Static (a -> c)
312+staticCompose g f = composeStatic `staticApply` g `staticApply` f
313+
314+staticSplit :: (Typeable a, Typeable a', Typeable b, Typeable b')
315+ => Static (a -> b) -> Static (a' -> b') -> Static ((a, a') -> (b, b'))
316+staticSplit f g = splitStatic `staticApply` f `staticApply` g
317+
318+staticConst :: (Typeable a, Typeable b)
319+ => Static a -> Static (b -> a)
320+staticConst x = constStatic `staticApply` x
321+
322+--------------------------------------------------------------------------------
323+-- Combinators on Closures --
324+--------------------------------------------------------------------------------
325+
326+closureApplyStatic :: forall a b. (Typeable a, Typeable b)
327+ => Static (a -> b) -> Closure a -> Closure b
328+closureApplyStatic f (Closure decoder env) =
329+ Closure (f `staticCompose` decoder) env
330+
331+decodeEnvPairStatic :: Static (ByteString -> (ByteString, ByteString))
332+decodeEnvPairStatic = staticLabel "$decodeEnvPair"
333+
334+closureApply :: forall a b. (Typeable a, Typeable b)
335+ => Closure (a -> b) -> Closure a -> Closure b
336+closureApply (Closure fdec fenv) (Closure xdec xenv) =
337+ Closure decoder (encode (fenv, xenv))
338+ where
339+ decoder :: Static (ByteString -> b)
340+ decoder = appStatic
341+ `staticCompose`
342+ (fdec `staticSplit` xdec)
343+ `staticCompose`
344+ decodeEnvPairStatic
345+
346+closureCompose :: (Typeable a, Typeable b, Typeable c)
347+ => Closure (b -> c) -> Closure (a -> b) -> Closure (a -> c)
348+closureCompose g f = composeStatic `closureApplyStatic` g `closureApply` f
349+
350+closureSplit :: (Typeable a, Typeable a', Typeable b, Typeable b')
351+ => Closure (a -> b) -> Closure (a' -> b') -> Closure ((a, a') -> (b, b'))
352+closureSplit f g = splitStatic `closureApplyStatic` f `closureApply` g
distributed-static/src/Control/Distributed/Static/Internal/Dynamic.hsnew file+121
@@ -0,0 +1,121 @@
1+module Control.Distributed.Static.Internal.Dynamic
2+ ( -- * The @Dynamic@ type
3+ Dynamic
4+ -- * Converting to and from @Dynamic@
5+ , toDyn
6+ , fromDyn
7+ , fromDynamic
8+ -- * Applying functions of dynamic type
9+ , dynApply
10+ , dynApp
11+ , dynTypeRep
12+ -- * Additions
13+ , unsafeToDyn
14+ , unsafeCastDyn
15+ ) where
16+
17+import Control.Exception (Exception)
18+import qualified GHC.Prim as GHC (Any)
19+import Data.Typeable (Typeable, TypeRep, typeOf, funResultTy)
20+import Unsafe.Coerce (unsafeCoerce)
21+
22+-------------------------------------------------------------
23+--
24+-- The type Dynamic
25+--
26+-------------------------------------------------------------
27+
28+{-|
29+ A value of type 'Dynamic' is an object encapsulated together with its type.
30+
31+ A 'Dynamic' may only represent a monomorphic value; an attempt to
32+ create a value of type 'Dynamic' from a polymorphically-typed
33+ expression will result in an ambiguity error (see 'toDyn').
34+
35+ 'Show'ing a value of type 'Dynamic' returns a pretty-printed representation
36+ of the object\'s type; useful for debugging.
37+-}
38+data Dynamic = Dynamic TypeRep Obj
39+ deriving Typeable
40+
41+instance Show Dynamic where
42+ -- the instance just prints the type representation.
43+ showsPrec _ (Dynamic t _) =
44+ showString "<<" .
45+ showsPrec 0 t .
46+ showString ">>"
47+
48+instance Exception Dynamic
49+
50+-- Use GHC's primitive 'Any' type to hold the dynamically typed value.
51+--
52+-- In GHC's new eval/apply execution model this type must not look
53+-- like a data type. If it did, GHC would use the constructor convention
54+-- when evaluating it, and this will go wrong if the object is really a
55+-- function. Using Any forces GHC to use
56+-- a fallback convention for evaluating it that works for all types.
57+type Obj = GHC.Any
58+
59+-- | Converts an arbitrary value into an object of type 'Dynamic'.
60+--
61+-- The type of the object must be an instance of 'Typeable', which
62+-- ensures that only monomorphically-typed objects may be converted to
63+-- 'Dynamic'. To convert a polymorphic object into 'Dynamic', give it
64+-- a monomorphic type signature. For example:
65+--
66+-- > toDyn (id :: Int -> Int)
67+--
68+toDyn :: Typeable a => a -> Dynamic
69+toDyn v = Dynamic (typeOf v) (unsafeCoerce v)
70+
71+-- | Converts a 'Dynamic' object back into an ordinary Haskell value of
72+-- the correct type. See also 'fromDynamic'.
73+fromDyn :: Typeable a
74+ => Dynamic -- ^ the dynamically-typed object
75+ -> a -- ^ a default value
76+ -> a -- ^ returns: the value of the first argument, if
77+ -- it has the correct type, otherwise the value of
78+ -- the second argument.
79+fromDyn (Dynamic t v) def
80+ | typeOf def == t = unsafeCoerce v
81+ | otherwise = def
82+
83+-- | Converts a 'Dynamic' object back into an ordinary Haskell value of
84+-- the correct type. See also 'fromDyn'.
85+fromDynamic
86+ :: Typeable a
87+ => Dynamic -- ^ the dynamically-typed object
88+ -> Maybe a -- ^ returns: @'Just' a@, if the dynamically-typed
89+ -- object has the correct type (and @a@ is its value),
90+ -- or 'Nothing' otherwise.
91+fromDynamic (Dynamic t v) =
92+ case unsafeCoerce v of
93+ r | t == typeOf r -> Just r
94+ | otherwise -> Nothing
95+
96+-- (f::(a->b)) `dynApply` (x::a) = (f a)::b
97+dynApply :: Dynamic -> Dynamic -> Maybe Dynamic
98+dynApply (Dynamic t1 f) (Dynamic t2 x) =
99+ case funResultTy t1 t2 of
100+ Just t3 -> Just (Dynamic t3 ((unsafeCoerce f) x))
101+ Nothing -> Nothing
102+
103+dynApp :: Dynamic -> Dynamic -> Dynamic
104+dynApp f x = case dynApply f x of
105+ Just r -> r
106+ Nothing -> error ("Type error in dynamic application.\n" ++
107+ "Can't apply function " ++ show f ++
108+ " to argument " ++ show x)
109+
110+dynTypeRep :: Dynamic -> TypeRep
111+dynTypeRep (Dynamic tr _) = tr
112+
113+--------------------------------------------------------------------------------
114+-- Additions --
115+--------------------------------------------------------------------------------
116+
117+unsafeToDyn :: a -> Dynamic
118+unsafeToDyn x = Dynamic (error "No type rep") (unsafeCoerce x)
119+
120+unsafeCastDyn :: (TypeRep -> TypeRep) -> Dynamic -> Dynamic
121+unsafeCastDyn f (Dynamic t x) = Dynamic (f t) x
distributed-process/src/Control/Distributed/Process/Internal/TypeRep.hs → distributed-static/src/Control/Distributed/Static/Internal/TypeRep.hsrenamed+1−1
@@ -1,6 +1,6 @@
11-- | 'Binary' instances for 'TypeRep', and 'TypeRep' equality (bug workaround)
22{-# OPTIONS_GHC -fno-warn-orphans #-}
3−module Control.Distributed.Process.Internal.TypeRep (compareTypeRep) where
3+module Control.Distributed.Static.Internal.TypeRep (compareTypeRep) where
44
55import Control.Applicative ((<$>), (<*>))
66import Data.Binary (Binary(get, put))