-- 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.3

-- | 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].
--   
--   
--   
--   
- https://github.com/mokus0/flexible-defaults/tree/master/examples
--   
--   
- https://github.com/mokus0/random-fu/blob/master/random-source/src/Data/Random/Internal/TH.hs
--   
module Language.Haskell.TH.FlexibleDefaults

-- | A description of a system of Functions and default
--   Implementations 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 Sum is replaced by whatever
--   monoid-constructor you want to use to combine scores):
--   
--   
--   foo = scoreBy Sum $ do
--      ...
--   
scoreBy :: (a -> b) -> Defaults a t -> Defaults b t

-- | A representation of a function for which one or more default
--   Implementations exist. Defined using the function
--   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
--   Function. Defined using the implementation 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 score or cost may be used per
--   implementation.
score :: s -> Implementation s ()

-- | Specify the cost (negated score) associated with the current
--   implementation. Only one invocation of either score or
--   cost 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 Implementation 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 Implementation 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 Q [Dec] containing an instance declaration, complete
--   that instance declaration using the given Defaults
--   specification. Typical usage would be along the lines of the
--   following:
--   
--   
--   $(withDefaults fooDefaults [d| instance Foo t where {- ... -} |])
--   
withDefaults :: (Monoid s, Ord s) => Defaults s () -> Q [Dec] -> Q [Dec]

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