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


-- | Named parameters (keyword arguments) for Haskell
--   
--   <a>named</a> is a lightweight library for named function parameters
--   (keyword arguments) based on overloaded labels. Keyword arguments have
--   several advantages over positional arguments:
--   
--   <ul>
--   <li>they can be supplied in arbitrary order</li>
--   <li>their names serve as documentation at call site</li>
--   <li>it is impossible to accidentally mix them up</li>
--   </ul>
--   
--   Unlike <tt>newtype</tt> wrappers, keyword arguments don't pollute the
--   global namespace, don't require top-level definitions, and don't need
--   to be exported.
--   
--   This implementation of named parameters is typesafe, provides good
--   type inference, descriptive type errors, and has no runtime overhead.
--   
--   Example usage:
--   
--   <pre>
--   import Named
--   
--   createSymLink :: FilePath `Named` "from" -&gt; FilePath `Named` "to" -&gt; IO ()
--   createSymLink (Named from) (Named to) = ...
--   
--   main = createSymLink ! #from "/path/to/source"
--                        ! #to "/target/path"
--   </pre>
@package named
@version 0.1.0.0


-- | Named parameters, also known as keyword arguments, have several
--   advantages over positional arguments:
--   
--   <ul>
--   <li>convenience: they can be supplied in arbitrary order</li>
--   <li>readability: their names serve as documentation at call site</li>
--   <li>safety: it is impossible to accidentally mix them up</li>
--   </ul>
--   
--   Consider a function to replace a substring with another string:
--   
--   <pre>
--   Text.replace path "$HOME" "/home/username/"
--   </pre>
--   
--   We want to replace references to the <tt>$HOME</tt> environment
--   variable with a concrete directory. There is but one problem – we have
--   supplied the text arguments in the wrong order.
--   
--   Compare that to a newtype-based solution:
--   
--   <pre>
--   Text.replace
--     (Needle "$HOME")
--     (Replacement "/home/username/")
--     (Haystack path)
--   </pre>
--   
--   Now that the function requires each argument to be wrapped in a
--   newtype, we cannot mix them up – the compiler will report an error,
--   and newtype constructors serve as documentation.
--   
--   The problem with newtypes is that it is bothersome to create them for
--   each parameter, they pollute the global namespace, and we still cannot
--   supply wrapped arguments in arbitrary order.
--   
--   With keyword arguments, none of that is a problem:
--   
--   <pre>
--   Text.replace <a>!</a> #haystack path
--                <a>!</a> #needle "$HOME"
--                <a>!</a> #replacement "/home/username/"
--   </pre>
--   
--   Functions must declare their parameter names in the type signature:
--   
--   <pre>
--   replace ::
--     Text `<a>Named</a>` "needle" -&gt;
--     Text `<a>Named</a>` "replacement" -&gt;
--     Text `<a>Named</a>` "haystack" -&gt;
--     Text
--   replace (Named needle) (Named replacement) (Named haystack) =
--     ...
--   </pre>
--   
--   Keyword arguments have seamless interoperability with positional
--   arguments when the function takes them last. Consider this function:
--   
--   <pre>
--   foo :: A -&gt; B -&gt; C `<a>Named</a>` "x" -&gt; IO ()
--   </pre>
--   
--   There are several ways to invoke it:
--   
--   <pre>
--   (foo a b) <a>!</a> #x c     -- parentheses for clarity
--   (foo a <a>!</a> #x c) b     -- parentheses required
--   (foo <a>!</a> #x c) a b     -- parentheses required
--   </pre>
--   
--   We can also supply keyword arguments using the <a>with</a> combinator
--   instead of the <a>!</a> operator:
--   
--   <pre>
--   (<a>with</a> #x c foo) a b  -- parentheses for clarity
--   <a>with</a> #x c (foo a b)  -- has the same effect
--   </pre>
--   
--   Both <a>!</a> and <a>with</a> work in a similar manner: they traverse
--   the spine of the function and supply the first keyword argument with a
--   matching name.
--   
--   For example:
--   
--   <pre>
--   bar           :: A `<a>Named</a>` "x" -&gt; B `<a>Named</a>` "y" -&gt; IO ()
--   bar <a>!</a> #y b    :: A `<a>Named</a>` "x"                  -&gt; IO ()
--   <a>with</a> #y b bar :: A `<a>Named</a>` "x"                  -&gt; IO ()
--   </pre>
module Named

-- | Assign a name to a value of type <tt>a</tt>. This is a simple wrapper
--   intended for use with <tt>-XOverloadedLabels</tt>:
--   
--   <pre>
--   #verbose True :: Named Bool "verbose"
--   </pre>
newtype Named a (name :: Symbol)
Named :: a -> Named a
[unnamed] :: Named a -> a

-- | Supply a keyword argument to a function:
--   
--   <pre>
--   function ! #param_name value
--   </pre>
(!) :: Apply name a fn fn' => fn -> Named a name -> fn'
infixl 9 !

-- | A proxy for a name, intended for use with <tt>-XOverloadedLabels</tt>:
--   
--   <pre>
--   #verbose :: Name "verbose"
--   </pre>
data Name (name :: Symbol)
Name :: Name

-- | Supply a keyword argument to a function:
--   
--   <pre>
--   with #param_name value function
--   </pre>
with :: Apply name a fn fn' => Name name -> a -> fn -> fn'

-- | Snake oil to cure boolean blindness.
type Flag = Named Bool

-- | Match on a flag, a version of <a>Named</a> specialized to <a>Bool</a>.

-- | Supply a parameter of type <tt>a</tt> named <tt>name</tt> to a
--   function <tt>fn</tt>, resulting in <tt>fn'</tt>.
--   
--   For example:
--   
--   <pre>
--   Apply "x" Char
--     (Named Bool "b" -&gt; Named Char "x" -&gt; r)
--     (Named Bool "b" -&gt; r)
--   </pre>
--   
--   In case the parameter cannot be supplied, this constraint will become
--   a type error.
type Apply (name :: Symbol) (a :: Type) (fn :: Type) (fn' :: Type) = Apply' (Decide name fn) name a fn fn'

-- | Apply a function to a keyword argument.
apply :: Apply' decision name a fn fn' => fn -> Named a name -> fn'

-- | Annotate a value with a name.
named :: Name name -> a -> Named a name
instance (fn ~ (Named.Named a name -> r), fn' ~ r, Named.Decide name fn ~ 'Named.Done) => Named.Apply' 'Named.Done name a fn fn'
instance (Named.Apply' decision name a r r', Named.Decide name fn ~ 'Named.Skip decision, fn ~ (x -> r), fn' ~ (x -> r')) => Named.Apply' ('Named.Skip decision) name a fn fn'
instance (name ~ name') => GHC.OverloadedLabels.IsLabel name' (Named.Name name)
instance (name ~ name', a ~ a') => GHC.OverloadedLabels.IsLabel name (a -> Named.Named a' name')
