# Path: pynads/utils/monoidal.py
# def get_generic_mappend(obj, generics=_generic_types,
#                         known_to_generics=_builtin_to_generic,
#                         known_mappends=_generic_mappends, **kwargs):
#     """Accepts an arbitrary object and attempts find its generic type and then
#     its generic mappend. If a generic type can't be determined, a type error
#     is raised.
# 
#     Optionally, a customized iterable of generics, a mapping of known types
#     to generic types or a mapping of generic types to mappends can be passed.
#     """
#     generic = _get_generic_type(obj, generics, known_to_generics)
# 
#     if generic is None:
#         raise TypeError("No known generic for {!r} instance of {!s}"
#                         "".format(obj, type(obj)))
# 
#     mappend = _get_generic_mappend(generic, known_mappends)
# 
#     if mappend is None:
#         raise TypeError("No known generic mappend for {!r} instance of {!s}"
#                         "".format(obj, type(obj)))
# 
#     return mappend
# 
# def get_generic_mempty(obj, known_mempties=_generic_mempties, **kwargs):
#     """Accepts an object and tries to find its known mempty value. If no
#     known mempty exists, a TypeError is raised.
# 
#     Optionally, a mapping of known type to mempty values can be passed. The
#     default value is a mapping of only types found in builtin: int, float,
#     complex, str, list, tuple, dict, set and frozenset.
#     """
#     generic = _get_generic_type(obj, **kwargs)
# 
#     mempty = known_mempties.get(generic, None)
#     if mempty is None:
#         raise TypeError("No known mempty for {!r} instance of {!s}"
#                         "".format(obj, type(obj)))
#     return mempty
# 
# def generic_mconcat(*monoids, **kwargs):
#     """Generic implementation of mconcat for known monodic objects that don't
#     define it. To do this, a generic mappend must be able to be derived for
#     the first object in the sequence via get_generic_mappend. If that isn't
#     possible, then a TypeError is propagated from get_generic_mappend.
# 
#     It is possible to pass optional keyword arguments down to
#     get_generic_mappend by using **kwargs.
#     """
#     mconcat = _make_generic_mconcat(monoids[0], **kwargs)
#     return mconcat(monoids)
# 
# def is_monoid(obj,
#               monoid_attrs=_monoidal_attrs,
#               generics=_generic_types,
#               known_to_generics=_builtin_to_generic,
#               known_mempties=_generic_mempties,
#               known_mappends=_generic_mappends,
#               **kwargs):
#     """Attempts to determine if an object is a monoid or not. When in doubt,
#     this function returns false. For example, even though get_generic_mappend
#     can derive a generic mappend for decimal.Decimal (it is, after all,
#     a "subclass" of numbers.Number), there's not a hardcoded mempty for it
#     despite that it would be ``decimal.Decimal(0)`` and is_monoid would
#     return false against it.
# 
#     Despite this, it is possible to override the default settings to provide
#     for other object types that are monoidal.
#     """
#     if isinstance(obj, Monoid) or all(hasattr(obj, x) for x in monoid_attrs):
#         return True
#     else:
#         try:
#             get_generic_mempty(obj, known_mempties=known_mempties)
#             get_generic_mappend(obj,
#                                 generics=generics,
#                                 known_to_generics=known_to_generics,
#                                 known_mappends=known_mappends)
#         except TypeError:
#             return False
#         else:
#             return True


from ..utils.monoidal import (get_generic_mappend, get_generic_mempty,
                              generic_mconcat, is_monoid)
"""Helper functions for making it easier to deal with types in Python that
*are* monoidal but exist as basic types in Python.
"""



__all__ = ('mempty', 'mappend', 'mconcat', 'is_monoid')


def mempty(monoid, **kwargs):
    """Returns the mempty value of a Monoid.

    If the object passed is an implementation of pynads.abc.Monoid, then the
    mempty attribute found there is returned. Otherwise, if it fulfills certain
    criteria, then a generic mempty is returned instead. This criteria is
    determined by pynads.utils.get_generic_mempty. If neither case is true,
    then a TypeError is raised (propagated from get_generic_mempty).

    It's possible to pass optional keyword arguments to get_generic_mempty
    by using kwargs.

    See:
        pynads.utils.monoidal.get_generic_mempty
    """

    if hasattr(monoid, 'mempty'):
        return monoid.mempty
    else:

