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


-- | CZipWith class and deriving via TH
--   
--   A typeclass similar to Data.Distributive, but for data parameterised
--   with a type constructor. The name comes from the resemblance of its
--   method to the regular zipWith function. The abstraction is useful for
--   example for program config handling.
@package czipwith
@version 1.0.0.0


-- | A typeclass for an operation resembling <a>zipWith</a> for types that
--   are parameterized over a constructor, plus template-haskell magic to
--   automatically derive instances.
--   
--   <pre>
--   zipWith  ::                          (g   -&gt; h   -&gt; i  ) -&gt; [g] -&gt; [h] -&gt; [i]
--   cZipWith :: CZipWith k =&gt; (forall a . g a -&gt; h a -&gt; i a) -&gt; k g -&gt; k h -&gt; k i
--   </pre>
--   
--   Types of the corresponding kind occur for example when handling
--   program configuration: When we define our an example configuration
--   type like
--   
--   <pre>
--   data MyConfig f = MyConfig
--     { flag_foo       :: f Bool
--     , flag_bar       :: f Bool
--     , flag_someLimit :: f Int
--     }
--   </pre>
--   
--   then
--   
--   <ul>
--   <li><tt>MyConfig Maybe</tt> can be used as the result-type of parsing
--   the commandline or a configuration file; it includes the option that
--   some field was not specified;</li>
--   <li><tt>MyConfig Identity</tt> can be used to represent both the
--   default configuration and the actual configuration derived from
--   defaults and the user input;</li>
--   <li><tt>MyConfig (Const Text)</tt> type to represent documentation for
--   our config, to be displayed to the user.</li>
--   </ul>
--   
--   This has the advantage that our configuration is defined in one place
--   only, so that changes are easy to make and we do not ever run into any
--   internal desynchonization of different datatypes. And once we obtained
--   the final config <tt>:: MyConfig Identity</tt>, we don't have to think
--   about <tt>Nothing</tt> cases anymore.
--   
--   The <tt><a>CZipWith</a></tt> helps with this use-case, more
--   specifically the merging of input and default config: we can express
--   the merging of user/default config <tt>:: MyConfig Maybe -&gt;
--   MyConfig Identity -&gt; MyConfig Identity</tt> in terms of
--   <tt><a>cZipWith</a></tt> (and get the implementation for free via
--   <a>deriveCZipWith</a>).
--   
--   As an example for such usage, the <a>brittany</a> package uses this
--   approach together with using automatically-derived Semigroup-instances
--   that allow merging of config values (for example when commandline args
--   do not override, but are added to those settings read from config
--   file). See <a>the module containing the config type</a>.
module Data.CZipWith

-- | laws:
--   
--   <ul>
--   <li><pre><a>cZipWith</a> (\x _ -&gt; x) g _ = g</pre></li>
--   <li><pre><a>cZipWith</a> (\_ y -&gt; y) _ h = h</pre></li>
--   </ul>
--   
--   This class is morally related to the <a>Distributive</a> class from
--   the <a>distributive</a> package, even when its method might not look
--   similar to those from <tt><tt>Distributive</tt></tt>. From the
--   corresponding docs:
--   
--   <pre>
--   To be distributable a container will need to have a way to consistently
--   zip a potentially infinite number of copies of itself. This effectively
--   means that the holes in all values of that type, must have the same
--   cardinality, fixed sized vectors, infinite streams, functions, etc.
--   and no extra information to try to merge together.
--   </pre>
--   
--   Especially "all values of that type must have the same cardinality" is
--   true for instances of CZipWith, the only difference being that the
--   "holes" are instantiations of the <tt>f :: * -&gt; *</tt> to some
--   type, where they are simply <tt>a :: *</tt> for
--   <tt><tt>Distributive</tt></tt>.
--   
--   For many <tt><tt>Distributive</tt></tt> instances there are
--   corresponding datatypes that are instances of <tt><a>CZipWith</a></tt>
--   (although they do not seem particularly useful..), for example:
--   
--   <pre>
--   newtype CUnit a f = CUnit (f a)                -- corresponding to <tt>Identity</tt>
--   data CPair a b f = CPair (f a) (f b)           -- corresponding to 'data MonoPair a = MonoPair a a'
--                                                  -- (the trivial fixed-size vector example :)
--   data CStream a f = CStream (f a) (CStream a f) -- corresponding to an infinite stream
--   </pre>
class CZipWith (k :: (* -> *) -> *)

-- | zipWith on constructors instead of values.
cZipWith :: CZipWith k => (forall a. g a -> h a -> i a) -> k g -> k h -> k i

-- | Derives a <a>CZipWith</a> instance for a datatype of kind <tt>(* -&gt;
--   *) -&gt; *</tt>.
--   
--   Requires that for this datatype (we shall call its argument <tt>f :: *
--   -&gt; *</tt> here)
--   
--   <ul>
--   <li>there is exactly one constructor;</li>
--   <li>all fields in the one constructor are either of the form <tt>f
--   x</tt> for some <tt>x</tt> or of the form <tt>X f</tt> for some type
--   <tt>X</tt> where there is an <tt>instance CZipWith X</tt>.</li>
--   </ul>
--   
--   For example, the following would be valid usage:
--   
--   <pre>
--   data A f = A
--     { a_str  :: f String
--     , a_bool :: f Bool
--     }
--   
--   data B f = B
--     { b_int   :: f Int
--     , b_float :: f Float
--     , b_a     :: A f
--     }
--   
--   deriveCZipWith ''A
--   deriveCZipWith ''B
--   </pre>
--   
--   This produces the following instances:
--   
--   <pre>
--   instance CZipWith A where
--     cZipWith f (A x1 x2) (A y1 y2) = A (f x1 y1) (f x2 y2)
--   
--   instance CZipWith B where
--     cZipWith f (B x1 x2 x3) (B y1 y2 y3)
--       = B (f x1 y1) (f x2 y2) (cZipWith f x3 y3)
--   </pre>
deriveCZipWith :: Name -> DecsQ
