2-- | /Towards Haskell in the Cloud/ (Epstein et al., Haskell Symposium 2011)
3-- proposes a new type construct called 'static' that characterizes values that
4-- are known statically. Cloud Haskell uses the
5-- 'Control.Distributed.Static.Static' implementation from
6-- "Control.Distributed.Static". That module comes with its own extensive
7-- documentation, which you should read if you want to know the details. Here
8-- we explain the Template Haskell support only.
12-- Given a top-level (possibly polymorphic, but unqualified) definition
14-- > f :: forall a1 .. an. T
17-- you can use a Template Haskell splice to create a static version of 'f':
19-- > $(mkStatic 'f) :: forall a1 .. an. (Typeable a1, .., Typeable an) => Static T
21-- Every module that you write that contains calls to 'mkStatic' needs to
22-- have a call to 'remotable':
24-- > remotable [ 'f, 'g, ... ]
26-- where you must pass every function (or other value) that you pass as an
27-- argument to 'mkStatic'. The call to 'remotable' will create a definition
29-- > __remoteTable :: RemoteTable -> RemoteTable
31-- which can be used to construct the 'RemoteTable' used to initialize
32-- Cloud Haskell. You should have (at most) one call to 'remotable' per module,
33-- and compose all created functions when initializing Cloud Haskell:
35-- > let rtable :: RemoteTable
36-- > rtable = M1.__remoteTable
37-- > . M2.__remoteTable
39-- > . Mn.__remoteTable
42-- NOTE: If you get a type error from ghc along these lines
44-- > The exact Name `a_a30k' is not in scope
45-- > Probable cause: you used a unique name (NameU) in Template Haskell but did not bind it
47-- then you need to enable the @ScopedTypeVariables@ language extension.
49-- [Static serialization dictionaries]
51-- Some Cloud Haskell primitives require static serialization dictionaries (**):
53-- > call :: Serializable a => Static (SerializableDict a) -> NodeId -> Closure (Process a) -> Process a
55-- Given some serializable type 'T' you can define
57-- > sdictT :: SerializableDict T
58-- > sdictT = SerializableDict
62-- > $(mkStatic 'sdictT) :: Static (SerializableDict T)
64-- However, since these dictionaries are so frequently required Cloud Haskell
65-- provides special support for them. When you call 'remotable' on a
66-- /monomorphic/ function @f :: T1 -> T2@
70-- then a serialization dictionary is automatically created for you, which you
73-- > $(functionSDict 'f) :: Static (SerializableDict T1)
75-- In addition, if @f :: T1 -> Process T2@, then a second dictionary is created
77-- > $(functionTDict 'f) :: Static (SerializableDict T2)
81-- Suppose you have a process
83-- > isPrime :: Integer -> Process Bool
87-- > $(mkClosure 'isPrime) :: Integer -> Closure (Process Bool)
89-- which you can then 'call', for example, to have a remote node check if
92-- In general, if you have a /monomorphic/ function
98-- > $(mkClosure 'f) :: T1 -> Closure T2
100-- provided that 'T1' is serializable (*) (remember to pass 'f' to 'remotable').
102-- (You can also create closures manually--see the documentation of
103-- "Control.Distributed.Static" for examples.)
107-- Here is a small self-contained example that uses closures and serialization
108-- dictionaries. It makes use of the Control.Distributed.Process.SimpleLocalnet
109-- Cloud Haskell backend.
111-- > {-# LANGUAGE TemplateHaskell #-}
112-- > import System.Environment (getArgs)
113-- > import Control.Distributed.Process
114-- > import Control.Distributed.Process.Closure
115-- > import Control.Distributed.Process.Backend.SimpleLocalnet
116-- > import Control.Distributed.Process.Node (initRemoteTable)
118-- > isPrime :: Integer -> Process Bool
119-- > isPrime n = return . (n `elem`) . takeWhile (<= n) . sieve $ [2..]
121-- > sieve :: [Integer] -> [Integer]
122-- > sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0]
124-- > remotable ['isPrime]
126-- > master :: [NodeId] -> Process ()
127-- > master [] = liftIO $ putStrLn "no slaves"
128-- > master (slave:_) = do
129-- > isPrime79 <- call $(functionTDict 'isPrime) slave ($(mkClosure 'isPrime) (79 :: Integer))
130-- > liftIO $ print isPrime79
136-- > ["master", host, port] -> do
137-- > backend <- initializeBackend host port rtable
138-- > startMaster backend master
139-- > ["slave", host, port] -> do
140-- > backend <- initializeBackend host port rtable
141-- > startSlave backend
143-- > rtable :: RemoteTable
144-- > rtable = __remoteTable initRemoteTable
148-- (*) If 'T1' is not serializable you will get a type error in the generated
149-- code. Unfortunately, the Template Haskell infrastructure cannot check
150-- a priori if 'T1' is serializable or not due to a bug in the Template
151-- Haskell libraries (<http://hackage.haskell.org/trac/ghc/ticket/7066>)
153-- (**) Even though 'call' is passed an explicit serialization
154-- dictionary, we still need the 'Serializable' constraint because
155-- 'Static' is not the /true/ static. If it was, we could 'unstatic'
156-- the dictionary and pattern match on it to bring the 'Typeable'
157-- instance into scope, but unless proper 'static' support is added to
158-- ghc we need both the type class argument and the explicit dictionary.
159module Control.Distributed.Process.Closure
160 ( -- * Serialization dictionaries (and their static versions)
168 -- * The CP type and associated combinators
175 -- * CP versions of Cloud Haskell primitives
182 -- * Working with static values and closures (without Template Haskell)
189#ifdef TemplateHaskellSupport
190 -- * Template Haskell support for creating static values and closures
201import Control.Distributed.Process.Serializable (SerializableDict(..))
202import Control.Distributed.Process.Internal.Closure.BuiltIn
203 ( -- Static dictionaries and associated operations
210 -- The CP type and associated combinators
217 -- CP versions of Cloud Haskell primitives
225import Control.Distributed.Process.Internal.Closure.Explicit
234#ifdef TemplateHaskellSupport
235import Control.Distributed.Process.Internal.Closure.TH
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list