# Path: pynads/utils/monoidal.py
# def get_generic_mappend(obj, generics=_generic_types,
#                         known_to_generics=_builtin_to_generic,
#                         known_mappends=_generic_mappends, **kwargs):
#     """Accepts an arbitrary object and attempts find its generic type and then
#     its generic mappend. If a generic type can't be determined, a type error
#     is raised.
# 
#     Optionally, a customized iterable of generics, a mapping of known types
#     to generic types or a mapping of generic types to mappends can be passed.
#     """
#     generic = _get_generic_type(obj, generics, known_to_generics)
# 
#     if generic is None:
#         raise TypeError("No known generic for {!r} instance of {!s}"
#                         "".format(obj, type(obj)))
# 
#     mappend = _get_generic_mappend(generic, known_mappends)
# 
#     if mappend is None:
#         raise TypeError("No known generic mappend for {!r} instance of {!s}"
#                         "".format(obj, type(obj)))
# 
#     return mappend
# 
# def get_generic_mempty(obj, known_mempties=_generic_mempties, **kwargs):
#     """Accepts an object and tries to find its known mempty value. If no
#     known mempty exists, a TypeError is raised.
# 
#     Optionally, a mapping of known type to mempty values can be passed. The
#     default value is a mapping of only types found in builtin: int, float,
#     complex, str, list, tuple, dict, set and frozenset.
#     """
#     generic = _get_generic_type(obj, **kwargs)
# 
#     mempty = known_mempties.get(generic, None)
#     if mempty is None:
#         raise TypeError("No known mempty for {!r} instance of {!s}"
#                         "".format(obj, type(obj)))
#     return mempty
# 
# def generic_mconcat(*monoids, **kwargs):
#     """Generic implementation of mconcat for known monodic objects that don't
#     define it. To do this, a generic mappend must be able to be derived for
#     the first object in the sequence via get_generic_mappend. If that isn't
#     possible, then a TypeError is propagated from get_generic_mappend.
# 
#     It is possible to pass optional keyword arguments down to
#     get_generic_mappend by using **kwargs.
#     """
#     mconcat = _make_generic_mconcat(monoids[0], **kwargs)
#     return mconcat(monoids)
# 
# def is_monoid(obj,
#               monoid_attrs=_monoidal_attrs,
#               generics=_generic_types,
#               known_to_generics=_builtin_to_generic,
#               known_mempties=_generic_mempties,
#               known_mappends=_generic_mappends,
#               **kwargs):
#     """Attempts to determine if an object is a monoid or not. When in doubt,
#     this function returns false. For example, even though get_generic_mappend
#     can derive a generic mappend for decimal.Decimal (it is, after all,
#     a "subclass" of numbers.Number), there's not a hardcoded mempty for it
#     despite that it would be ``decimal.Decimal(0)`` and is_monoid would
#     return false against it.
# 
#     Despite this, it is possible to override the default settings to provide
#     for other object types that are monoidal.
#     """
#     if isinstance(obj, Monoid) or all(hasattr(obj, x) for x in monoid_attrs):
#         return True
#     else:
#         try:
#             get_generic_mempty(obj, known_mempties=known_mempties)
#             get_generic_mappend(obj,
#                                 generics=generics,
#                                 known_to_generics=known_to_generics,
#                                 known_mappends=known_mappends)
#         except TypeError:
#             return False
#         else:
#             return True


# Path: pynads/funcs/monoid.py
from ..utils.monoidal import (get_generic_mappend, get_generic_mempty,
                              generic_mconcat, is_monoid)

"""Helper functions for making it easier to deal with types in Python that
*are* monoidal but exist as basic types in Python.
"""



__all__ = ('mempty', 'mappend', 'mconcat', 'is_monoid')


def mempty(monoid, **kwargs):
    """Returns the mempty value of a Monoid.

    If the object passed is an implementation of pynads.abc.Monoid, then the
    mempty attribute found there is returned. Otherwise, if it fulfills certain
    criteria, then a generic mempty is returned instead. This criteria is
    determined by pynads.utils.get_generic_mempty. If neither case is true,
    then a TypeError is raised (propagated from get_generic_mempty).

    It's possible to pass optional keyword arguments to get_generic_mempty
    by using kwargs.

    See:
        pynads.utils.monoidal.get_generic_mempty
    """

    if hasattr(monoid, 'mempty'):
        return monoid.mempty
    else:

        return get_generic_mempty(monoid, **kwargs)