-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Compositional, type-safe, polymorphic static values and closures
--   
--   <i>Towards Haskell in the Cloud</i> (Epstein et al, Haskell Symposium
--   2011) introduces the concept of <i>static</i> values: values that are
--   known at compile time. In a distributed setting where all nodes are
--   running the same executable, static values can be serialized simply by
--   transmitting a code pointer to the value. This however requires
--   special compiler support, which is not yet available in ghc. We can
--   mimick the behaviour by keeping an explicit mapping
--   (<a>RemoteTable</a>) from labels to values (and making sure that all
--   distributed nodes are using the same <a>RemoteTable</a>). In this
--   module we implement this mimickry and various extensions: type safety
--   (including for polymorphic static values) and compositionality.
@package distributed-static
@version 0.3.8


-- | <i>Towards Haskell in the Cloud</i> (Epstein et al, Haskell Symposium
--   2011) introduces the concept of <i>static</i> values: values that are
--   known at compile time. In a distributed setting where all nodes are
--   running the same executable, static values can be serialized simply by
--   transmitting a code pointer to the value. This however requires
--   special compiler support, which is not yet available in ghc. We can
--   mimick the behaviour by keeping an explicit mapping
--   (<a>RemoteTable</a>) from labels to values (and making sure that all
--   distributed nodes are using the same <a>RemoteTable</a>). In this
--   module we implement this mimickry and various extensions.
--   
--   <ul>
--   <li><i>Compositionality</i></li>
--   </ul>
--   
--   Static values as described in the paper are not compositional: there
--   is no way to combine two static values and get a static value out of
--   it. This makes sense when interpreting static strictly as <i>known at
--   compile time</i>, but it severely limits expressiveness. However, the
--   main motivation for 'static' is not that they are known at compile
--   time but rather that <i>they provide a free</i> <a>Binary</a>
--   <i>instance</i>. We therefore provide two basic constructors for
--   <a>Static</a> values:
--   
--   <pre>
--   staticLabel :: String -&gt; Static a
--   staticApply :: Static (a -&gt; b) -&gt; Static a -&gt; Static b
--   </pre>
--   
--   The first constructor refers to a label in a <a>RemoteTable</a>. The
--   second allows to apply a static function to a static argument, and
--   makes <a>Static</a> compositional: once we have <a>staticApply</a> we
--   can implement numerous derived combinators on <a>Static</a> values (we
--   define a few in this module; see <a>staticCompose</a>,
--   <a>staticSplit</a>, and <a>staticConst</a>).
--   
--   <ul>
--   <li><i>Closures</i></li>
--   </ul>
--   
--   Closures in functional programming arise when we partially apply a
--   function. A closure is a code pointer together with a runtime data
--   structure that represents the value of the free variables of the
--   function. A <a>Closure</a> represents these closures explicitly so
--   that they can be serialized:
--   
--   <pre>
--   data Closure a = Closure (Static (ByteString -&gt; a)) ByteString
--   </pre>
--   
--   See <i>Towards Haskell in the Cloud</i> for the rationale behind
--   representing the function closure environment in serialized
--   (<a>ByteString</a>) form. Any static value can trivially be turned
--   into a <a>Closure</a> (<a>staticClosure</a>). Moreover, since
--   <a>Static</a> is now compositional, we can also define derived
--   operators on <a>Closure</a> values (<a>closureApplyStatic</a>,
--   <a>closureApply</a>, <a>closureCompose</a>, <a>closureSplit</a>).
--   
--   <ul>
--   <li><i>Monomorphic example</i></li>
--   </ul>
--   
--   Suppose we are working in the context of some distributed environment,
--   with a monadic type <tt>Process</tt> representing processes,
--   <tt>NodeId</tt> representing node addresses and <tt>ProcessId</tt>
--   representing process addresses. Suppose further that we have a
--   primitive
--   
--   <pre>
--   sendInt :: ProcessId -&gt; Int -&gt; Process ()
--   </pre>
--   
--   We might want to define
--   
--   <pre>
--   sendIntClosure :: ProcessId -&gt; Closure (Int -&gt; Process ())
--   </pre>
--   
--   In order to do that, we need a static version of <tt>send</tt>, and a
--   static decoder for <tt>ProcessId</tt>:
--   
--   <pre>
--   sendIntStatic :: Static (ProcessId -&gt; Int -&gt; Process ())
--   sendIntStatic = staticLabel "$send"
--   </pre>
--   
--   <pre>
--   decodeProcessIdStatic :: Static (ByteString -&gt; Int)
--   decodeProcessIdStatic = staticLabel "$decodeProcessId"
--   </pre>
--   
--   where of course we have to make sure to use an appropriate
--   <a>RemoteTable</a>:
--   
--   <pre>
--   rtable :: RemoteTable
--   rtable = registerStatic "$send" (toDynamic sendInt)
--          . registerStatic "$decodeProcessId" (toDynamic (decode :: ByteString -&gt; Int))
--          $ initRemoteTable
--   </pre>
--   
--   We can now define <tt>sendIntClosure</tt>:
--   
--   <pre>
--   sendIntClosure :: ProcessId -&gt; Closure (Int -&gt; Process ())
--   sendIntClosure pid = closure decoder (encode pid)
--     where
--       decoder :: Static (ByteString -&gt; Int -&gt; Process ())
--       decoder = sendIntStatic `staticCompose` decodeProcessIdStatic
--   </pre>
--   
--   <ul>
--   <li><i>Polymorphic example</i></li>
--   </ul>
--   
--   Suppose we wanted to define a primitive
--   
--   <pre>
--   sendIntResult :: ProcessId -&gt; Closure (Process Int) -&gt; Closure (Process ())
--   </pre>
--   
--   which turns a process that computes an integer into a process that
--   computes the integer and then sends it someplace else.
--   
--   We can define
--   
--   <pre>
--   bindStatic :: (Typeable a, Typeable b) =&gt; Static (Process a -&gt; (a -&gt; Process b) -&gt; Process b)
--   bindStatic = staticLabel "$bind"
--   </pre>
--   
--   provided that we register this label:
--   
--   <pre>
--   rtable :: RemoteTable
--   rtable = ...
--          . registerStatic "$bind" ((&gt;&gt;=) :: Process ANY1 -&gt; (ANY1 -&gt; Process ANY2) -&gt; Process ANY2)
--          $ initRemoteTable
--   </pre>
--   
--   (Note that we are using the special <a>ANY1</a> and <a>ANY2</a> types
--   from <a>Data.Rank1Typeable</a> to represent this polymorphic value.)
--   Once we have a static bind we can define
--   
--   <pre>
--   sendIntResult :: ProcessId -&gt; Closure (Process Int) -&gt; Closure (Process ())
--   sendIntResult pid cl = bindStatic `closureApplyStatic` cl `closureApply` sendIntClosure pid
--   </pre>
--   
--   <ul>
--   <li><i>Dealing with qualified types</i></li>
--   </ul>
--   
--   In the above we were careful to avoid qualified types. Suppose that we
--   have instead
--   
--   <pre>
--   send :: Binary a =&gt; ProcessId -&gt; a -&gt; Process ()
--   </pre>
--   
--   If we now want to define <tt>sendClosure</tt>, analogous to
--   <tt>sendIntClosure</tt> above, we somehow need to include the
--   <a>Binary</a> instance in the closure -- after all, we can ship this
--   closure someplace else, where it needs to accept an <tt>a</tt>,
--   <i>then encode it</i>, and send it off. In order to do this, we need
--   to turn the Binary instance into an explicit dictionary:
--   
--   <pre>
--   data BinaryDict a where
--     BinaryDict :: Binary a =&gt; BinaryDict a
--   
--   sendDict :: BinaryDict a -&gt; ProcessId -&gt; a -&gt; Process ()
--   sendDict BinaryDict = send
--   </pre>
--   
--   Now <tt>sendDict</tt> is a normal polymorphic value:
--   
--   <pre>
--   sendDictStatic :: Static (BinaryDict a -&gt; ProcessId -&gt; a -&gt; Process ())
--   sendDictStatic = staticLabel "$sendDict"
--   
--   rtable :: RemoteTable
--   rtable = ...
--          . registerStatic "$sendDict" (sendDict :: BinaryDict ANY -&gt; ProcessId -&gt; ANY -&gt; Process ())
--          $ initRemoteTable
--   </pre>
--   
--   so that we can define
--   
--   <pre>
--   sendClosure :: Static (BinaryDict a) -&gt; Process a -&gt; Closure (a -&gt; Process ())
--   sendClosure dict pid = closure decoder (encode pid)
--     where
--       decoder :: Static (ByteString -&gt; a -&gt; Process ())
--       decoder = (sendDictStatic `staticApply` dict) `staticCompose` decodeProcessIdStatic
--   </pre>
--   
--   <ul>
--   <li><i>Word of Caution</i></li>
--   </ul>
--   
--   You should not <i>define</i> functions on <tt>ANY</tt> and co. For
--   example, the following definition of <tt>rtable</tt> is incorrect:
--   
--   <pre>
--   rtable :: RemoteTable
--   rtable = registerStatic "$sdictSendPort" sdictSendPort
--          $ initRemoteTable
--     where
--       sdictSendPort :: SerializableDict ANY -&gt; SerializableDict (SendPort ANY)
--       sdictSendPort SerializableDict = SerializableDict
--   </pre>
--   
--   This definition of <tt>sdictSendPort</tt> ignores its argument
--   completely, and constructs a <tt>SerializableDict</tt> for the
--   <i>monomorphic</i> type <tt>SendPort ANY</tt>, which isn't what you
--   want. Instead, you should do
--   
--   <pre>
--   rtable :: RemoteTable
--   rtable = registerStatic "$sdictSendPort" (sdictSendPort :: SerializableDict ANY -&gt; SerializableDict (SendPort ANY))
--          $ initRemoteTable
--     where
--       sdictSendPort :: forall a. SerializableDict a -&gt; SerializableDict (SendPort a)
--       sdictSendPort SerializableDict = SerializableDict
--   </pre>
module Control.Distributed.Static

