-- | Implementation of 'Closure' that works around the absence of 'static'. -- -- [Built-in closures] -- -- We offer a number of standard commonly useful closures. -- -- [Closure combinators] -- -- Closures combinators allow to create closures from other closures. For -- example, 'spawnSupervised' is defined as follows: -- -- > spawnSupervised :: NodeId -- > -> Closure (Process ()) -- > -> Process (ProcessId, MonitorRef) -- > spawnSupervised nid proc = do -- > us <- getSelfPid -- > them <- spawn nid (linkClosure us `cpSeq` proc) -- > ref <- monitor them -- > return (them, ref) -- -- [User-defined closures] -- -- Suppose we have a monomorphic function -- -- > addInt :: Int -> Int -> Int -- > addInt x y = x + y -- -- Then the Template Haskell splice -- -- > remotable ['addInt] -- -- creates a function -- -- > $(mkClosure 'addInt) :: Int -> Closure (Int -> Int) -- -- which can be used to partially apply 'addInt' and turn it into a 'Closure', -- which can be sent across the network. Closures can be deserialized with -- -- > unClosure :: Typeable a => Closure a -> Process a -- -- In general, given a monomorphic function @f :: a -> b@ the corresponding -- function @$(mkClosure 'f)@ will have type @a -> Closure b@. -- -- The call to 'remotable' will also generate a function -- -- > __remoteTable :: RemoteTable -> RemoteTable -- -- which can be used to construct the 'RemoteTable' used to initialize -- Cloud Haskell. You should have (at most) one call to 'remotable' per module, -- and compose all created functions when initializing Cloud Haskell: -- -- > let rtable = M1.__remoteTable -- > . M2.__remoteTable -- > . ... -- > . Mn.__remoteTable -- > $ initRemoteTable -- -- See Section 6, /Faking It/, of /Towards Haskell in the Cloud/ for more info. -- -- [Serializable Dictionaries] -- -- Some functions (such as 'sendClosure' or 'returnClosure') require an -- explicit (reified) serializable dictionary. To create such a dictionary do -- -- > serializableDictInt :: SerializableDict Int -- > serializableDictInt = SerializableDict -- -- and then pass @'serializableDictInt@ to 'remotable'. This will fail if the -- type is not serializable. module Control.Distributed.Process.Closure ( -- * User-defined closures remotable , mkClosure , SerializableDict(..) -- * Built-in closures , linkClosure , unlinkClosure , sendClosure , returnClosure , expectClosure -- * Generic closure combinators , closureApply , closureConst , closureUnit -- * Arrow combinators for processes , CP , cpIntro , cpElim , cpId , cpComp , cpFirst , cpSwap , cpSecond , cpPair , cpCopy , cpFanOut , cpLeft , cpMirror , cpRight , cpEither , cpUntag , cpFanIn , cpApply -- * Derived combinators for processes , cpBind , cpSeq ) where import Control.Distributed.Process.Internal.Types (SerializableDict(..)) import Control.Distributed.Process.Internal.Closure.TH (remotable, mkClosure) import Control.Distributed.Process.Internal.Closure.BuiltIn ( linkClosure , unlinkClosure , sendClosure , returnClosure , expectClosure ) import Control.Distributed.Process.Internal.Closure.Combinators ( -- Generic combinators closureApply , closureConst , closureUnit -- Arrow combinators for processes , CP , cpIntro , cpElim , cpId , cpComp , cpFirst , cpSwap , cpSecond , cpPair , cpCopy , cpFanOut , cpLeft , cpMirror , cpRight , cpEither , cpUntag , cpFanIn , cpApply -- Derived process operators , cpBind , cpSeq )