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


-- | Serialization of arbitrary Haskell expressions
--   
--   Serialization of arbitrary Haskell expressions.
@package imprint
@version 0.0.1.0


-- | This package provides a solution for serialization of arbitrary
--   Haskell values, monomorphic functions, and closures without relying on
--   remote tables or Template Haskell, with minimum boilderplate.
--   
--   To use the package, be sure to enable the following language
--   extensions:
--   
--   <ul>
--   <li><a>DataKinds</a></li>
--   <li><a>StaticPointers</a></li>
--   <li><a>TypeOperators</a></li>
--   </ul>
--   
--   The following form of import is recommended:
--   
--   <pre>
--   import Data.Imprint (Imprint, Col (..), Dict (..), (&lt;:&gt;))
--   import qualified Data.Imprint as I
--   </pre>
--   
--   To serialize a value, we must first create an <a>Imprint</a> of it. If
--   the value in question is an instance of the <a>Binary</a> type class,
--   then the <a>binary</a> function should be used:
--   
--   <pre>
--   intImprint :: Imprint 'Z Int
--   intImprint = I.binary (static Dict) 4
--   </pre>
--   
--   The <tt>static</tt> keyword has to do with the concept of static
--   pointers, see the link above. We won't go into the details here, but
--   it suffices to say that we need to have an evidence of existence of
--   <a>Binary</a> instance in serializable form. <tt>static</tt>, being a
--   keyword, not a function, has to be used like this and cannot be put
--   inside <a>binary</a>, because it creates a pointer to a concrete thing
--   that is passed to it. This little ceremony of passing <tt>static
--   Dict</tt> as the first argument of <a>binary</a> every time you create
--   an <a>Imprint</a> of a value that has a <a>Binary</a> instance is the
--   only boilderplate we have to put up with, though.
--   
--   To create an <a>Imprint</a> of a function or indeed almost anything
--   that has no <a>Binary</a> instance, we use the <a>static</a> function:
--   
--   <pre>
--   funImprint :: Imprint 'Z (Int -&gt; String -&gt; String)
--   funImprint = I.static (static f)
--     where
--       f n str = str ++ show n
--   </pre>
--   
--   The <tt>f</tt> function we want to serialize may be defined anywhere.
--   Note that the resulting <a>Imprint</a> is opaque and has no sign of
--   how it was created (with <a>binary</a> or with <a>static</a>).
--   
--   Finally, there is a way to apply an <a>Imprint</a> of a value to an
--   <a>Imprint</a> of a function with <tt>(<a>&lt;:&gt;</a>)</tt>:
--   
--   <pre>
--   closureImprint :: Imprint ('Z ':~&gt; Int) (String -&gt; String)
--   closureImprint = funImprint &lt;:&gt; intImprint
--   </pre>
--   
--   Note how the applied arguments are collected in the phantom type (the
--   first argument of <a>Imprint</a> type constructor). There is no
--   requirement to apply all arguments, you may transmit a partially
--   applied function all right.
--   
--   Now, to serialization. That is quite simple, because <a>Imprint</a> is
--   an instance of <a>Binary</a> and so it is perfectly serializable. On
--   the receiving site, you however must know the full type of
--   <a>Imprint</a>, including the collection of applied arguments in order
--   to restore it.
--   
--   If a more dynamic approach is desirable, we could adopt the
--   representation of closures used in <tt>distributed-process</tt> as a
--   special case with the following type of <a>Imprint</a>:
--   
--   <pre>
--   Imprint ('Z ':~&gt; ByteString) (Process ())
--   </pre>
--   
--   In that case we would need to serialize all the arguments beforehand
--   and put the deserializing code into the <tt>ByteString -&gt; Process
--   ()</tt> function.
--   
--   Finally, we give the guarantee that if you have a value of the type
--   <tt><a>Imprint</a> as a</tt>, then you can have the <tt>a</tt> value
--   back, see <a>restore</a>:
--   
--   <pre>
--   restore :: Imprint bs a -&gt; a
--   </pre>
module Data.Imprint

-- | <tt><a>Imprint</a> bs a</tt> is an image of <tt>a</tt> that is
--   isomorphic to <tt>a</tt> and serializable.
data Imprint (bs :: Col *) a

-- | This helper type is used to build the phantom type holding types of
--   the arguments applied to an <a>Imprint</a> of a function.
data Col a
[Z] :: Col a
[:~>] :: Col a -> a -> Col a

-- | Values of type <tt><a>Dict</a> p</tt> capture a dictionary for a
--   constraint of type <tt>p</tt>.
--   
--   e.g.
--   
--   <pre>
--   <a>Dict</a> :: <a>Dict</a> (<a>Eq</a> <a>Int</a>)
--   </pre>
--   
--   captures a dictionary that proves we have an:
--   
--   <pre>
--   instance <a>Eq</a> 'Int
--   </pre>
--   
--   Pattern matching on the <a>Dict</a> constructor will bring this
--   instance into scope.
data Dict a :: Constraint -> *
[Dict] :: Dict a

-- | Create an <a>Imprint</a> of a value with <a>Binary</a> instance.
--   
--   <pre>
--   intImprint :: Imprint 'Z Int
--   intImprint = I.binary (static Dict) 4
--   </pre>
binary :: Typeable a => StaticPtr (Dict (Binary a)) -> a -> Imprint  'Z a

-- | Create an <a>Imprint</a> of a value without <a>Binary</a> instance.
--   
--   <pre>
--   funImprint :: Imprint 'Z (Int -&gt; String -&gt; String)
--   funImprint = I.static (static f)
--     where
--       f n str = str ++ show n
--   </pre>
static :: Typeable a => StaticPtr a -> Imprint  'Z a

-- | Apply <a>Imprint</a> of a value to an <a>Imprint</a> of a function
--   building a closure.
--   
--   <pre>
--   closureImprint :: Imprint ('Z ':~&gt; Int) (String -&gt; String)
--   closureImprint = funImprint &lt;:&gt; intImprint
--   </pre>
(<:>) :: Imprint bs (b -> a) -> Imprint  'Z b -> Imprint (bs :~> b) a
infixl 4 <:>

-- | Restore a value from its <a>Imprint</a>.
restore :: Imprint as a -> a
instance Data.Typeable.Internal.Typeable a => Data.Binary.Class.Binary (Data.Imprint.Imprint 'Data.Imprint.Z a)
instance (Data.Binary.Class.Binary (Data.Imprint.Imprint bs (b -> a)), Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable b) => Data.Binary.Class.Binary (Data.Imprint.Imprint (bs 'Data.Imprint.:~> b) a)