-- | A static value. Static is opaque; see <a>staticLabel</a> and
--   <a>staticApply</a>.
data Static a

-- | Create a primitive static value.
--   
--   It is the responsibility of the client code to make sure the
--   corresponding entry in the <a>RemoteTable</a> has the appropriate
--   type.
staticLabel :: String -> Static a

-- | Apply two static values
staticApply :: Static (a -> b) -> Static a -> Static b

-- | Construct a static value from a static pointer
--   
--   Since 0.3.4.0.
staticPtr :: forall a. Typeable a => StaticPtr a -> Static a

-- | Apply a static pointer to a static value
--   
--   Since 0.3.4.0.
staticApplyPtr :: (Typeable a, Typeable b) => StaticPtr (a -> b) -> Static a -> Static b

-- | Static version of (<a>.</a>)
staticCompose :: Static (b -> c) -> Static (a -> b) -> Static (a -> c)

-- | Static version of (<a>***</a>)
staticSplit :: Static (a -> b) -> Static (a' -> b') -> Static ((a, a') -> (b, b'))

-- | Static version of <a>const</a>
staticConst :: Static a -> Static (b -> a)

-- | Static version of <a>flip</a>
staticFlip :: Static (a -> b -> c) -> Static (b -> a -> c)

-- | A closure is a static value and an encoded environment
data Closure a
closure :: Static (ByteString -> a) -> ByteString -> Closure a

