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


-- | Generate default function implementations for complex type classes.
--   
--   Template Haskell code to implement default implementations for
--   type-class functions based on which functions are already implemented.
--   Currently extremely crude but still fairly effective.
--   
--   When defining a type class with many functions, each of which can be
--   implemented based on arbitrary subsets of the others, the standard
--   default-implementation concept breaks down quite badly. This library
--   provides a system by which more complex rules can be described for
--   choosing default implementations based on which ones the user
--   supplies. These implementations can additionally be given "suitability
--   scores", so that when multiple possible choices could be made, the
--   library can choose the "best" one.
@package flexible-defaults
@version 0.0.2


-- | A code-generation system for complex typeclass default-implementation
--   configurations. There are usage examples in this package's source
--   distribution[1] and in the random-source package[2].
--   
--   <ol>
--   
--   <li><a>https://github.com/mokus0/flexible-defaults/tree/master/examples</a></li>
--   
--   <li><a>https://github.com/mokus0/random-fu/blob/master/random-source/src/Data/Random/Internal/TH.hs</a></li>
--   </ol>
module Language.Haskell.TH.FlexibleDefaults

-- | A description of a system of <a>Function</a>s and default
--   <a>Implementation</a>s which can be used to complete a partial
--   implementation of some type class.
data Defaults s a

-- | Map a function over all scores. This function's name comes from the
--   following idiom (where <a>Sum</a> is replaced by whatever
--   monoid-constructor you want to use to combine scores):
--   
--   <pre>
--   foo = scoreBy Sum $ do
--      ...
--   </pre>
scoreBy :: (a -> b) -> Defaults a t -> Defaults b t

-- | A representation of a function for which one or more default
--   <a>Implementation</a>s exist. Defined using the <a>function</a>
--   function.
data Function s a

-- | Declare a function that must be implemented, and provide a description
--   of any default implementations which can be used.
function :: String -> Function s a -> Defaults s a

-- | State that a function must be implemented but has no default
--   implementation.
requireFunction :: String -> Defaults s ()

-- | A representation of a single possible implementation of a
--   <a>Function</a>. Defined using the <a>implementation</a> function.
data Implementation s a

-- | Describe a default implementation of the current function
implementation :: Implementation s (Q [Dec]) -> Function s ()

-- | Specify the score associated with the current implementation. Only one
--   invocation of either <a>score</a> or <a>cost</a> may be used per
--   implementation.
score :: s -> Implementation s ()

-- | Specify the cost (negated score) associated with the current
--   implementation. Only one invocation of either <a>score</a> or
--   <a>cost</a> may be used per implementation.
cost :: Num s => s -> Implementation s ()

-- | Specify that the current implementation must not be used unless the
--   given function is already defined. If this implementation can be used
--   mutually-recursively with _ALL_ potential implementations of some
--   other function, then a dependency need not be declared on that
--   function.
dependsOn :: String -> Implementation s ()

-- | Specify that an <a>Implementation</a> should be annotated with an
--   INLINE pragma. Under GHC versions earlier than 6.12 this is a no-op,
--   because those Template Haskell implementations do not support pragmas.
inline :: Implementation s ()

-- | Specify that an <a>Implementation</a> should be annotated with a
--   NOINLINE pragma. Under GHC versions earlier than 6.12 this is a no-op,
--   because those Template Haskell implementations do not support pragmas.
noinline :: Implementation s ()

-- | Given a <tt>Q [Dec]</tt> containing an instance declaration, complete
--   that instance declaration using the given <a>Defaults</a>
--   specification. Typical usage would be along the lines of the
--   following:
--   
--   <pre>
--   $(withDefaults fooDefaults [d| instance Foo t where {- ... -} |])
--   </pre>
withDefaults :: (Monoid s, Ord s) => Defaults s () -> Q [Dec] -> Q [Dec]

-- | Given a partial list of function declarations, complete that list
--   based on the <a>Defaults</a> specification given.
implementDefaults :: (Ord s, Monoid s) => Defaults s () -> [Dec] -> Q [Dec]