-- | Convert a static value into a closure.
staticClosure :: Static a -> Closure a

-- | Apply a static function to a closure
closureApplyStatic :: Static (a -> b) -> Closure a -> Closure b

-- | Closure application
closureApply :: forall a b. Closure (a -> b) -> Closure a -> Closure b

-- | Closure composition
closureCompose :: Closure (b -> c) -> Closure (a -> b) -> Closure (a -> c)

-- | Closure version of (<a>***</a>)
closureSplit :: Closure (a -> b) -> Closure (a' -> b') -> Closure ((a, a') -> (b, b'))

-- | Runtime dictionary for <a>unstatic</a> lookups
data RemoteTable

-- | Initial remote table
initRemoteTable :: RemoteTable

-- | Register a static label
registerStatic :: String -> Dynamic -> RemoteTable -> RemoteTable

-- | Resolve a static value
unstatic :: Typeable a => RemoteTable -> Static a -> Either String a

-- | Resolve a closure
unclosure :: Typeable a => RemoteTable -> Closure a -> Either String a
instance GHC.Show.Show (Control.Distributed.Static.Closure a)
instance GHC.Classes.Ord (Control.Distributed.Static.Closure a)
instance GHC.Classes.Eq (Control.Distributed.Static.Closure a)
instance GHC.Show.Show (Control.Distributed.Static.Static a)
instance GHC.Classes.Ord (Control.Distributed.Static.Static a)
instance GHC.Classes.Eq (Control.Distributed.Static.Static a)
instance GHC.Show.Show Control.Distributed.Static.StaticLabel
instance GHC.Classes.Ord Control.Distributed.Static.StaticLabel
instance GHC.Classes.Eq Control.Distributed.Static.StaticLabel
instance Data.Binary.Class.Binary (Control.Distributed.Static.Closure a)
instance Control.DeepSeq.NFData (Control.Distributed.Static.Closure a)
instance Control.DeepSeq.NFData (Control.Distributed.Static.Static a)
instance Data.Binary.Class.Binary (Control.Distributed.Static.Static a)
instance Control.DeepSeq.NFData Control.Distributed.Static.StaticLabel
instance GHC.Show.Show Control.Distributed.Static.SDynamic
instance GHC.Classes.Eq Control.Distributed.Static.SDynamic
instance GHC.Classes.Ord Control.Distributed.Static.SDynamic
