diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -548,6 +548,7 @@ code = setup(name = 'sage',
                      'sage.calculus',
 
                      'sage.categories',
+                     'sage.categories.examples',
 
                      'sage.coding',
 
diff --git a/module_list.py b/module_list.py
--- a/module_list.py
+++ b/module_list.py
@@ -133,6 +133,9 @@ ext_modules = [
     Extension('sage.categories.morphism',
               sources = ['sage/categories/morphism.pyx']),
 
+    Extension('sage.categories.examples.semigroups_cython',
+              sources = ['sage/categories/examples/semigroups_cython.pyx']),
+
     ################################
     ## 
     ## sage.coding
diff --git a/sage/categories/basic.py b/sage/categories/basic.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/basic.py
@@ -0,0 +1,47 @@
+r"""
+A subset of sage.categories.all with just the basic categories needed
+for sage startup (i.e. to define ZZ, QQ, ...).
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from objects import Objects
+from sets_cat import Sets
+from ordered_sets import OrderedSets
+
+from abelian_semigroups import AbelianSemigroups
+from abelian_monoids import AbelianMonoids
+from abelian_groups import AbelianGroups
+
+from semigroups import Semigroups
+from monoids import Monoids
+from finite_semigroups import FiniteSemigroups
+from finite_monoids import FiniteMonoids
+from groups import Groups
+from ordered_monoids import OrderedMonoids
+
+from rngs import Rngs
+from rings import Rings
+from entire_rings import EntireRings
+from division_rings import DivisionRings
+
+from commutative_rings import CommutativeRings
+from integral_domains import IntegralDomains
+from gcd_domains import GcdDomains
+from principal_ideal_domains import PrincipalIdealDomains
+from euclidean_domains import EuclideanDomains
+from unique_factorization_domains import UniqueFactorizationDomains
+
+from fields import Fields
diff --git a/sage/categories/all.py b/sage/categories/all.py
--- a/sage/categories/all.py
+++ b/sage/categories/all.py
@@ -1,45 +1,15 @@
-from category import    is_Category
+from category import    is_Category, Category, HomCategory, AbstractCategory
 
 from category_types import(
                         Elements,
                         Sequences,
-                        Objects,
-                        Sets,
-                        GSets,
-                        PointedSets,
-                        SetsWithPartialMaps,
                         SimplicialComplexes,
-                        Semigroups,
-                        Monoids,
-                        Groupoid,
-                        Groups,
-                        AbelianSemigroups,
-                        AbelianMonoids,
-                        AbelianGroups,
-                        Rings,
-                        CommutativeRings,
-                        Fields,
-                        FiniteFields,
-                        NumberFields,
-                        Algebras,
-                        CommutativeAlgebras,
-                        MonoidAlgebras,
-                        GroupAlgebras,
-                        MatrixAlgebras,
-                        RingModules,
-                        Modules,
-                        FreeModules,
-                        VectorSpaces,
-                        HeckeModules,
-                        RingIdeals, Ideals,
-                        CommutativeRingIdeals,
-                        AlgebraModules,
-                        AlgebraIdeals,
-                        CommutativeAlgebraIdeals,
                         ChainComplexes,
-                        Schemes,
-                        ModularAbelianVarieties)
+)
 
+from tensor     import TensorialCategory, TensorCategory, tensor
+from direct_sum import AbelianCategory, DirectSumCategory, direct_sum
+from dual       import DualityCategory
 
 from functor  import (is_Functor,
                       ForgetfulFunctor,
@@ -51,7 +21,89 @@ from homset   import (Hom, hom, is_Homse
 
 from morphism import Morphism, is_Morphism
 
+from basic import *
 
+from g_sets import GSets
+from pointed_sets import PointedSets
 
+from sets_with_partial_maps import SetsWithPartialMaps
+from groupoid import Groupoid
 
+# enumerated sets
+from enumerated_sets import EnumeratedSets
+from finite_enumerated_sets import FiniteEnumeratedSets
+from infinite_enumerated_sets import InfiniteEnumeratedSets
 
+# fields
+from quotient_fields import QuotientFields
+from finite_fields import FiniteFields
+from number_fields import NumberFields
+
+# modules
+from left_modules import LeftModules
+from right_modules import RightModules
+from bimodules import Bimodules
+
+from modules import Modules
+RingModules = Modules
+from vector_spaces import VectorSpaces
+
+# (hopf) algebra structures
+from algebras import Algebras
+from commutative_algebras import CommutativeAlgebras
+from coalgebras import Coalgebras
+from bialgebras import Bialgebras
+from hopf_algebras import HopfAlgebras
+from operads import Operads
+
+# specific algebras
+from monoid_algebras import MonoidAlgebras
+from group_algebras import GroupAlgebras
+from matrix_algebras import MatrixAlgebras
+
+# ideals
+from ring_ideals import RingIdeals
+Ideals = RingIdeals
+from commutative_ring_ideals import CommutativeRingIdeals
+from algebra_modules import AlgebraModules
+from algebra_ideals import AlgebraIdeals
+from commutative_algebra_ideals import CommutativeAlgebraIdeals
+
+# schemes and varieties
+from modular_abelian_varieties import ModularAbelianVarieties
+from schemes import Schemes
+
+# * with basis
+from modules_with_basis import ModulesWithBasis
+FreeModules = ModulesWithBasis
+from hecke_modules            import HeckeModules
+from algebras_with_basis      import AlgebrasWithBasis
+from coalgebras_with_basis    import CoalgebrasWithBasis
+from bialgebras_with_basis    import BialgebrasWithBasis
+from hopf_algebras_with_basis import HopfAlgebrasWithBasis
+from operads_with_basis       import OperadsWithBasis
+
+# finite dimensional * with basis
+from finite_dimensional_modules_with_basis       import FiniteDimensionalModulesWithBasis
+from finite_dimensional_algebras_with_basis      import FiniteDimensionalAlgebrasWithBasis
+from finite_dimensional_coalgebras_with_basis    import FiniteDimensionalCoalgebrasWithBasis
+from finite_dimensional_bialgebras_with_basis    import FiniteDimensionalBialgebrasWithBasis
+from finite_dimensional_hopf_algebras_with_basis import FiniteDimensionalHopfAlgebrasWithBasis
+
+# graded *
+from graded_modules       import GradedModules
+from graded_algebras      import GradedAlgebras
+from graded_coalgebras    import GradedCoalgebras
+from graded_bialgebras    import GradedBialgebras
+from graded_hopf_algebras import GradedHopfAlgebras
+
+# graded * with basis
+from graded_modules_with_basis       import GradedModulesWithBasis
+from graded_algebras_with_basis      import GradedAlgebrasWithBasis
+from graded_coalgebras_with_basis    import GradedCoalgebrasWithBasis
+from graded_bialgebras_with_basis    import GradedBialgebrasWithBasis
+from graded_hopf_algebras_with_basis import GradedHopfAlgebrasWithBasis
+
+
+
+
diff --git a/sage/algebras/group_algebra.py b/sage/algebras/group_algebra.py
--- a/sage/algebras/group_algebra.py
+++ b/sage/algebras/group_algebra.py
@@ -281,7 +281,7 @@ class GroupAlgebra(Algebra):
             sage: GroupAlgebra(SU(2, GF(4, 'a')), IntegerModRing(12)).category()
             Category of group algebras over Ring of integers modulo 12
         """
-        from sage.categories.category_types import GroupAlgebras
+        from sage.categories.all import GroupAlgebras
         return GroupAlgebras(self.base_ring())
 
 
diff --git a/sage/algebras/steenrod_algebra.py b/sage/algebras/steenrod_algebra.py
--- a/sage/algebras/steenrod_algebra.py
+++ b/sage/algebras/steenrod_algebra.py
@@ -446,7 +446,7 @@ class SteenrodAlgebra_generic(Algebra):
             sage: A.category()
             Category of algebras over Finite Field of size 3
         """
-        from sage.categories.category_types import Algebras
+        from sage.categories.all import Algebras
         return Algebras(GF(self.prime))
 
 
diff --git a/sage/categories/abelian_groups.py b/sage/categories/abelian_groups.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/abelian_groups.py
@@ -0,0 +1,54 @@
+r"""
+AbelianGroups
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+from sage.categories.basic import AbelianMonoids
+
+class AbelianGroups(Category):
+    """
+    The category of abelian groups, i.e. additive abelian monoids
+    where each element has an inverse.
+
+    EXAMPLES::
+
+        sage: AbelianGroups()
+        Category of abelian groups
+        sage: AbelianGroups().super_categories()
+        [Category of abelian monoids]
+        sage: AbelianGroups().all_super_categories()
+        [Category of abelian groups, Category of abelian monoids, Category of abelian semigroups, Category of sets, Category of objects]
+
+    TESTS::
+
+        sage: C = AbelianGroups()
+        sage: loads(C.dumps()) == C
+        True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [AbelianMonoids()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        ##def -x, -(x,y):
+        pass
diff --git a/sage/categories/abelian_monoids.py b/sage/categories/abelian_monoids.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/abelian_monoids.py
@@ -0,0 +1,94 @@
+r"""
+AbelianMonoids
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+from sage.categories.basic import AbelianSemigroups
+
+# CHANGE: AbelianMonoid does not inherit any more from Monoids
+class AbelianMonoids(Category):
+    """
+    The category of abelian monoids
+    semigroups with an additive identity element
+
+    EXAMPLES::
+
+        sage: AbelianMonoids()
+        Category of abelian monoids
+        sage: AbelianMonoids().super_categories()
+        [Category of abelian semigroups]
+        sage: AbelianMonoids().all_super_categories()
+        [Category of abelian monoids, Category of abelian semigroups, Category of sets, Category of objects]
+
+    TESTS::
+
+        sage: C = AbelianMonoids()
+        sage: loads(C.dumps()) == C
+        True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [AbelianSemigroups()]
+
+    class ParentMethods:
+
+        @cached_method
+        def zero(self):
+            """
+            Returns the zero of the abelian monoid, that is the unique neutral element for `+`.
+
+            The default implementation is to coerce 0 into self.
+
+            It is recommended to override this method because the
+            coercion from the integers:
+             - is not always meaningful (except for `0`),
+             - often uses self.zero() otherwise.
+            """
+            return self(0)
+
+        def zero_element(self):
+            """
+            Alias for self.zero(), for backward compatibility
+            """
+            return self.zero()
+
+    class ElementMethods:
+        def __sub__(left, right):
+            """
+            Top-level subtraction operator for ModuleElements.
+            See extensive documentation at the top of element.pyx.
+            """
+            if left.parent() == right.parent() and hasattr(left, "_sub_"):
+                return left._sub_(right)
+            from sage.structure.element import get_coercion_model
+            import operator
+            return get_coercion_model().bin_op(left, right, operator.sub)
+
+        ##################################################
+        # Negation
+        ##################################################    
+
+        def __neg__(self):
+            """
+            Top-level negation operator for elements of abelian
+            monoids, which may choose to implement _neg_ rather than
+            __neg__ for consistancy.
+            """
+            return self._neg_()
diff --git a/sage/categories/abelian_semigroups.py b/sage/categories/abelian_semigroups.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/abelian_semigroups.py
@@ -0,0 +1,116 @@
+r"""
+AbelianSemigroups
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.abstract_method import abstract_method
+from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.categories.category import Category
+from sage.categories.sets_cat import Sets
+from sage.structure.sage_object import have_same_parent
+
+class AbelianSemigroups(Category):
+    """
+    The category of additive abelian semigroups, i.e. sets with an
+    associative and abelian operation +.
+
+    EXAMPLES::
+
+        sage: AbelianSemigroups()
+        Category of abelian semigroups
+        sage: AbelianSemigroups().super_categories()
+        [Category of sets]
+        sage: AbelianSemigroups().all_super_categories()
+        [Category of abelian semigroups, Category of sets, Category of objects]
+
+    TESTS::
+        sage: C = AbelianSemigroups()
+        sage: loads(C.dumps()) == C
+        True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [Sets()]
+
+    class ParentMethods:
+        def test_additive_associativity(self, **options):
+            tester = self.tester(**options)
+            # Better than use all.  
+            for x in tester.some_elements():
+                for y in tester.some_elements():
+                    for z in tester.some_elements():
+                        tester.assert_((x + y) + z == x + (y + z))
+
+        @abstract_method
+        def summation(self, x, y):
+            """
+            The binary addition operator of the semigroup
+
+            This must be implemented by any parent in AdditiveSemigroups().
+            
+            INPUT:
+             - ``x``, ``y``: elements of this additive semigroup
+
+            Returns the product of ``x`` and ``y``
+
+            EXAMPLES::
+
+                sage: S = AdditiveSemigroups().example()  # todo: not implemented
+                sage: x = S('a'); y = S('b')              # todo: not implemented
+                sage: S.summation(x, y)                   # todo: not implemented
+                'ab'
+
+            By default, the addition method on elements
+            ``x._add_(y)`` calls ``S.product(x,y)`` (not yet implemented).
+
+            As a bonus effect, ``S.product`` by itself models the
+            binary function from ``S`` to ``S``::
+
+                sage: bin = S.summation                   # todo: not implemented
+                sage: bin(x,y)                            # todo: not implemented
+                'ab'
+
+            Here, ``S.product`` is just a bound method. Whenever
+            possible, it is recommended to enrich this ``S.product``
+            with extra mathematical structure. Lazy attributes can
+            come handy for this.
+
+            Todo: add an example.
+            """
+            pass
+
+    class ElementMethods:
+
+        def _add_parent(self, other):
+            return self.parent().summation(self, other)
+
+        def __add__(left, right): 
+            if have_same_parent(left, right) and hasattr(left, "_add_"):
+                return left._add_(right)
+            from sage.structure.element import get_coercion_model
+            import operator
+            return get_coercion_model().bin_op(left, right, operator.add)
+
+        def __radd__(right, left): 
+            if have_same_parent(left, right) and hasattr(left, "_add_"):
+                return left._add_(right)
+            from sage.structure.element import get_coercion_model
+            import operator
+            return get_coercion_model().bin_op(left, right, operator.add)
+
diff --git a/sage/categories/algebra_ideals.py b/sage/categories/algebra_ideals.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/algebra_ideals.py
@@ -0,0 +1,46 @@
+r"""
+AlgebraIdeals
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from category_types import Category_ideal
+
+class AlgebraIdeals(Category_ideal):
+    """
+    The category of ideals in a fixed algebra $A$.
+
+    EXAMPLES:
+        sage: C = AlgebraIdeals(FreeAlgebra(QQ,2,'a,b'))
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, A):
+        from sage.algebras.algebra import is_Algebra
+        if not is_Algebra(A): # A not in Algebras() ?
+            raise TypeError, "A (=%s) must be an algebra"%A
+        Category_ideal.__init__(self, A)
+
+    def algebra(self):
+        return self.ambient()
+
+    @cached_method
+    def super_categories(self):
+        from algebra_modules import AlgebraModules
+        R = self.algebra()
+        return [AlgebraModules(R)]
diff --git a/sage/categories/algebra_modules.py b/sage/categories/algebra_modules.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/algebra_modules.py
@@ -0,0 +1,46 @@
+r"""
+AlgebraModules
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from category_types import Category_module
+
+class AlgebraModules(Category_module):
+    """
+    The category of modules over a fixed algebra $A$.
+
+    TESTS:
+        sage: C = AlgebraModules(FreeAlgebra(QQ,2,'a,b'))
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, A):
+        from sage.algebras.algebra import is_Algebra
+        if not is_Algebra(A): # A not in Algebras()?
+            raise TypeError, "A (=%s) must be an algebra"%A
+        Category_module.__init__(self, A)
+
+    def algebra(self):
+        return self.base_ring()
+
+    @cached_method
+    def super_categories(self):
+        R = self.algebra()
+        from modules import Modules
+        return [Modules(R)]
diff --git a/sage/categories/algebras.py b/sage/categories/algebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/algebras.py
@@ -0,0 +1,154 @@
+r"""
+Algebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import Hom, Rings, Modules, Semigroups, AbelianCategory, DirectSumCategory, direct_sum
+from sage.categories.morphism import SetMorphism
+from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.structure.element import AlgebraElement, get_coercion_model
+from sage.structure.sage_object import have_same_parent
+from sage.rings.integer import Integer
+import operator
+
+class Algebras(Category_over_base_ring, AbelianCategory):
+    """
+    The category of algebras over a given base ring.
+
+    An algebra over a ring R is a module over R which is itself a ring.
+
+    TODO: should R be a commutative ring?
+
+    EXAMPLES:
+        sage: Algebras(ZZ)
+        Category of algebras over Integer Ring
+        sage: Algebras(ZZ).super_categories()
+        [Category of rings, Category of modules over Integer Ring]
+
+    TESTS:
+        sage: C = Algebras(ZZ)
+        sage: loads(dumps(C)) == C
+        True
+
+    """
+
+    # For backward compatibility?
+    def __contains__(self, x):
+        from sage.structure.parent import Parent
+        from ring import Algebra
+        return (isinstance(x, Parent) and x.category()) or (isinstance(x, Algebra) and x.base_ring() == self.base_field())
+
+    def base_field(self):
+        """
+        Return the base field over which the algebras of this category
+        are all defined.
+        """
+        return self.base_ring()
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [Rings(), Modules(R)]
+
+    class ParentMethods: # (Algebra):  # Eventually, the content of Algebra should be moved here
+        def from_base_ring(self, r):
+            return self.one()._lmul_(r)
+
+        def __init_extra__(self):
+            # TODO: find and implement a good syntax!
+            self.register_coercion(SetMorphism(function = self.from_base_ring, parent = Hom(self.base_ring(), self, Rings())))
+            # Should be a morphism of Algebras(self.base_ring()), but e.g. QQ is not in Algebras(QQ)
+
+    class ElementMethods:
+        # TODO: move the content of AlgebraElement here
+
+        # Workaround: this sets back Semigroups.Element.__mul__, which is currently overriden by Modules.Element.__mul__
+        # What does this mean in terms of inheritance order?
+        # Could we do a variant like __mul__ = Semigroups.Element.__mul__
+        def __mul__(self, right): 
+            """
+            EXAMPLES::
+                sage: s = SFASchur(QQ)
+                sage: a = s([2])
+                sage: a._mul_(a) #indirect doctest
+                s[2, 2] + s[3, 1] + s[4]
+
+            Todo: use AlgebrasWithBasis(QQ).example()
+            """
+            if have_same_parent(self, right) and hasattr(self, "_mul_"):
+                return self._mul_(right)
+            from sage.structure.element import get_coercion_model
+            import operator
+            return get_coercion_model().bin_op(self, right, operator.mul)
+
+#        __imul__ = __mul__
+
+        # Parents in this category should implement _lmul_ and _rmul_
+
+        def _div_(self, y):
+            """
+            # TODO: move in Monoids
+
+            EXAMPLES:
+                sage: C = AlgebrasWithBasis(QQ).example()
+                sage: x = C(2); x
+                2*B[()]
+                sage: y = C.algebra_generators().first(); y
+                B[(1,2,3)]
+
+                sage: y._div_(x)
+                1/2*B[(1,2,3)]
+                sage: x._div_(y)
+                Traceback (most recent call last):
+                ...
+                ValueError: cannot invert self (= B[(1,2,3)])
+            """
+            return self.parent().product(self, ~y)
+
+    class DirectSumCategory(DirectSumCategory):
+        """
+        The category of modules with basis constructed by direct sums of modules with basis
+        """
+        @cached_method
+        def super_categories(self):
+            return [Algebras(self.base_category.base_ring())]
+
+        class ParentMethods:
+            @cached_method
+            def one(self):
+                """
+                EXAMPLES:
+                    sage: S = direct_sum([SymmetricGroupAlgebra(QQ, 3), SymmetricGroupAlgebra(QQ, 4)])
+                    sage: S.one()
+                    B[(0, [1, 2, 3])] + B[(1, [1, 2, 3, 4])]
+                """
+                return direct_sum([module.one() for module in self.modules])
+            
+            def product(self, left, right):
+                """
+                EXAMPLES:
+                    sage: A = SymmetricGroupAlgebra(QQ, 3);
+                    sage: x = direct_sum([A([1,3,2]), A([2,3,1])])
+                    sage: y = direct_sum([A([1,3,2]), A([2,3,1])])
+                    sage: direct_sum([A,A]).product(x,y)
+                    B[(0, [1, 2, 3])] + B[(1, [3, 1, 2])]
+                    sage: x*y
+                    B[(0, [1, 2, 3])] + B[(1, [3, 1, 2])]
+                """
+            
+                return direct_sum([(a*b) for (a,b) in zip(left.summand_split(), right.summand_split())])
diff --git a/sage/categories/algebras_with_basis.py b/sage/categories/algebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/algebras_with_basis.py
@@ -0,0 +1,366 @@
+r"""
+AlgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.abstract_method import abstract_method
+from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.categories.all import Category, TensorialCategory, TensorCategory, AbelianCategory, DirectSumCategory, tensor, DualityCategory, ModulesWithBasis, Algebras
+from category_types import Category_over_base_ring
+
+class AlgebrasWithBasis(Category_over_base_ring, AbelianCategory, TensorialCategory, DualityCategory):
+    """
+    The category of algebras with a distinguished basis
+
+    EXAMPLES::
+
+        sage: C = AlgebrasWithBasis(QQ); C
+        Category of algebras with basis over Rational Field
+        sage: C.super_categories()
+        [Category of modules with basis over Rational Field, Category of algebras over Rational Field]
+
+    We construct a typical parent in this category, and do some computations with it::
+
+        sage: A = C.example(); A
+        The group algebra of Dihedral group of order 6 as a permutation group over Rational Field
+
+        sage: A.category()
+        Category of algebras with basis over Rational Field
+
+        sage: A.one_basis()
+        ()
+        sage: A.one()
+        B[()]
+
+        sage: A.base_ring()
+        Rational Field
+        sage: A.basis().keys()
+        Dihedral group of order 6 as a permutation group
+
+        sage: [a,b] = A.algebra_generators()
+        sage: a, b
+        (B[(1,2,3)], B[(1,3)])
+        sage: a^3, b^2
+        (B[()], B[()])
+        sage: a*b
+        B[(1,2)]
+
+        sage: A.product
+        Generic endomorphism of The group algebra of Dihedral group of order 6 as a permutation group over Rational Field
+        sage: A.product(b,b)
+        B[()]
+
+        sage: A.check(verbose=True)
+        running test_additive_associativity ... done
+        running test_an_element ... done
+        running test_associativity ... done
+        running test_element_pickling ... done
+        running test_not_implemented_methods ... done
+        running test_one ... done
+        running test_pickling ... done
+        running test_prod ... done
+        running test_product ... done
+        running test_some_elements ... done
+        sage: A.__class__
+        <class 'sage.categories.examples.algebras_with_basis.MyGroupAlgebra_with_category'>
+        sage: A.element_class
+        <class 'sage.combinat.free_module.MyGroupAlgebra_with_category.element_class'>
+
+    Please see the source code of `A` (with ``A??``) for how to
+    implement other algebras with basis.
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [ModulesWithBasis(R), Algebras(R)]
+
+    def example(self, G = None):
+        """
+        Returns an example of algebra with basis::
+
+            sage: AlgebrasWithBasis(QQ).example()
+            The group algebra of Dihedral group of order 6 as a permutation group over Rational Field
+
+        An other group can be specified as optional argument::
+
+            sage: AlgebrasWithBasis(QQ).example(SymmetricGroup(4))
+            The group algebra of SymmetricGroup(4) over Rational Field
+
+        """
+        from sage.categories.examples.algebras_with_basis import MyGroupAlgebra
+        from sage.groups.perm_gps.permgroup_named import DihedralGroup
+        if G is None:
+            G = DihedralGroup(3)
+        return MyGroupAlgebra(self.base_ring(), G)
+
+    class ParentMethods:
+
+        #@cached_method   # todo: reinstate once #5843 is fixed
+        def one_from_one_basis(self):
+            return self.term(self.one_basis())
+
+        @lazy_attribute
+        def one(self):
+            if hasattr(self, "one_basis"):
+                return self.one_from_one_basis
+            else:
+                return NotImplemented
+
+        @lazy_attribute
+        def from_base_ring(self):
+            if hasattr(self, "one_basis"):
+                return self.from_base_ring_from_one_basis
+            else:
+                return NotImplemented
+
+        def from_base_ring_from_one_basis(self, r):
+            """
+            INPUTS:
+
+             - `r`: an element of the coefficient ring
+
+            Implements the canonical embeding from the ground ring.
+
+            EXAMPLES::
+
+                sage: A = AlgebrasWithBasis(QQ).example()
+                sage: A.from_base_ring_from_one_basis(3)
+                3*B[()]
+                sage: A.from_base_ring(3)
+                3*B[()]
+                sage: A(3)
+                3*B[()]
+
+            """
+            return self.monomial(self.one_basis(), r)
+
+        def test_one(self, **options):
+            tester = self.tester(**options)
+            tester.assert_(self.one() in self)
+            tester.assert_(all(self.one() * x == x for x in self.basis()))
+
+        @abstract_method("optional")
+        def product_on_basis(self, i, j):
+            """
+            The product of the algebra on the basis (optional)
+
+            INPUT:
+             - ``i``, ``j``: the indices of two elements of the basis of self
+
+            Returns the product of the two corresponding basis elements
+
+            If implemented, :met:`product` is defined from it by bilinearity.
+
+            EXAMPLES::
+
+                sage: A = AlgebrasWithBasis(QQ).example()
+                sage: i, j = A.algebra_generators().keys()
+                sage: i, j
+                ((1,2,3), (1,3))
+                sage: A.product_on_basis(i,j)
+                B[(1,2)]
+            """
+
+        @lazy_attribute
+        def product(self):
+            """
+            The product of the algebra, as per ``Algebras.ParentMethods.product``
+
+            By default, this is implemented from
+            :meth:`product_on_basis`, if available.
+
+            EXAMPLES::
+
+                sage: A = AlgebrasWithBasis(QQ).example()
+                sage: x, y = A.algebra_generators()
+                sage: A.product(x + 2*y, 3*y)
+                6*B[()] + 3*B[(1,2)]
+
+            """
+            if self.product_on_basis is not NotImplemented:
+                return self._module_morphism(self._module_morphism(self.product_on_basis, position = 0, codomain=self),
+                                                                                          position = 1)
+            elif hasattr(self, "_multiply") or hasattr(self, "_multiply_basis"):
+                return self._product_from_combinatorial_algebra_multiply
+            else:
+                return NotImplemented
+
+        # Backward compatibility temporary cruft to help migrating form CombinatorialAlgebra
+        def _product_from_combinatorial_algebra_multiply(self,left,right):
+            """
+            Returns left\*right where left and right are elements of self.
+            product() uses either _multiply or _multiply basis to carry out
+            the actual multiplication.
+
+            EXAMPLES::
+
+                sage: s = SFASchur(QQ)
+                sage: a = s([2])
+                sage: s.product(a,a)
+                s[2, 2] + s[3, 1] + s[4]
+            """
+            A = left.parent()
+            BR = A.base_ring()
+            z_elt = {}
+
+            #Do the case where the user specifies how to multiply basis elements
+            if hasattr(self, '_multiply_basis'):
+                for (left_m, left_c) in left._monomial_coefficients.iteritems():
+                    for (right_m, right_c) in right._monomial_coefficients.iteritems():
+                        res = self._multiply_basis(left_m, right_m)
+                        #Handle the case where the user returns a dictionary
+                        #where the keys are the monomials and the values are
+                        #the coefficients.  If res is not a dictionary, then
+                        #it is assumed to be an element of self
+                        if not isinstance(res, dict):
+                            if isinstance(res, self._element_class):
+                                res = res._monomial_coefficients
+                            else:
+                                res = {res: BR(1)}
+                        for m in res:
+                            if m in z_elt:
+                                z_elt[ m ] = z_elt[m] + left_c * right_c * res[m]
+                            else:
+                                z_elt[ m ] = left_c * right_c * res[m]
+
+            #We assume that the user handles the multiplication correctly on
+            #his or her own, and returns a dict with monomials as keys and
+            #coefficients as values
+            else:
+                m = self._multiply(left, right)
+                if isinstance(m, self._element_class):
+                    return m
+                if not isinstance(m, dict):
+                    z_elt = m.monomial_coefficients()
+                else:
+                    z_elt = m
+
+            #Remove all entries that are equal to 0
+            BR = self.base_ring()
+            zero = BR(0)
+            del_list = []
+            for m, c in z_elt.iteritems():
+                if c == zero:
+                    del_list.append(m)
+            for m in del_list:
+                del z_elt[m]
+
+            return self._from_dict(z_elt)
+
+
+
+        def test_product(self, **options):
+            tester = self.tester(**options)
+            tester.assert_(self.product is not None)
+            # could check that self.product is in Hom( self x self, self)
+
+    class ElementMethods:
+
+        def __invert__(self):
+            """
+            Returns the inverse of self if self is a multiple of one,
+            and one is in the basis of this algebra. Otherwise throws
+            an error.
+
+            Caveat: this generic implementation is not complete; there
+            may be invertible elements in the algebra that can't be
+            inversed this way. It is correct though for graded
+            connected algebras with basis.
+
+            EXAMPLES:
+            sage: C = AlgebrasWithBasis(QQ).example()
+            sage: x = C(2); x
+            2*B[()]
+            sage: ~x
+            1/2*B[()]
+            sage: x = C.algebra_generators().first(); x
+            B[(1,2,3)]
+            sage: ~x
+            Traceback (most recent call last):
+            ...
+            ValueError: cannot invert self (= B[(1,2,3)])
+            """
+            # FIXME: make this generic
+            mcs = self._monomial_coefficients
+            one = self.parent().one_basis()
+            if len(mcs) == 1 and one in mcs:
+                return self.parent()( ~mcs[ one ] )
+            else:
+                raise ValueError, "cannot invert self (= %s)"%self
+
+
+    class DirectSumCategory(DirectSumCategory):
+        """
+        The category of algebras with basis constructed by direct sums of algebras with basis
+        """
+
+        @cached_method
+        def super_categories(self):
+            return [AlgebrasWithBasis(self.base_category.base_ring())]
+
+        class ParentMethods:
+            #@cached_method   # todo: reinstate once #5843 is fixed
+            def one_from_direct_sum_of_one_basis(self):
+                # This implementation does not require multiplication by
+                # scalars nor calling direct_sum. This might help keeping
+                # things as lazy as possible upon initialization
+                return self.sum_of_terms( (i, self.modules[i].one_basis()) for i in range(len(self.modules)))
+
+            @lazy_attribute
+            def one(self):
+                if all(hasattr(module, "one_basis") for module in self.modules):
+                    return self.one_from_direct_sum_of_one_basis
+                else:
+                    return NotImplemented
+
+            #def product_on_basis(self, t1, t2):
+            # would be easy to implement, but without a special
+            # version of module morphism, this would not take
+            # advantage of the bloc structure
+
+
+    class TensorCategory(TensorCategory):
+        """
+        The category of algebras with basis constructed by tensor product of algebras with basis
+        """
+
+        @cached_method
+        def super_categories(self):
+            return [AlgebrasWithBasis(self.base_category.base_ring())]
+
+        class ParentMethods:
+            """
+            implements operations on tensor products of algebras with basis
+            """
+
+            @cached_method
+            def one_basis(self):
+                if all(hasattr(module, "one_basis") for module in self.modules):
+                    return tuple(module.one_basis() for module in self.modules)
+
+            def product_on_basis(self, t1, t2):
+                # TODO: optimize!
+                return tensor( (module.term(x1)*module.term(x2) for (module, x1, x2) in zip(self.modules, t1, t2)) )
+
+        class ElementMethods:
+            """
+            implements operations on elements of tensor products of algebras with basis
+            """
+            pass
diff --git a/sage/categories/bialgebras.py b/sage/categories/bialgebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/bialgebras.py
@@ -0,0 +1,51 @@
+r"""
+Bialgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.categories.category_types import Category_over_base_ring
+from sage.categories.all import Algebras, Coalgebras
+
+class Bialgebras(Category_over_base_ring):
+    """
+    The category of bialgebras
+
+    EXAMPLES:
+      sage: Bialgebras(ZZ)
+      Category of bialgebras over Integer Ring
+      sage: Bialgebras(ZZ).super_categories()
+      [Category of algebras over Integer Ring, Category of coalgebras over Integer Ring]
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [Algebras(R), Coalgebras(R)]
+
+    class ParentMethods:
+        @lazy_attribute
+        def antipode(self, existence_only):
+            if self.implements("antipode_basis"):
+                if existence_only:
+                    return True
+                else:
+                    return self.module_morphism(self.antipode_basis)
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/bialgebras_with_basis.py b/sage/categories/bialgebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/bialgebras_with_basis.py
@@ -0,0 +1,53 @@
+r"""
+BialgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_attribute import lazy_attribute
+from category_types import Category_over_base_ring
+from sage.categories.all import AlgebrasWithBasis, CoalgebrasWithBasis, Bialgebras
+
+class BialgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of bialgebras with a distinguished basis
+
+    EXAMPLES::
+
+        sage: BialgebrasWithBasis(ZZ)
+        Category of bialgebras with basis over Integer Ring
+        sage: BialgebrasWithBasis(ZZ).super_categories()
+        [Category of algebras with basis over Integer Ring, Category of coalgebras with basis over Integer Ring, Category of bialgebras over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [AlgebrasWithBasis(R), CoalgebrasWithBasis(R), Bialgebras(R)]
+
+    class ParentMethods:
+        @lazy_attribute
+        def antipode(self, existence_only):
+            if self.implements("antipode_basis"):
+                if existence_only:
+                    return True
+                else:
+                    return self.module_morphism(self.antipode_basis)
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/bimodules.py b/sage/categories/bimodules.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/bimodules.py
@@ -0,0 +1,75 @@
+r"""
+Bimodules
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.all import Category, LeftModules, RightModules
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+#?class Bimodules(Category_over_base_rng, Category_over_base_rng):
+class Bimodules(Category):
+    """
+    The category of (R,S)-bimodules
+
+    A (R,S)-bimodule is a left R-module and right S-module such that
+    the left and right actions commute: $r*(x*s) = (r*x)*s$
+
+    EXAMPLES:
+      sage: Bimodules(QQ, ZZ)
+      Category of bimodules over Rational Field on the left and Integer Ring on the right
+      sage: Bimodules(QQ, ZZ).super_categories()
+      [Category of left modules over Rational Field, Category of right modules over Integer Ring]
+
+    """
+
+    def __init__(self, left_base, right_base, name=None):
+        Category.__init__(self, name)
+        self.__left_base_ring = left_base 
+        self.__right_base_ring = right_base 
+
+    def _repr_(self):
+        return Category._repr_(self) + " over %s on the left and %s on the right" \
+            %(self.__left_base_ring, self.__right_base_ring)
+
+    def left_base_ring(self):
+        """
+        Return the left base ring over which elements of this category are
+        defined.
+        """
+        return self.__left_base_ring
+
+    def right_base_ring(self):
+        """
+        Return the right base ring over which elements of this category are
+        defined.
+        """
+        return self.__right_base_ring
+
+    def _latex_(self):
+        return "\\mbox{\\bf %s}_{%s}_{%s}"%(self.__label, latex(self.__left_base_ring), latex(self.__right_base_ring))
+
+    @cached_method
+    def super_categories(self):
+        R = self.left_base_ring()
+        S = self.right_base_ring()
+        return [LeftModules(R), RightModules(S)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/coalgebras.py b/sage/categories/coalgebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/coalgebras.py
@@ -0,0 +1,85 @@
+from category_types import Category_over_base_ring
+from sage.categories.all import Modules, Algebras, TensorialCategory, TensorCategory, DualityCategory, tensor
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.misc.cachefunc import cached_method
+
+class Coalgebras(Category_over_base_ring, TensorialCategory, DualityCategory):
+    """
+    The category of coalgebras
+
+    EXAMPLES::
+
+        sage: Coalgebras(QQ)
+        Category of coalgebras over Rational Field
+        sage: Coalgebras(QQ).super_categories()
+        [Category of modules over Rational Field]
+        sage: Coalgebras(QQ).all_super_categories() # todo: update once the hierarchy is more appropriate
+        [Category of coalgebras over Rational Field,
+         Category of modules over Rational Field,
+         Category of bimodules over Rational Field on the left and Rational Field on the right,
+         Category of left modules over Rational Field,
+         Category of right modules over Rational Field,
+         Category of abelian groups,
+         Category of abelian monoids,
+         Category of abelian semigroups,
+         Category of sets,
+         Category of objects]
+    """
+    @cached_method
+    def super_categories(self):
+        return [Modules(self.base_ring())]
+
+    def dual(self):
+        """
+            Returns the dual category
+
+            EXAMPLES:
+                The category of coalgebras over the Rational Field is dual
+                to the category of algebras over the same field:
+
+                sage: C = Coalgebras(QQ)
+                sage: C.dual()
+                Category of algebras over Rational Field
+        """
+        return Algebras(self.base_ring())
+
+    class ParentMethods:
+        def __init_add__(self): # The analogue of initDomainAdd
+            # If it exists, declare the coproduct of self to the coercion mechanism
+            pass
+
+        # TODO: attribute/method? caching just rely on the caching of Tensor?
+        @lazy_attribute
+        def tensor_square(self):
+            return tensor([self, self])
+
+        # CHECKME
+        def coproduct(self, x):
+            """
+            Returns the coproduct of x
+
+            The default implementation is to delegate to the
+            overloading mechanism and force the conversion back
+            """
+            return self.tensor_square(overloaded_coproduct(x))
+
+    class ElementMethods:
+        def coproduct(self):
+            """
+            Returns the coproduct of self
+            """
+            return self.parent().coproduct(self)
+
+    class TensorCategory(TensorCategory):
+        @cached_method
+        def super_categories(self):
+            return [Coalgebras(self.base_category.base_ring())]
+
+        class ParentMethods:
+            def coproduct(self):
+                # Not tested yet!
+                return tensor(module.coproduct for module in self.modules)
+
+        class ElementMethods:
+            " implements operations on elements of tensor products of coalgebras"
+            pass
diff --git a/sage/categories/coalgebras_with_basis.py b/sage/categories/coalgebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/coalgebras_with_basis.py
@@ -0,0 +1,69 @@
+r"""
+CoalgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.abstract_method import abstract_method
+from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_attribute import lazy_attribute
+from category_types import Category_over_base_ring
+from sage.categories.all import Coalgebras, ModulesWithBasis, tensor, Hom
+#from sage.categories.homset import Hom 
+
+class CoalgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of coalgebras with a distinguished basis
+
+    EXAMPLES:
+      sage: CoalgebrasWithBasis(ZZ)
+      Category of coalgebras with basis over Integer Ring
+      sage: CoalgebrasWithBasis(ZZ).super_categories()
+      [Category of modules with basis over Integer Ring, Category of coalgebras over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [ModulesWithBasis(R), Coalgebras(R)]
+
+    class ParentMethods:
+
+        @abstract_method("optional")
+        def coproduct_on_basis(self, i):
+            """
+            The product of the algebra on the basis (optional)
+
+            INPUT:
+             - ``i``: the indices of an element of the basis of self
+
+            Returns the coproduct of the corresponding basis elements
+            If implemented, the coproduct of the algebra is defined
+            from it by linearity.
+            """
+
+    class ParentMethods:
+        @lazy_attribute
+        def coproduct(self):
+            if self.coproduct_on_basis is not NotImplemented:
+                # TODO: if self is a coalgebra, then one would want
+                # to create a morphism of algebras with basis instead
+                # should there be a method self.coproduct_hom_category?
+                return Hom(self, tensor([self, self]), ModulesWithBasis(self.base_ring()))(on_basis = self.coproduct_on_basis)
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/commutative_algebra_ideals.py b/sage/categories/commutative_algebra_ideals.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/commutative_algebra_ideals.py
@@ -0,0 +1,40 @@
+r"""
+CommutativeAlgebraIdeals
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from category_types import Category_ideal
+
+class CommutativeAlgebraIdeals(Category_ideal):
+    """
+    The category of ideals in a fixed commutative algebra $A$.
+    """
+    def __init__(self, A):
+        if not is_CommutativeAlgebra(A):
+            raise TypeError, "A (=%s) must be a commutative algebra"%A
+        Category_in_ambient.__init__(self, A)
+
+    def algebra(self):
+        return self.ambient()
+    
+    @cached_method
+    def super_categories(self):
+        from algebra_ideals import AlgebraIdeals
+        R = self.algebra()
+        return [AlgebraIdeals(R)]
diff --git a/sage/categories/commutative_algebras.py b/sage/categories/commutative_algebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/commutative_algebras.py
@@ -0,0 +1,43 @@
+r"""
+MonoidAlgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from category_types import Category_over_base_ring
+
+class CommutativeAlgebras(Category_over_base_ring):
+    """
+    The category of commutative algebras over a given base ring.
+
+    EXAMPLES:
+        sage: M = CommutativeAlgebras(GF(19))
+        sage: M
+        Category of commutative algebras over Finite Field of size 19
+
+    TESTS:
+        sage: C = CommutativeAlgebras(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+    
+    @cached_method
+    def super_categories(self):
+        from algebras import Algebras
+        R = self.base_ring()
+        return [Algebras(R)]
diff --git a/sage/categories/commutative_ring_ideals.py b/sage/categories/commutative_ring_ideals.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/commutative_ring_ideals.py
@@ -0,0 +1,49 @@
+r"""
+CommutativeRingIdeals
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from category_types import Category_ideal
+
+class CommutativeRingIdeals(Category_ideal):
+    """
+    The category of ideals in a fixed commutative ring.
+    
+    EXAMPLES:
+
+        sage: C = CommutativeRingIdeals(IntegerRing())
+        sage: C
+        Category of commutative ring ideals in Integer Ring
+
+    TESTS:
+        sage: C = CommutativeRingIdeals(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, R):
+        import sage.rings.all
+        if not sage.rings.all.is_CommutativeRing(R):
+            raise TypeError, "R (=%s) must be a commutative ring"%R
+        Category_ideal.__init__(self, R)
+        
+    @cached_method
+    def super_categories(self):
+        from ring_ideals import RingIdeals
+        R = self.ring()
+        return [RingIdeals(R)]
diff --git a/sage/categories/commutative_rings.py b/sage/categories/commutative_rings.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/commutative_rings.py
@@ -0,0 +1,50 @@
+r"""
+CommutativeRings
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class CommutativeRings(Category):
+    """
+    The category of commutative rings
+
+    commutative rings with unity, i.e. rings with commutative * and 
+    a multiplicative identity
+
+    EXAMPLES:
+      sage: CommutativeRings()
+      Category of commutative rings
+      sage: CommutativeRings().super_categories()
+      [Category of rings]
+
+    TESTS:
+        sage: C = CommutativeRings()
+        sage: loads(C.dumps()) == C
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        from sage.categories.rings import Rings
+        return [Rings()] # TODO: Bimodule(R,R)
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/division_rings.py b/sage/categories/division_rings.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/division_rings.py
@@ -0,0 +1,46 @@
+r"""
+DivisionRings
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class DivisionRings(Category):
+    """
+    The category of division rings
+
+    a division ring (or skew field) is a not necessarily commutative
+    ring where all non-zero elements have multiplicative inverses
+
+    EXAMPLES:
+      sage: DivisionRings()
+      Category of division rings
+      sage: DivisionRings().super_categories()
+      [Category of entire rings]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        from sage.categories.entire_rings import EntireRings
+        return [EntireRings()] # TODO: Algebra(QQ) sounds wrong (think Z/Z2)
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/entire_rings.py b/sage/categories/entire_rings.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/entire_rings.py
@@ -0,0 +1,46 @@
+r"""
+EntireRings
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.rings import Rings
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class EntireRings(Category):
+    """
+    The category of entire rings
+
+    An entire ring (or non-commutative integral domains), is a not
+    necessarily commutative ring which has no zero divisors.
+
+    EXAMPLES:
+        sage: EntireRings()
+        Category of entire rings
+        sage: EntireRings().super_categories()
+        [Category of rings]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [Rings()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/enumerated_sets.py b/sage/categories/enumerated_sets.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/enumerated_sets.py
@@ -0,0 +1,535 @@
+r"""
+Enumerated Sets
+"""
+#*****************************************************************************
+#  Copyright (C) 2009 Florent Hivert <Florent.Hivert@univ-rouen.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+
+from sage.structure.element import Element
+from sage.structure.parent import Parent
+from category_types import Category
+from sage.misc.cachefunc import cached_method
+from sage.categories.sets_cat import Sets
+from sage.rings.integer import Integer
+
+class EnumeratedSets(Category):
+    """
+    The category of enumerated sets
+
+    An *enumerated set* is a *finite* or *countable* set or multiset together
+    with a canonical enumeration of its elements; Conceptually, this is very
+    similar to an imutable list. The main differences lies in the names and
+    the return typeof the methods, and of course the fact that the list of
+    element is not supposed to be expanded in memory. Except in the unlikely
+    case where you want to implement an enumerated set for which you don't
+    know the cardinality, you should use one of the two sub-categories
+    ``FiniteEnumeratedSets()`` or ``InfiniteEnumeratedSets()``. 
+
+    The goal of this category is threefold:
+       - to fix a common interface for all these sets;
+       - to provide a bunch of default implementations;
+       - to provide consistency tests. 
+    
+    The standard methods for an enumerated set ``S`` are:
+
+       - ``S.cardinality()``: the number of element of the set. This is the
+         equivalent for ``len`` on a list except that the return value is
+         specified to be a sage ``Integer`` or ``Infinity``, instead of a
+         python ``int``;
+
+       - ``iter(S)``: an iterator for the element of the set;
+       
+       - ``S.list()``: the list of the element of the set when possible; raise a
+         NotImplementedError if the list is too large to be expanded in
+         memory.
+
+       - ``S.unrank(n)``: the  ``n-th`` element of the set when ``n`` is a sage
+         ``Integer``. This is the equivanlent for ``l[n]`` on a list. 
+         
+       - ``S.rank(e)``: the position of the element ``e`` in the set; This is
+         equivalent to ``l.index(e)`` for a list except that return value is
+         specified to be a sage ``Integer``, instead of a python ``int``;
+
+       - ``S.first()``: the first object of the set; It is equivalent to
+         ``S.unrank(0)``;
+
+       - ``S.next(e)``: the object of the set which follows ``e``; It is
+         equivalent to ``S.unrank(S.rank(e)+1)``.
+
+       - ``S.random_element()``: a random generator for an element of the set;
+         Unless otherwise stated, for finite enumerated sets the probability
+         is uniform.
+         
+    For examples and test see:
+    
+       - FiniteEnumeratedSets().example()
+       - InfiniteEnumeratedSets().example()
+
+       
+    EXAMPLES::
+    
+        sage: EnumeratedSets()
+        Category of enumerated sets
+        sage: EnumeratedSets().super_categories()
+        [Category of sets]
+        sage: EnumeratedSets().all_super_categories()
+        [Category of enumerated sets, Category of sets, Category of objects]
+
+    TESTS::
+    
+        sage: C = EnumeratedSets()
+        sage: loads(C.dumps()) == C
+        True    """
+
+    @cached_method
+    def super_categories(self):
+        return [Sets()]
+
+
+    class ParentMethods:
+        """
+        Parent class for the enumerated set category 
+        """
+
+        def __iter__(self):
+            """
+            An iterator for the enumerated set. 
+            
+            ``iter(self)`` allows the combinatorial class to be treated as an
+            iterator. This if the default implementation from the category
+            ``EnumeratedSet()`` it just goes through the iterator of the set
+            to count the number of objects.
+
+            By decreasing order of priority, the second column of the
+            following array shows which methods is used to define
+            ``__iter__``, when the methods of the first column are overloaded:
+
+            +------------------------+---------------------------------+ 
+            | Needed methods         | Default ``__iterator`` provided |
+            +========================+=================================+ 
+            | ``first`` and ``next`` | ``_iterator_from_next``         |
+            +------------------------+---------------------------------+ 
+            | ``unrank``             | ``_iterator_from_unrank``       |
+            +------------------------+---------------------------------+ 
+            | ``list`                | ``_iterator_from_next``         |
+            +------------------------+---------------------------------+ 
+
+            If non of these are provided raise a ``NotImplementedError``
+            
+            EXAMPLES::
+
+            We start with an example where nothing is implemented::
+            
+                sage: class broken(UniqueRepresentation, Parent):
+                ...    def __init__(self):
+                ...        Parent.__init__(self, category = EnumeratedSets())
+                ...
+                sage: it = iter(broken()); [it.next(), it.next(), it.next()]
+                Traceback (most recent call last):
+                ...
+                NotImplementedError: iterator called but not implemented
+
+            Here is what happends when ``first`` and ``next`` are implemeted::
+                
+                sage: class set_first_next(UniqueRepresentation, Parent):
+                ...    def __init__(self):
+                ...        Parent.__init__(self, category = EnumeratedSets())
+                ...    def first(self):
+                ...        return 0
+                ...    def next(self, elt):
+                ...        return elt+1
+                ...
+                sage: it = iter(set_first_next()); [it.next(), it.next(), it.next()]
+                [0, 1, 2]
+
+            Let's try with ``unrank``::
+            
+                sage: class set_unrank(UniqueRepresentation, Parent):
+                ...    def __init__(self):
+                ...        Parent.__init__(self, category = EnumeratedSets())
+                ...    def unrank(self, i):
+                ...        return i + 5
+                ...
+                sage: it = iter(set_unrank()); [it.next(), it.next(), it.next()]
+                [5, 6, 7]
+
+            Let's finally try with ``list``::
+            
+                sage: class set_list(UniqueRepresentation, Parent):
+                ...    def __init__(self):
+                ...        Parent.__init__(self, category = EnumeratedSets())
+                ...    def list(self):
+                ...        return [5, 6, 7]
+                ...
+                sage: it = iter(set_list()); [it.next(), it.next(), it.next()]
+                [5, 6, 7]
+                
+            """
+            #Check to see if .first() and .next() are overridden in the subclass
+            if ( self.first != self._first_from_iterator and
+                 self.next  != self._next_from_iterator ):
+                return self._iterator_from_next()
+            #Check to see if .unrank() is overridden in the subclass
+            elif self.unrank != self._unrank_from_iterator:
+                return self._iterator_from_unrank()
+            #Finally, check to see if .list() is overridden in the subclass
+            elif self.list != self._list_default:
+                return self._iterator_from_list()
+            else:
+                raise NotImplementedError, "iterator called but not implemented"
+       
+        
+        def cardinality(self):
+            """
+            The cardinality of ``self``.
+
+            ``self.cardinality()`` should returns the cardinality of the set
+            ``self`` as a sage ``Integer`` or as ``+Infinity``.
+            
+            This if the default implementation from the category
+            ``EnumeratedSet()`` it returns `NotImplementedError` since one does
+            not know if the set is finite or not.
+            
+            EXAMPLES::
+        
+                sage: class broken(UniqueRepresentation, Parent):
+                ...    def __init__(self):
+                ...        Parent.__init__(self, category = EnumeratedSets())
+                ...
+                sage: broken().cardinality()
+                Traceback (most recent call last):
+                ...
+                NotImplementedError: unknown cardinality
+            """
+            raise NotImplementedError, "unknown cardinality"
+
+        def list(self):
+            """
+            Returns an error since the cardinality of self is not known.
+        
+            EXAMPLES::
+
+                sage: class broken(UniqueRepresentation, Parent):
+                ...    def __init__(self):
+                ...        Parent.__init__(self, category = EnumeratedSets())
+                ...
+                sage: broken().list()
+                Traceback (most recent call last):
+                ...
+                NotImplementedError: unknown cardinality
+            """
+            raise NotImplementedError, "unknown cardinality"
+        _list_default  = list # needed by the check system. 
+
+        
+        def _first_from_iterator(self):
+            """
+            The "first" element of ``self``.
+
+            ``self.first()`` returns the first element of the set
+            ``self``. This is a generic implementation from the category
+            ``EnumeratedSet()`` which can be used when the method ``__iter__`` is
+            provided.
+
+            EXAMPLES::
+
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.first() # indirect doctest
+                1
+            """
+            it = self.__iter__()
+            return it.next()
+        first = _first_from_iterator
+
+        def _next_from_iterator(self, obj):
+            """
+            The "next" element after ``obj`` in ``self``.
+
+            ``self.next(e)`` returns the element of the set ``self`` which
+            follows ``e``. This is a generic implementation from the category
+            ``EnumeratedSet()`` which can be used when the method ``__iter__``
+            is provided.
+
+            Remark: It is rather slow !!!
+
+            EXAMPLES::
+        
+                sage: C = InfiniteEnumeratedSets().example()
+                sage: C._next_from_iterator(10) # indirect doctest
+                11
+            """
+            it = iter(self)
+            el = it.next()
+            while el != obj:
+                el = it.next()
+            return it.next()
+        next = _next_from_iterator
+        
+        
+        def _unrank_from_iterator(self, r):
+            """
+            The ``r``-th element of ``self``
+
+            ``self.unrank(r)`` returns the ``r``-th element of self where
+            ``r`` is an integer between ``0`` and ``n-1`` where ``n`` is the
+            cardinality of ``self``. This is a generic implementation from the
+            category ``EnumeratedSet()`` which can be used when the method
+            ``__iter__`` is provided. It may be extermely slow.
+            
+            EXAMPLES::
+        
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.unrank(2) # indirect doctest
+                3
+                sage: C.unrank(5) # indirect doctest
+                Traceback (most recent call last):
+                ...
+                ValueError: the value must be between 0 and 2 inclusive
+            """
+            counter = 0
+            for u in self:
+                if counter == r:
+                    return u
+                counter += 1
+            raise ValueError, "the value must be between %s and %s inclusive"%(0,counter-1)
+        unrank = _unrank_from_iterator    
+
+        def _iterator_from_list(self):
+            """
+            An iterator for the elements of ``self``.
+
+            ``self.iterator()`` returns an iterator for the element of the set
+            ``self``. This is a generic implementation from the category
+            ``EnumeratedSet()`` which can be used when the method ``list`` is
+            provided.
+        
+            EXAMPLES::
+        
+                sage: C = FiniteEnumeratedSets().example()
+                sage: it = C._iterator_from_list()
+                sage: [it.next(), it.next(), it.next()]
+                [1, 2, 3]
+            """
+            for x in self.list():
+                yield x
+        
+        def _iterator_from_next(self):
+            """
+            An iterator for the elements of ``self``.
+
+            ``self.iterator()`` returns an iterator for the element of the set
+            ``self``. This is a generic implementation from the category
+            ``EnumeratedSet()`` which can be used when then methods ``first``
+            and ``next`` are provided.
+
+            EXAMPLES::
+
+                sage: C = InfiniteEnumeratedSets().example()
+                sage: it = C._iterator_from_next()
+                sage: [it.next(), it.next(), it.next(), it.next(), it.next()]
+                [0, 1, 2, 3, 4]
+            """
+            f = self.first()
+            yield f
+            while True:
+                try:
+                    f = self.next(f)
+                except (TypeError, ValueError ):
+                    break
+            
+                if f is None or f is False :
+                    break
+                else:
+                    yield f
+
+        def _iterator_from_unrank(self):
+            """
+            An iterator for the elements of ``self``.
+
+            ``self.iterator()`` returns an iterator for the element of the set
+            ``self``. This is a generic implementation from the category
+            ``EnumeratedSet()`` which can be used when the method ``unrank`` is
+            provided.
+
+            EXAMPLES::
+
+                sage: C = InfiniteEnumeratedSets().example()
+                sage: it = C._iterator_from_unrank()
+                sage: [it.next(), it.next(), it.next(), it.next(), it.next()]
+                [0, 1, 2, 3, 4]
+            """
+            r = 0
+            u = self.unrank(r)
+            yield u
+            while True:
+                r += 1
+                try:
+                    u = self.unrank(r)
+                except (TypeError, ValueError, IndexError):
+                    break
+            
+                if u == None:
+                    break
+                else:
+                    yield u
+
+
+                    
+        def _an_element_from_iterator(self):
+            """
+            An element in ``self``.
+
+            ``self.an_element()`` returns a particular element of the set
+            ``self``. This is a generic implementation from the category
+            ``EnumeratedSet()`` which can be used when the method ``__iter__``
+            is provided.
+
+            EXAMPLES::
+            
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.an_element() # indirect doctest
+                1
+            """
+            it = self.__iter__()
+            return it.next()                    
+        _an_element_ = _an_element_from_iterator
+
+        #FIXME: use combinatorial_class_from_iterator once class_from_iterator.patch is in
+        def _some_elements_from_iterator(self):
+            """
+            Some elements in ``self``.
+
+            ``self.some_element()`` returns an iterator for some particular
+            elements of the set ``self``. This is a generic implementation
+            from the category ``EnumeratedSet()`` which can be used when the
+            method ``__iter__`` is provided.
+
+            EXAMPLES::
+            
+                sage: C = FiniteEnumeratedSets().example()
+                sage: list(C.some_elements()) # indirect doctest
+                [1, 2, 3]
+            """
+            nb = 0
+            for i in self:
+                yield i
+                nb += 1
+                if nb >= 100:
+                    break
+        some_elements = _some_elements_from_iterator
+
+        def random_element(self):
+            """
+            A random element in ``self``.
+        
+            ``self.random_element()`` should returns a random element in
+            ``self``. This is a generic implementation from the category
+            ``EnumeratedSet()`` it raise a ``NotImplementedError`` since one
+            does not know if the set is finite.
+
+            EXAMPLES::
+        
+                sage: class broken(UniqueRepresentation, Parent):
+                ...    def __init__(self):
+                ...        Parent.__init__(self, category = EnumeratedSets())
+                ...
+                sage: broken().random_element()
+                Traceback (most recent call last):
+                ...
+                NotImplementedError: unknown cardinality
+                """
+            raise NotImplementedError, "unknown cardinality"
+
+        
+        
+#
+#  Consistency test suite for an enumerated set:         
+#        
+        # If the enumerated set is large, one can stop some coeherency tests
+        # after looking at the first element by setting the following variable:
+        max_test_enumerated_set_loop=100 # TODO: Devise a sensible bound !!
+        ##########
+        def test_enumerated_set_contains(self, **options):
+            tester = self.tester(**options)
+            """
+            Check the coherency between methods ``__contains__`` and ``__iter__``.
+            Automagically called by ``check()``
+
+            TESTS::
+
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.test_enumerated_set_contains()
+                sage: C.check()
+
+            Let's now break the class::
+                
+                sage: from sage.categories.examples.finite_enumerated_sets import Example
+                sage: class CCls(Example):
+                ...       def __contains__(self, obj):
+                ...           if obj == 3:
+                ...               return False
+                ...           else:
+                ...               return obj in C  
+                sage: CC = CCls()
+                sage: CC.check()
+                Traceback (most recent call last):
+                ...
+                AssertionError
+            """
+            i = 0
+            for w in self:
+                tester.assertTrue(w in self)
+                i += 1
+                if i > self.max_test_enumerated_set_loop:
+                    return
+                
+        def test_enumerated_set_iter_list(self, **options):
+            tester = self.tester(**options)
+            """
+            Check the coherency between methods ``list`` and ``__iter__``
+            Automagically called by ``check()``
+
+            EXAMPLES::
+            
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.test_enumerated_set_iter_list()
+
+            Let's now break the class::
+                
+                sage: from sage.categories.examples.finite_enumerated_sets import Example
+                sage: class CCls(Example):
+                ...       def list(self):
+                ...           return [1,2,3,4]
+                sage: CC = CCls()
+                sage: CC.check()
+                Traceback (most recent call last):
+                ...
+                AssertionError: 3 != 4
+            """
+            if self.list != self._list_default:
+                ls = self.list()
+                i = 0
+                for obj in self:
+                    tester.assertEqual(obj, ls[i])
+                    i += 1
+                    if i > self.max_test_enumerated_set_loop:
+                        return
+                tester.assertEqual(i, len(ls))
+        
+    class ElementMethods:
+        def rank(self):
+            return self.parent().rank(self)
+
+
diff --git a/sage/categories/euclidean_domains.py b/sage/categories/euclidean_domains.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/euclidean_domains.py
@@ -0,0 +1,46 @@
+r"""
+EuclideanDomains
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.basic import PrincipalIdealDomains
+from sage.misc.cachefunc import cached_method
+
+class EuclideanDomains(Category):
+    """
+    The category of euclidean domains
+    constructive euclidean domain, i.e. one can divide producing a quotient and a
+    remainder where the remainder is either zero or is "smaller" than the divisor
+
+
+    EXAMPLES:
+      sage: EuclideanDomains()
+      Category of euclidean domains
+      sage: EuclideanDomains().super_categories()
+      [Category of principal ideal domains]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [PrincipalIdealDomains()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/examples/__init__.py b/sage/categories/examples/__init__.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/__init__.py
@@ -0,0 +1,1 @@
+
diff --git a/sage/categories/examples/algebras_with_basis.py b/sage/categories/examples/algebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/algebras_with_basis.py
@@ -0,0 +1,45 @@
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.sets.family import Family
+from sage.categories.all import AlgebrasWithBasis
+from sage.combinat.free_module import CombinatorialFreeModule
+
+class MyGroupAlgebra(CombinatorialFreeModule):
+    r"""
+    A minimal example of algebra with basis: the group algebra of a group.
+    """
+
+    def __init__(self, R, G):
+        self.group = G
+        CombinatorialFreeModule.__init__(self, R, G, category = AlgebrasWithBasis(R))
+
+    def _repr_(self):
+        return "The group algebra of %s over %s"%(self.group, self.base_ring())
+
+    @cached_method
+    def one_basis(self):
+        return self.group.one()
+
+    def product_on_basis(self, g1, g2):
+        return self.basis()[g1 * g2]
+
+    @cached_method
+    def algebra_generators(self):
+        return Family(self.group.gens(), self.term)
+
+    def some_elements(self):
+        return self.basis()
diff --git a/sage/categories/examples/finite_enumerated_sets.py b/sage/categories/examples/finite_enumerated_sets.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/finite_enumerated_sets.py
@@ -0,0 +1,58 @@
+
+#################################################################    
+#                                                               #
+#                        Examples                               #
+#                                                               #
+#################################################################    
+from sage.structure.element import Element
+from sage.structure.parent import Parent
+from sage.structure.unique_representation import UniqueRepresentation
+from sage.structure.element_wrapper import ElementWrapper
+from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
+        
+#################################################################    
+# Example of an enumerated set
+class Example(UniqueRepresentation, Parent):
+    r"""
+    Example of an enumerated set
+
+    This class shows a minimal example of an enumerated set.
+
+    EXAMPLES::
+
+        sage: C = FiniteEnumeratedSets().example()
+        sage: C.cardinality() #indirect doctest
+        3
+        sage: C.list()
+        [1, 2, 3]
+
+    To check if the different methods of the enumerated set C return
+    consistent results, on can simpli use::
+        
+        sage: C.check()
+
+    TESTS::
+    
+        sage: loads(C.dumps()) == C
+        True
+    """
+    
+    def __init__(self):
+        Parent.__init__(self, category = FiniteEnumeratedSets())
+
+    def _repr_(self):
+        return "example of finite enumerated set"
+        
+    def __contains__(self, o):
+        return o in [1,2,3]
+        
+    def __iter__(self):
+        return iter([1,2,3])
+
+    # temporarily needed because parent overload it. 
+    def an_element(self):
+        return self._an_element_from_iterator()
+    
+    class Element(ElementWrapper):
+        pass
+                
diff --git a/sage/categories/examples/finite_semigroups.py b/sage/categories/examples/finite_semigroups.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/finite_semigroups.py
@@ -0,0 +1,123 @@
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.misc.cachefunc import cached_method
+from sage.sets.family import Family
+from sage.categories.all import FiniteSemigroups
+from sage.structure.parent import Parent
+from sage.structure.unique_representation import UniqueRepresentation
+from sage.structure.element_wrapper import ElementWrapper
+
+
+# Example of a finite semi-group    
+class LRBand(UniqueRepresentation, Parent):
+    r"""
+    An example of finite semigroup
+
+    The purpose of this class is to provide a minimal template for
+    implementing of a finite semi-group.
+
+    EXAMPLES:
+        sage: S=FiniteSemigroups().example(); S
+        An example of finite semi-group: the left regular band generated by ('a', 'b', 'c', 'd')
+
+    This is the semi group generated by::
+
+        sage: S.semigroup_generators()
+        Family ('a', 'b', 'c', 'd')
+
+    such that ``x^2 = x`` and `x y x = xy` for any `x` and `y` in `S`.
+
+        sage: S('dab')
+        'dab'
+        sage: S('dab') * S('acb')
+        'dabc'
+
+    # todo: profile the operations below
+
+    It follows that the elements of `S` are strings without
+    repetitions over the alphabet `a`, `b`, `c`, `d`::
+
+        sage: S.list()
+        ['a', 'c', 'b', 'bd', 'bda', 'd', 'bdc', 'bc', 'bcd', 'cb',
+         'ca', 'ac', 'cba', 'ba', 'cbd', 'bdca', 'db', 'dc', 'cd',
+         'bdac', 'ab', 'abd', 'da', 'ad', 'cbad', 'acb', 'abc',
+         'abcd', 'acbd', 'cda', 'cdb', 'dac', 'dba', 'dbc', 'dbca',
+         'dcb', 'abdc', 'cdab', 'bcda', 'dab', 'acd', 'dabc', 'cbda',
+         'bca', 'dacb', 'bad', 'adb', 'bac', 'cab', 'adc', 'cdba',
+         'dca', 'cad', 'adbc', 'adcb', 'dbac', 'dcba', 'acdb', 'bacd',
+         'cabd', 'cadb', 'badc', 'bcad', 'dcab']
+
+    There are 64 of them::
+
+        sage: S.cardinality()
+        64
+
+    Indeed::
+
+        sage: 4 * ( 1 + 3 * (1 + 2 * (1 + 1)))
+        64
+
+    As expected, all the elements of `S` are idempotents::
+
+        sage: all( x.is_idempotent() for x in S )
+        True
+
+    Now, let us look at the structure of the semigroup::
+
+        sage: S = FiniteSemigroups().example(alphabet = ('a','b','c'))
+        sage: S.cayley_graph(side = "left", simple = True).plot()
+        sage: S.j_transversal_of_idempotents()
+        ['cab', 'ca', 'ab', 'cb', 'a', 'c', 'b']
+
+    We conclude by running systematic tests on this semigroup::
+
+        sage: S.check(verbose = True)
+        running test_an_element ... done
+        running test_associativity ... done
+        running test_element_pickling ... done
+        running test_enumerated_set_contains ... done
+        running test_enumerated_set_iter_cardinality ... done
+        running test_enumerated_set_iter_list ... done
+        running test_pickling ... done
+        running test_some_elements ... done
+    """
+
+    def __init__(self, alphabet=('a','b','c','d')):
+        self.alphabet = alphabet
+        Parent.__init__(self, category = FiniteSemigroups())
+
+    def _repr_(self):
+        return "An example of finite semi-group: the left regular band generated by %s"%(self.alphabet,)
+
+    def product(self, x, y):
+        assert x in self
+        assert y in self
+        x = x.value
+        y = y.value
+        return self(x + ''.join(c for c in y if c not in x))
+
+    @cached_method
+    def semigroup_generators(self):
+        return Family([self(i) for i in self.alphabet])
+
+    def an_element(self):
+        return self("acb")
+
+    class Element (ElementWrapper):
+        wrapped_class = str
+
+Example = LRBand
diff --git a/sage/categories/examples/hopf_algebras_with_basis.py b/sage/categories/examples/hopf_algebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/hopf_algebras_with_basis.py
@@ -0,0 +1,50 @@
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.sets.family import Family
+from sage.categories.all import HopfAlgebrasWithBasis
+from sage.combinat.free_module import CombinatorialFreeModule
+from sage.categories.all import tensor
+
+class MyGroupAlgebra(CombinatorialFreeModule):
+    r"""
+    A minimal example of hopf algebra with basis: the group algebra of a group.
+
+    Todo: either merge with the example of AlgebrasWithBasis, or make
+    them really different examples.
+    """
+
+    def __init__(self, R, G):
+        self.group = G
+        CombinatorialFreeModule.__init__(self, R, G, category = HopfAlgebrasWithBasis(R))
+
+    def _repr_(self):
+        return "The Hopf algebra of the %s over %s"%(self.group, self.base_ring())
+    
+    @cached_method
+    def one_basis(self):
+        return self.group.one()
+
+    def product_on_basis(self, g1, g2):
+        return self.basis()[g1 * g2]
+
+    @cached_method
+    def algebra_generators(self):
+        return Family(self.group.gens(), self.term)
+
+    def coproduct_on_basis(self, g):
+        g = self.term(g)
+        return tensor([g, g])
diff --git a/sage/categories/examples/infinite_enumerated_sets.py b/sage/categories/examples/infinite_enumerated_sets.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/infinite_enumerated_sets.py
@@ -0,0 +1,89 @@
+#################################################################    
+#                                                               #
+#                        Examples                               #
+#                                                               #
+#################################################################    
+
+from sage.structure.element import Element
+from sage.structure.parent import Parent
+from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
+from sage.structure.unique_representation import UniqueRepresentation
+from sage.rings.integer import Integer
+#################################################################    
+# Example of an infinite enumerated set    
+class NonNegativeIntegers(UniqueRepresentation, Parent):
+    r"""
+    Example of an enumerated set
+
+    This class shows an example of an infinite enumerated set.
+
+    EXAMPLES::
+        sage: from sage.categories.examples.infinite_enumerated_sets import NonNegativeIntegers
+        sage: NN = NonNegativeIntegers()
+        sage: NN
+        Set of non negative integers
+        sage: NN.cardinality()
+        +Infinity
+        sage: NN.check() 
+        sage: NN.list()
+        Traceback (most recent call last):
+        ...
+        NotImplementedError: infinite list
+        sage: NN.element_class
+        <type 'sage.rings.integer.Integer'>
+        sage: it = iter(NN)
+        sage: [it.next(), it.next(), it.next(), it.next(), it.next()]
+        [0, 1, 2, 3, 4]
+        sage: x = it.next(); type(x)
+        <type 'sage.rings.integer.Integer'>
+        sage: x.parent()
+        Integer Ring
+        sage: x+3
+        8
+        sage: NN(15)
+        15
+
+    To check if the different methods of the enumerated set C return
+    consistent results, on can simpli use::
+        
+        sage: NN.check()
+    """
+    
+    def __init__(self):
+        Parent.__init__(self, category = InfiniteEnumeratedSets())
+
+    def __repr__(self):
+        return "Set of non negative integers"
+        
+    def __contains__(self, elt):
+        return Integer(elt) >= Integer(0)
+        
+    def __iter__(self):
+        i = self._element_constructor_(0)
+        while True:
+            yield self._element_constructor_(i)
+            i += 1
+            ## FIXME : This allows to catch infinite loop during debugging"
+            ## FIXME : remove the following two lines,             
+            if i > 200: 
+                raise ValueError, "Infinite loop during DEBUG! TODO: remove me"
+
+    def __call__(self, elt):
+        if elt in self:
+            return self._element_constructor_(elt)
+            
+    def an_element(self):
+        return self._element_constructor_(42)
+
+    def first(self):
+        return self._element_constructor_(0)
+    
+    def next(self, o):
+        return self._element_constructor_(o+1)
+
+    def _element_constructor_(self, elt):
+        return self.element_class(elt)
+    
+    Element = Integer
+
+
diff --git a/sage/categories/examples/monoids.py b/sage/categories/examples/monoids.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/monoids.py
@@ -0,0 +1,77 @@
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.structure.parent import Parent
+from sage.structure.element import Element
+from sage.structure.unique_representation import UniqueRepresentation
+from sage.structure.element_wrapper import ElementWrapper
+from sage.categories.all import Monoids
+from sage.sets.family import Family
+from semigroups import FreeSemigroup
+
+class FreeMonoid(FreeSemigroup):
+    r"""
+    An example of monoid
+
+    The purpose of this class is to provide a minimal template for
+    implementing of a monoid.
+
+    EXAMPLES::
+
+        sage: S = Monoids().example(); S
+        An example of monoid: the free monoid generated by ('a', 'b', 'c', 'd')
+
+        sage: S.category()
+        Category of monoids
+
+    This is the free semigroup generated by::
+
+        sage: S.semigroup_generators()
+        Family ('a', 'b', 'c', 'd')
+
+        sage: S('dab') * S('acb')
+        'dabacb'
+
+    We conclude by running systematic tests on this monoid::
+
+        sage: S.check(verbose = True)
+        running test_an_element ... done
+        running test_associativity ... done
+        running test_element_pickling ... done
+        running test_one ... done
+        running test_pickling ... done
+        running test_prod ... done
+        running test_some_elements ... done
+    """
+
+    def __init__(self, alphabet=('a','b','c','d')):
+        self.alphabet = alphabet
+        Parent.__init__(self, category = Monoids())
+
+    def _repr_(self):
+        return "An example of monoid: the free monoid generated by %s"%(self.alphabet,)
+
+    @cached_method
+    def one(self):
+        return self("")
+
+    def an_element(self):
+        return self("acbabaca")
+
+    class Element (ElementWrapper):
+        wrapped_class = str
+
+Example = FreeMonoid
diff --git a/sage/categories/examples/semigroups.py b/sage/categories/examples/semigroups.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/semigroups.py
@@ -0,0 +1,205 @@
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.structure.parent import Parent
+from sage.structure.element import Element
+from sage.structure.unique_representation import UniqueRepresentation
+from sage.structure.element_wrapper import ElementWrapper
+from sage.categories.all import Semigroups
+from sage.sets.family import Family
+
+class LeftmostProductSemigroup(UniqueRepresentation, Parent):
+    r"""
+    An example of semigroup
+
+    This class illustrates a minimal implementation of a semigroup.
+
+    EXAMPLES:
+        sage: S = Semigroups().example(); S
+        The leftmost-product semigroup
+
+    This is the semigroup which contains all sort of objects:
+
+        sage: S.some_elements()
+        [3, 42, 'a', 3.3999999999999999, 'raton laveur']
+        
+    with product rule is given by $a \times b = a$ for all $a,b$. 
+
+        sage: S('hello') * S('world')
+        'hello'
+
+        sage: S(3)*S(1)*S(2)
+        3
+
+        sage: S(3)^12312321312321
+        3
+
+        sage: S.check(verbose = True)
+        running test_an_element ... done
+        running test_associativity ... done
+        running test_element_pickling ... done
+        running test_pickling ... done
+        running test_some_elements ... done
+    """
+    
+    def __init__(self):
+        Parent.__init__(self, category = Semigroups())
+
+    def _repr_(self):
+        return "The leftmost-product semigroup"
+
+    def product(self, x, y):
+        assert x in self
+        assert y in self
+        return x
+
+    def an_element(self):
+        return self(42)
+
+    def some_elements(self):
+        return [self(i) for i in [3, 42, "a", 3.4, "raton laveur"]]
+
+    class Element(ElementWrapper):
+        def is_idempotent(self):
+            """
+            Trivial implementation of ``Semigroups.Element.is_idempotent``
+            
+            All elements of this monoid are idempotent!
+            """
+            return True
+
+
+class FreeSemigroup(UniqueRepresentation, Parent):
+    r"""
+    An example of semigroup
+
+    The purpose of this class is to provide a minimal template for
+    implementing of a semigroup.
+
+    EXAMPLES:
+        sage: S=Semigroups().example("free"); S
+        An example of semigroup: the free semigroup generated by ('a', 'b', 'c', 'd')
+
+    This is the free semi group generated by::
+
+        sage: S.semigroup_generators()
+        Family ('a', 'b', 'c', 'd')
+
+        sage: S('dab') * S('acb')
+        'dabacb'
+
+    We conclude by running systematic tests on this semigroup::
+
+        sage: S.check(verbose = True)
+        running test_an_element ... done
+        running test_associativity ... done
+        running test_element_pickling ... done
+        running test_pickling ... done
+        running test_some_elements ... done
+    """
+
+    def __init__(self, alphabet=('a','b','c','d')):
+        self.alphabet = alphabet
+        Parent.__init__(self, category = Semigroups())
+
+    def _repr_(self):
+        return "An example of semigroup: the free semigroup generated by %s"%(self.alphabet,)
+
+    def product(self, x, y):
+        assert x in self
+        assert y in self
+        return self(x.value + y.value)
+
+    @cached_method
+    def semigroup_generators(self):
+        return Family([self(i) for i in self.alphabet])
+
+    def an_element(self):
+        return self("acbabaca")
+
+    class Element (ElementWrapper):
+        wrapped_class = str
+    
+
+
+class SubQuotientOfLeftmostProductSemigroup(UniqueRepresentation, Parent):
+    r"""
+    Example of a sub-quotient semigroup
+
+    EXAMPLES::
+
+        sage: S = Semigroups().SubQuotients().example(); S
+        A subquotient of The leftmost-product semigroup
+
+    This is the quotient of::    
+
+        sage: S.ambient()
+        The leftmost-product semigroup
+
+    by setting `x=42` for any `x\geq 42`::
+
+        sage: S(100)
+        42
+        sage: S(100) == S(42)
+        True
+
+        sage: S(1)*S(2) == S(1)
+        True
+
+    TESTS::
+
+        sage: S.check(verbose = True)
+        running test_an_element ... done
+        running test_associativity ... done
+        running test_element_pickling ... done
+        running test_pickling ... done
+        running test_some_elements ... done
+
+    """
+    def _element_constructor_(self, x):
+        return self.retract(self.ambient()(x))
+
+    def __init__(self):
+         Parent.__init__(self, category = Semigroups().SubQuotients())
+
+    def ambient(self):
+        return Semigroups().example()
+        
+    def lift(self, x):
+        assert x in self
+        return x.value
+
+    def the_answer(self):
+        return self.retract(self.ambient()(42))
+
+    def an_element(self):
+        return self.the_answer()
+
+    def some_elements(self):
+        return (self.retract(self.ambient()(i))
+                for i in [1, 2, 3, 8, 42, 100])
+        
+    def retract(self, x):
+        from sage.rings.integer_ring import ZZ
+        assert x in self.ambient() and x.value in ZZ
+        if x.value > 42:
+            return self.the_answer()
+        else:
+            return self.element_class(x, parent = self)
+
+    class Element(ElementWrapper):
+        pass
+        
diff --git a/sage/categories/examples/semigroups_cython.pyx b/sage/categories/examples/semigroups_cython.pyx
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/semigroups_cython.pyx
@@ -0,0 +1,139 @@
+from sage.structure.parent import Parent
+from sage.structure.element cimport Element
+from sage.categories.all import Category, Semigroups
+from sage.misc.cachefunc import cached_method
+from sage.categories.examples.semigroups import LeftmostProductSemigroup as LeftmostProductSemigroupPython
+
+class DummyClass:
+    def method(self):
+        pass
+
+cdef class DummyCClass:
+    def method(self):
+        pass
+
+    cpdef cpmethod(self):
+        pass
+
+instancemethod     = type(DummyClass.method)
+method_descriptor  = type(DummyCClass.method)
+
+cdef class IdempotentSemigroupsElement(Element):
+    def _pow_(self, i):
+        assert i > 0
+        return self
+
+    cpdef is_idempotent_cpdef(self):
+        return True
+
+class IdempotentSemigroups(Category):
+    @cached_method
+    def super_categories(self):
+        return [Semigroups()]
+
+    ElementMethods = IdempotentSemigroupsElement
+
+
+cdef class LeftmostProductSemigroupElement(Element):
+    cdef object _value
+
+    def __init__(self, value, parent):
+        Element.__init__(self, parent = parent)
+        self._value = value
+
+    def _repr_(self):
+        return repr(self._value)
+
+    def __reduce__(self):
+        return LeftmostProductSemigroupElement, (self._value, self._parent)
+
+    def __cmp__(LeftmostProductSemigroupElement self, LeftmostProductSemigroupElement other):
+        return cmp(self._value, other._value)
+    
+    def __getattr__(self, name):
+        result = getattr(self.parent().category().element_class, name)
+        if isinstance(result, instancemethod):
+            return instancemethod(result.im_func, self, self.__class__)
+        elif isinstance(result,  method_descriptor):
+            return result # should bind the method descriptor to appropriate object
+        else:
+            return result
+
+    # Apparently, python looks for __mul__, __pow__, ... in the
+    # class of self rather than in self itself. No big deal, since
+    # those will usually be defined in a cython super class of
+    # this class
+    def __mul__(self, other):
+        return self._mul_(other)
+
+    cpdef _mul_(self, other):
+        return self.parent().product(self, other)
+
+    def __pow__(self, i, dummy):
+        return self._pow_(i)
+
+class LeftmostProductSemigroup(LeftmostProductSemigroupPython):
+    r"""
+    An example of semigroup
+
+    This class illustrates a minimal implementation of a semi-group
+    where the element class is an extension type, and still gets code
+    from the category. Also, the category itself includes some cython
+    methods.
+
+    This is purely a proof of concept. The code obviously needs refactorisation!
+
+    Comments:
+    - nested classes seem not to be currently supported by cython
+    - one cannot play ugly use class surgery tricks (as with _mul_parent)
+      available operations should really be declared to the coercion model!
+
+    EXAMPLES:
+        sage: from sage.categories.examples.semigroups_cython import LeftmostProductSemigroup
+        sage: S = LeftmostProductSemigroup(); S
+        The leftmost-product semigroup
+
+    This is the semigroup which contains all sort of objects:
+
+        sage: S.some_elements()
+        [3, 42, 'a', 3.3999999999999999, 'raton laveur']
+        
+    with product rule is given by $a \times b = a$ for all $a,b$. 
+
+        sage: S('hello') * S('world')
+        'hello'
+
+        sage: S(3)*S(1)*S(2)
+        3
+
+        sage: S(3)^12312321312321         # todo: not implemented (see below)   
+        3
+
+        sage: S.check(verbose = True)
+        running test_an_element ... done
+        running test_associativity ... done
+        running test_element_pickling ... done
+        running test_pickling ... done
+        running test_some_elements ... done
+
+        # That's really the only method which is obtained from the category ...
+        sage: S(42).is_idempotent
+        <bound method LeftmostProductSemigroupElement.is_idempotent of 42>
+        sage: S(42).is_idempotent()
+        True
+
+        sage: S(42)._pow_                 # how to bind it?
+        <method '_pow_' of 'sage.categories.examples.semigroups_cython.IdempotentSemigroupsElement' objects>
+        sage: S(42)^10                    # todo: not implemented
+        42
+
+        sage: S(42).is_idempotent_cpdef   # how to bind it?
+        <method 'is_idempotent_cpdef' of 'sage.categories.examples.semigroups_cython.IdempotentSemigroupsElement' objects>
+        sage: S(42).is_idempotent_cpdef() # todo: not implemented
+        True
+    """
+    
+    def __init__(self):
+        Parent.__init__(self, category = IdempotentSemigroups())
+
+    Element = LeftmostProductSemigroupElement
diff --git a/sage/categories/examples/sets_cat.py b/sage/categories/examples/sets_cat.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/examples/sets_cat.py
@@ -0,0 +1,185 @@
+from sage.structure.parent import Parent
+from sage.categories.sets_cat import Sets
+from sage.rings.integer import Integer, IntegerWrapper
+from sage.rings.integer_ring import IntegerRing
+from sage.rings.arith import is_prime 
+from sage.structure.unique_representation import UniqueRepresentation
+
+
+class PrimeNumbers(UniqueRepresentation, Parent):
+    """
+    An example of parent in the category sets: the set of prime numbers.  
+
+    EXAMPLES::
+            
+        sage: P = Sets().example(facade=False)
+        sage: P(12)
+        Traceback (most recent call last):
+        ...
+        AssertionError: 12 is not a prime number
+        sage: a = P.an_element()
+        sage: a.parent()
+        Set of prime numbers
+        sage: x = P(13); x
+        13
+        sage: x.is_prime()
+        True
+        sage: type(x)
+        <class 'sage.categories.examples.sets_cat.PrimeNumbers_with_category.element_class'>
+        sage: x.parent()
+        Set of prime numbers
+        sage: P(13) in P
+        True
+        sage: y = x+1; y
+        14
+        sage: type(y)
+        <type 'sage.rings.integer.Integer'>
+        sage: y.parent()
+        Integer Ring
+        sage: type(P(13)+P(17))
+        <type 'sage.rings.integer.Integer'>    
+        sage: type(P(2)+P(3))
+        <type 'sage.rings.integer.Integer'>    
+
+        sage: P.check(verbose=True)
+        running test_an_element ... done
+        running test_element_pickling ... done
+        running test_pickling ... done
+        running test_some_elements ... done
+    """
+
+    def __init__(self):
+        """
+        TESTS::
+
+            sage: P = Sets().example(facade=False)
+            sage: type(P(13)+P(17))
+            <type 'sage.rings.integer.Integer'>    
+            sage: type(P(2)+P(3))
+            <type 'sage.rings.integer.Integer'>    
+        """
+        Parent.__init__(self, category = Sets())
+        self._populate_coercion_lists_(embedding=IntegerRing())
+
+    def _repr_(self):
+        """
+        TESTS::
+
+            sage: P = Sets().example(facade=False); P
+            Set of prime numbers
+        """
+        return "Set of prime numbers"
+    
+    def an_element(self):
+        """
+        TESTS::
+
+            sage: P = Sets().example(facade=False)
+            sage: x = P.an_element(); x
+            47
+            sage: x.parent()
+            Set of prime numbers            
+        """
+        return self(47)
+
+    def __contains__(self, p):
+        """
+        TESTS::
+        
+            sage: P = Sets().example(facade=False)
+            sage: 13 in P, P(13) in P
+            (False, True)
+            sage: 12 in P
+            False
+        """
+        return p.parent() is self
+
+    class Element(IntegerWrapper):
+        def __init__(self, p, parent):
+            """
+            TESTS::
+
+                sage: P = Sets().example(facade=False)
+                sage: P(12)
+                Traceback (most recent call last):
+                ...
+                AssertionError: 12 is not a prime number
+                sage: x = P(13); type(x)
+                <class 'sage.categories.examples.sets_cat.PrimeNumbers_with_category.element_class'>
+                sage: x.parent() is P
+                True
+            """    
+            assert is_prime(p), "%s is not a prime number"%(p)
+            IntegerWrapper.__init__(self, p, parent=parent)
+            
+        def is_prime(self):
+            """
+            TESTS::
+
+                sage: P = Sets().example(facade=False)
+                sage: P.an_element().is_prime()
+                True
+            """
+            return True
+
+class PrimeNumbers_Facade(UniqueRepresentation, Parent):
+    """
+    EXAMPLES::
+    
+        sage: P = Sets().example(facade=True)
+        sage: P(12)
+        Traceback (most recent call last):
+        ...
+        AssertionError: 12 is not a prime number
+        sage: a = P.an_element()
+        sage: a.parent()
+        Integer Ring
+        sage: x = P(13); x
+        13
+        sage: type(x)
+        <type 'sage.rings.integer.Integer'>
+        sage: x.parent()
+        Integer Ring
+        sage: 13 in P
+        True
+        sage: 12 in P
+        False
+        sage: y = x+1; y
+        14
+        sage: type(y)
+        <type 'sage.rings.integer.Integer'>
+
+        sage: P.check(verbose=True)
+        running test_an_element ... done
+        running test_element_pickling ... done
+        running test_pickling ... done
+        running test_some_elements ... done
+    """
+    def __init__(self):
+        Parent.__init__(self, category = Sets())
+
+    def _repr_(self):
+        return "Set of prime numbers (facade implementation)"
+    
+    def an_element(self):
+        return self(47) # if speed is needed, call: self.element_class(47) 
+
+    def __contains__(self, p):
+        """
+        TESTS::
+        
+            sage: P = Sets().example(facade=True)
+            sage: 13 in P
+            True
+            sage: 12 in P
+            False
+        """
+        return isinstance(p, Integer) and p.is_prime()
+
+    def _element_constructor_(self, e):
+        p = self.element_class(e)
+        assert is_prime(p), "%s is not a prime number"%(p)
+        return p
+    
+    element_class = Integer
+    
diff --git a/sage/categories/fields.py b/sage/categories/fields.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/fields.py
@@ -0,0 +1,75 @@
+r"""
+Fields
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class Fields(Category):
+    """
+    The category of fields
+    commutative fields, i.e. commutative rings where all non-zero elements have 
+    multiplicative inverses
+
+    EXAMPLES:
+        sage: K = Fields()
+        sage: K
+        Category of fields
+        sage: Fields().super_categories()
+        [Category of euclidean domains, Category of unique factorization domains, Category of division rings]
+
+        sage: K(IntegerRing())
+        Rational Field
+        sage: K(PolynomialRing(GF(3), 'x'))
+        Fraction Field of Univariate Polynomial Ring in x over
+        Finite Field of size 3
+        sage: K(RealField())
+        Real Field with 53 bits of precision
+
+    TESTS:
+        sage: C = Fields()
+        sage: loads(C.dumps()) == C
+        True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        from sage.categories.basic import EuclideanDomains, UniqueFactorizationDomains, DivisionRings
+        return [EuclideanDomains(), UniqueFactorizationDomains(), DivisionRings()]
+
+    # for backward compatibility
+    def __contains__(self, x):
+        from sage.rings.field import is_Field
+        return is_Field(x)
+
+    def __call__(self, x):
+        if x in self:
+            return x
+        try:
+            return x.fraction_field()
+        except AttributeError:
+            raise TypeError, "unable to associate a field to %s"%x
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/finite_dimensional_algebras_with_basis.py b/sage/categories/finite_dimensional_algebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_dimensional_algebras_with_basis.py
@@ -0,0 +1,91 @@
+r"""
+FiniteDimensionalAlgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import FiniteDimensionalModulesWithBasis, AlgebrasWithBasis
+from sage.misc.cachefunc import cached_method
+
+class FiniteDimensionalAlgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of finite dimensional algebras with a distinguished basis
+
+    EXAMPLES:
+      sage: FiniteDimensionalAlgebrasWithBasis(QQ)
+      Category of finite dimensional algebras with basis over Rational Field
+      sage: FiniteDimensionalAlgebrasWithBasis(QQ).super_categories()
+      [Category of finite dimensional modules with basis over Rational Field, Category of algebras with basis over Rational Field]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [FiniteDimensionalModulesWithBasis(R), AlgebrasWithBasis(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+      def on_left_matrix(self, new_BR = None):
+        """
+        Returns the matrix of the action of self on the algebra my
+        multiplication on the left
+
+        If new_BR is specified, then the matrix will be over new_BR.
+
+        TODO: split into to parts
+         - build the endomorphism of multiplication on the left
+         - build the matrix of an endomorphism
+
+        EXAMPLES:
+            sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
+            sage: a = QS3([2,1,3])
+            sage: a._matrix_()
+            [0 0 1 0 0 0]
+            [0 0 0 0 1 0]
+            [1 0 0 0 0 0]
+            [0 0 0 0 0 1]
+            [0 1 0 0 0 0]
+            [0 0 0 1 0 0]
+            sage: a._matrix_(RDF)
+            [0.0 0.0 1.0 0.0 0.0 0.0]
+            [0.0 0.0 0.0 0.0 1.0 0.0]
+            [1.0 0.0 0.0 0.0 0.0 0.0]
+            [0.0 0.0 0.0 0.0 0.0 1.0]
+            [0.0 1.0 0.0 0.0 0.0 0.0]
+            [0.0 0.0 0.0 1.0 0.0 0.0]
+  
+        """
+        parent = self.parent()
+        
+        if parent.get_order() is None:
+            cc = parent._combinatorial_class
+        else:
+            cc = parent.get_order()
+            
+        BR = parent.base_ring()
+        if new_BR is None:
+            new_BR = BR
+
+        from sage.matrix.all import MatrixSpace
+        MS = MatrixSpace(new_BR, parent.dimension(), parent.dimension())
+        l = [ (self*parent(m)).to_vector() for m in cc ]
+        return MS(l).transpose()
+
+      _matrix_ = on_left_matrix  # For temporary backward compatibility
+      to_matrix = on_left_matrix
diff --git a/sage/categories/finite_dimensional_bialgebras_with_basis.py b/sage/categories/finite_dimensional_bialgebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_dimensional_bialgebras_with_basis.py
@@ -0,0 +1,45 @@
+r"""
+FiniteDimensionalBialgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import FiniteDimensionalAlgebrasWithBasis, FiniteDimensionalCoalgebrasWithBasis, Bialgebras
+from sage.misc.cachefunc import cached_method
+
+class FiniteDimensionalBialgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of finite dimensional bialgebras with a distinguished basis
+
+    EXAMPLES::
+
+        sage: FiniteDimensionalBialgebrasWithBasis(QQ)
+        Category of finite dimensional bialgebras with basis over Rational Field
+        sage: FiniteDimensionalBialgebrasWithBasis(QQ).super_categories()
+        [Category of finite dimensional algebras with basis over Rational Field, Category of finite dimensional coalgebras with basis over Rational Field, Category of bialgebras over Rational Field]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [FiniteDimensionalAlgebrasWithBasis(R), FiniteDimensionalCoalgebrasWithBasis(R), Bialgebras(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/finite_dimensional_coalgebras_with_basis.py b/sage/categories/finite_dimensional_coalgebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_dimensional_coalgebras_with_basis.py
@@ -0,0 +1,44 @@
+r"""
+FiniteDimensionalCoalgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import FiniteDimensionalModulesWithBasis, CoalgebrasWithBasis
+from sage.misc.cachefunc import cached_method
+
+class FiniteDimensionalCoalgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of finite dimensional coalgebras with a distinguished basis
+
+    EXAMPLES:
+      sage: FiniteDimensionalCoalgebrasWithBasis(QQ)
+      Category of finite dimensional coalgebras with basis over Rational Field
+      sage: FiniteDimensionalCoalgebrasWithBasis(QQ).super_categories()
+      [Category of finite dimensional modules with basis over Rational Field, Category of coalgebras with basis over Rational Field]
+    
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [FiniteDimensionalModulesWithBasis(R), CoalgebrasWithBasis(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/finite_dimensional_hopf_algebras_with_basis.py b/sage/categories/finite_dimensional_hopf_algebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_dimensional_hopf_algebras_with_basis.py
@@ -0,0 +1,45 @@
+r"""
+FiniteDimensionalHopfAlgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import FiniteDimensionalBialgebrasWithBasis, HopfAlgebrasWithBasis
+from sage.misc.cachefunc import cached_method
+
+class FiniteDimensionalHopfAlgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of finite dimensional Hopf algebras with a distinguished basis
+
+    EXAMPLES::
+
+        sage: FiniteDimensionalHopfAlgebrasWithBasis(QQ) # fixme: Hopf should be capitalized
+        Category of finite dimensional hopf algebras with basis over Rational Field
+        sage: FiniteDimensionalHopfAlgebrasWithBasis(QQ).super_categories()
+        [Category of finite dimensional bialgebras with basis over Rational Field, Category of hopf algebras with basis over Rational Field]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [FiniteDimensionalBialgebrasWithBasis(R), HopfAlgebrasWithBasis(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/finite_dimensional_modules_with_basis.py b/sage/categories/finite_dimensional_modules_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_dimensional_modules_with_basis.py
@@ -0,0 +1,44 @@
+r"""
+FiniteDimensionalModulesWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import ModulesWithBasis
+from sage.misc.cachefunc import cached_method
+
+class FiniteDimensionalModulesWithBasis(Category_over_base_ring):
+    """
+    The category of finite dimensional modules with a distinguished basis
+
+    EXAMPLES:
+      sage: FiniteDimensionalModulesWithBasis(QQ)
+      Category of finite dimensional modules with basis over Rational Field
+      sage: FiniteDimensionalModulesWithBasis(QQ).super_categories()
+      [Category of modules with basis over Rational Field]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [ModulesWithBasis(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/finite_enumerated_sets.py b/sage/categories/finite_enumerated_sets.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_enumerated_sets.py
@@ -0,0 +1,202 @@
+r"""
+Finite Enumerated Sets
+"""
+#*****************************************************************************
+#  Copyright (C) 2009 Florent Hivert <Florent.Hivert@univ-rouen.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+
+from category_types import Category
+from sage.categories.enumerated_sets import EnumeratedSets
+from sage.rings.integer import Integer
+from sage.misc.cachefunc import cached_method
+
+class FiniteEnumeratedSets(Category):
+    """
+    The category of finite enumerated sets
+
+    EXAMPLES::
+    
+        sage: FiniteEnumeratedSets()
+        Category of finite enumerated sets
+        sage: FiniteEnumeratedSets().super_categories()
+        [Category of enumerated sets]
+        sage: FiniteEnumeratedSets().all_super_categories()
+        [Category of finite enumerated sets,
+         Category of enumerated sets,
+         Category of sets,
+         Category of objects]
+
+    TESTS::
+    
+        sage: C = FiniteEnumeratedSets()
+        sage: loads(C.dumps()) == C
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [EnumeratedSets()]
+
+    pass
+
+    def example(self):
+        """
+        A simple example of a finite enumerated set.
+
+        EXAMPLES::
+
+            sage: FiniteEnumeratedSets().example()
+            example of finite enumerated set
+        """
+        from sage.categories.examples.finite_enumerated_sets import Example
+        return Example()
+
+    class ParentMethods:
+        """
+        Parent class for the finite enumerated set category 
+        """
+
+        def _cardinality_from_iterator(self):
+            """
+            The cardinality of ``self``.
+
+            ``self.cardinality()`` returns the cardinality of the set ``self``
+            as a sage ``Integer`` or as ``+Infinity``.
+            
+            This if the default implementation from the category
+            ``FiniteEnumeratedSet()`` it just goes through the iterator of the
+            set to count the number of objects.
+            
+            EXAMPLES::
+        
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.cardinality() # indirect doctest
+                3
+            """
+            c = Integer(0)
+            one = Integer(1)
+            for _ in self:
+                c += one
+            return c
+        #Set cardinality to the default implementation
+        cardinality = _cardinality_from_iterator
+
+        
+        def _list_from_iterator(self):
+            """
+            The list of elements ``self``.
+
+            ``self.list()`` returns the list of the element of the set
+            ``self``. This is the default implementation the category
+            ``EnumeratedSet()`` which builds the list from the iterator.
+        
+            EXAMPLES::
+        
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.list() # indirect doctest
+                [1, 2, 3]
+            """
+            return [x for x in self]
+        #Set list to the default implementation
+        _list_default = _list_from_iterator # needed by the check mechanism. 
+        list  = _list_default
+
+
+        def _random_element_from_unrank(self):
+            """
+            A random element in ``self``.
+        
+            ``self.random_element()`` returns a random element in ``self``
+            with uniform probability. This is a generic implementation from
+            the category ``EnumeratedSet()`` which can be used when the method
+            ``unrank`` is provided.
+
+            EXAMPLES::
+        
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.random_element()
+                1
+                """
+            from sage.misc.prandom import randint
+            c = self.cardinality()
+            r = randint(0, c-1)
+            return self.unrank(r)
+        #Set the default implementation of random
+        random_element = _random_element_from_unrank
+
+        @cached_method
+        def _last_from_iterator(self):
+            """
+            The last element of ``self``.
+
+            ``self.last()`` returns the last element of ``self`` This is a
+            generic implementation from the category ``FiniteEnumeratedSet()``
+            which can be used when the method ``__iter__`` is provided.
+
+            EXAMPLES::
+        
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.last()
+                3
+            """
+            for i in self:
+                pass
+            return i
+        last = _last_from_iterator
+
+        def _last_from_unrank(self):
+            """
+            The last element of ``self``.
+
+            ``self.last()`` returns the last element of ``self`` This is a
+            generic implementation from the category ``FiniteEnumeratedSet()``
+            which can be used when the method ``unrank`` is provided.
+
+            EXAMPLES::
+        
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C._last_from_unrank()
+                3
+            """
+            return self.unrank(self.cardinality() -1)
+        
+        def test_enumerated_set_iter_cardinality(self, **options):
+            tester = self.tester(**options)
+            """
+            Check the coherency between methods ``cardinality`` and
+            ``__iter__``.  Automagically called by ``check()``
+
+            EXAMPLES::
+            
+                sage: C = FiniteEnumeratedSets().example()
+                sage: C.test_enumerated_set_iter_cardinality()
+
+            Let's now break the class::
+
+                sage: from sage.categories.examples.finite_enumerated_sets import Example
+                sage: class CCls(Example):
+                ...       def cardinality(self):
+                ...           return 4
+                sage: CC = CCls()
+                sage: CC.check()
+                Traceback (most recent call last):
+                ...
+                AssertionError: 4 != 3
+            """
+            if self.cardinality != self._cardinality_from_iterator:
+                tester.assertEqual(self.cardinality(),
+                                   self._cardinality_from_iterator())
+
+
diff --git a/sage/categories/finite_fields.py b/sage/categories/finite_fields.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_fields.py
@@ -0,0 +1,69 @@
+r"""
+Fields
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.categories.category import Category
+from sage.categories.all import Fields
+from sage.rings.field import is_Field
+
+class FiniteFields(Category):
+    """
+    The category of finite fields
+
+    EXAMPLES:
+    EXAMPLES:
+        sage: K = FiniteFields()
+        sage: K
+        Category of finite fields
+        sage: FiniteField(17) in K
+        True
+        sage: RationalField() in K
+        False
+        sage: K(RationalField())
+        Traceback (most recent call last):
+        ...
+        TypeError: unable to canonically associate a finite field to Rational Field
+
+    TESTS:
+        sage: C = FiniteFields()
+        sage: loads(C.dumps()) == C
+        True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [Fields()]
+
+    def __contains__(self, x):
+        return is_Field(x) and x.is_finite()
+
+    def __call__(self, x):
+        if x in self:
+            return x
+        raise TypeError, "unable to canonically associate a finite field to %s"%x
+        # TODO: local dvr ring?
+
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/finite_monoids.py b/sage/categories/finite_monoids.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_monoids.py
@@ -0,0 +1,68 @@
+r"""
+Monoids
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.misc.all import attrcall
+from sage.categories.category import Category, HomCategory
+from sage.categories.category import Category
+from sage.categories.finite_semigroups import FiniteSemigroups
+from sage.categories.monoids import Monoids
+
+
+class FiniteMonoids(Category):
+    """
+    The category of finite monoids
+
+    EXAMPLES::
+
+        sage: FiniteMonoids()
+        Category of finite monoids
+        sage: FiniteMonoids().super_categories()
+        [Category of finite semigroups, Category of monoids]
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [FiniteSemigroups(), Monoids()]
+
+
+    class ElementMethods:
+        def pseudo_order(self):
+            r"""
+            Returns the pair [k, j] with k minimal and $0\leq j <k$ such
+            that self^k = self^j.
+
+            Note that j is uniquely determined.
+
+            TODO: more appropriate name?
+            """
+            self_powers = {self.parent().one(): 0}
+            k = 1
+            self_power_k = self
+            while not self_power_k in self_powers:
+                self_powers[self_power_k] = k
+                k += 1
+                self_power_k = self_power_k * self
+            return [k, self_powers[self_power_k]] 
+            
+
+    class HomCategory(HomCategory):
+        """
+        The category of monoid morphisms
+        """
+        pass
diff --git a/sage/categories/finite_semigroups.py b/sage/categories/finite_semigroups.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/finite_semigroups.py
@@ -0,0 +1,215 @@
+r"""
+Semigroups
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Florent Hivert <florent.hivert at univ-rouen.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.semigroups import Semigroups
+from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
+from sage.structure.unique_representation import UniqueRepresentation
+from sage.structure.parent import Parent
+from sage.structure.element import Element, generic_power
+from sage.structure.element_wrapper import ElementWrapper
+from sage.misc.cachefunc import cached_method
+
+class FiniteSemigroups(Category):
+    """
+    The category of (multiplicative) finite semigroups,
+    i.e. enumerated sets with an associative operation *.
+
+    EXAMPLES::
+
+        sage: FiniteSemigroups()
+        Category of finite semigroups
+        sage: FiniteSemigroups().super_categories()
+        [Category of semigroups, Category of finite enumerated sets]
+        sage: FiniteSemigroups().all_super_categories()
+        [Category of finite semigroups,
+         Category of semigroups,
+         Category of finite enumerated sets,
+         Category of enumerated sets,
+         Category of sets,
+         Category of objects]
+        sage: FiniteSemigroups().example()
+        An example of finite semi-group: the left regular band generated by ('a', 'b', 'c', 'd')
+
+    TESTS::
+
+        sage: C = Semigroups()
+        sage: loads(C.dumps()) == C
+        True
+    """
+    @cached_method
+    def super_categories(self):
+        return [Semigroups(), FiniteEnumeratedSets()]
+
+    class ParentMethods:
+        def some_elements(self):
+            return self
+        
+        def idempotents(self):
+            return [x for x in self if x.is_idempotent()]
+
+        def succ_generators(self, side = "both"):
+            r"""
+            INPUT:
+             - ``side``: "left", "right", or "both"
+            
+            Returns the the successor function of the left
+            (resp. right, resp. two sided) Cayley graph of self.
+
+            This is a function which maps an element of self to all
+            the products of x by a generator of this semigroup, on the
+            left (resp. the right, resp. on both sides).
+
+            FIXME: find a better name for this method and for both
+            FIXME: should we return a set? a family?
+            
+            EXAMPLES:
+                sage: S = FiniteSemigroups().example()
+                sage: S.succ_generators("left" )(S('ca'))
+                ('ac', 'bca', 'ca', 'dca')
+                sage: S.succ_generators("right")(S('ca'))
+                ('ca', 'cab', 'ca', 'cad')
+                sage: S.succ_generators("both" )(S('ca'))
+                ('ac', 'bca', 'ca', 'dca', 'ca', 'cab', 'ca', 'cad')
+            """
+            left  = (side == "left"  or side == "both")
+            right = (side == "right" or side == "both")
+            generators = self.semigroup_generators()
+            return lambda x: (tuple(g * x for g in generators) if left  else ()) + (tuple(x * g for g in generators) if right else ())
+            
+        def __iter__(self):
+            """
+            Returns an iterator over self
+            """
+            from sage.combinat.backtrack import TransitiveIdeal
+            return TransitiveIdeal(self.succ_generators(side = "right"), self.semigroup_generators()).__iter__()
+
+        def ideal(self, gens, side = "both"):
+            """
+            INPUT:
+             - gens: a list (or iterable)
+             - side: "left", "right" or "both"; defaults to "both"
+            
+            Returns the left (resp. right, resp. two sided) ideal generated by gens
+
+            EXAMPLES::
+
+                sage: S = FiniteSemigroups().example()
+                sage: list(S.ideal([S('cab')], side = "left" ))
+                ['cab', 'dcab', 'adcb', 'acb', 'bdca', 'bca', 'abdc',
+                'cadb', 'acdb', 'bacd', 'abcd', 'cbad', 'abc', 'acbd',
+                'dbac', 'dabc', 'cbda', 'bcad', 'cabd', 'dcba',
+                'bdac', 'cba', 'badc', 'bac', 'cdab', 'dacb', 'dbca',
+                'cdba', 'adbc', 'bcda']
+                sage: list(S.ideal([S('cab')], side = "right"))
+                ['cab', 'cabd']
+                sage: list(S.ideal([S('cab')], side = "both" ))
+                ['cab', 'dcab', 'acb', 'adcb', 'acbd', 'bdca', 'bca', 'cabd', 'abdc', 'cadb', 'acdb', 'bacd', 'abcd', 'cbad', 'abc', 'dbac', 'dabc', 'cbda', 'bcad', 'dcba', 'bdac', 'cba', 'cdab', 'bac', 'badc', 'dacb', 'dbca', 'cdba', 'adbc', 'bcda']
+                sage: list(S.ideal([S('cab')]                ))
+                ['cab', 'dcab', 'acb', 'adcb', 'acbd', 'bdca', 'bca', 'cabd', 'abdc', 'cadb', 'acdb', 'bacd', 'abcd', 'cbad', 'abc', 'dbac', 'dabc', 'cbda', 'bcad', 'dcba', 'bdac', 'cba', 'cdab', 'bac', 'badc', 'dacb', 'dbca', 'cdba', 'adbc', 'bcda']
+
+            """
+            from sage.combinat.backtrack import TransitiveIdeal
+            return TransitiveIdeal(self.succ_generators(side = side), gens)
+            
+        def cayley_graph(self, side = "both", simple = False):
+            """
+
+            EXAMPLES::
+
+                sage: S = FiniteSemigroups().example(('a','b'))
+                sage: g = S.cayley_graph(side="right", simple=True)
+                sage: g.vertices()
+                ['a', 'ab', 'b', 'ba']
+                sage: g.edges()
+                [('a', 'ab', None), ('b', 'ba', None)]
+
+                sage: g = S.cayley_graph(side="left", simple=True)
+                sage: g.vertices()
+                ['a', 'ab', 'b', 'ba']
+                sage: g.edges()
+                [('a', 'ba', None), ('ab', 'ba', None), ('b', 'ab', None), ('ba', 'ab', None)]
+
+                sage: g = S.cayley_graph(side="both", simple=True)
+                sage: g.vertices()
+                ['a', 'ab', 'b', 'ba']
+                sage: g.edges()
+                [('a', 'ab', None), ('a', 'ba', None), ('ab', 'ba', None), ('b', 'ab', None), ('b', 'ba', None), ('ba', 'ab', None)]
+
+            TODO: add an option to specify a subset of module generators and module operators, and a predicate to stop the iteration
+            """
+            from sage.graphs.graph import DiGraph
+            if simple:
+                result = DiGraph()
+            else:
+                result = DiGraph(multiedges = True, loops = True)
+            result.add_vertices([x for x in self])
+            generators = self.semigroup_generators()
+            left  = (side == "left"  or side == "both")
+            right = (side == "right" or side == "both")
+            def edge(source, target, label):
+                if simple:
+                    return [source, target]
+                else:
+                    return [source, target, label]
+            for x in self:
+                for i in generators.keys():
+                    if left:
+                        result.add_edge(edge(x, generators[i]*x, (i, "left" )))
+                    if right:
+                        result.add_edge(edge(x, x*generators[i], (i, "right")))
+            return result
+
+        def twosided_ideal_graph(self, simple = False):
+            raise NotImplementedError("Please use self.cayley_graph(...)")
+
+        @cached_method
+        def j_classes(self):
+            r"""
+            Two elements $u$ and $v$ of a monoid are in the same j-class if
+            u divides v and v divides u.
+            
+            This method returns all the j-classes of self, as a list of lists
+            """
+            return self.cayley_graph(side="both", simple=True).strongly_connected_components()
+
+        @cached_method
+        def j_classes_of_idempotents(self):
+            r"""
+            Returns all idempotents of self, grouped by j-class, as a list of lists
+            """
+            return filter(lambda l: len(l) > 0,
+                          map(lambda cl: filter(attrcall('is_idempotent'), cl),
+                              self.j_classes()))
+
+        @cached_method
+        def j_transversal_of_idempotents(self):
+            r"""
+            Returns a list of one idempotent per regular j-class
+            """
+            def first_idempotent(l):
+                for x in l:
+                    if x.is_idempotent():
+                        return x
+                return None
+            return filter(lambda x: not x is None,
+                          map(first_idempotent, self.j_classes()))
+
+        # TODO: compute eJe, where J is the J-class of e
+        # TODO: construct the action of self on it, as a permutation group
diff --git a/sage/categories/g_sets.py b/sage/categories/g_sets.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/g_sets.py
@@ -0,0 +1,56 @@
+r"""
+G-Sets
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+#############################################################
+# GSets
+#     $G$-Sets play an important role in permutation groups.
+#############################################################
+class GSets(Category):
+    """
+    The category of $G$-sets, for a group $G$.
+
+    EXAMPLES:
+        sage: S = SymmetricGroup(3)
+        sage: GSets(S)
+        Category of G-sets for SymmetricGroup(3)
+
+    TESTS:
+        sage: S8 = SymmetricGroup(8)
+        sage: C = GSets(S8)
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, G):
+        Category.__init__(self, "G-sets")
+        self.__G = G
+
+    def __repr__(self):
+        return "Category of G-sets for %s"%self.__G
+
+    def construction(self):
+        return (self.__class__, self.__G)
+
+    @cached_method
+    def super_categories(self):
+        from sets_cat import Sets
+        return [Sets()]
diff --git a/sage/categories/gcd_domains.py b/sage/categories/gcd_domains.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/gcd_domains.py
@@ -0,0 +1,47 @@
+r"""
+GdcDomains
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class GcdDomains(Category):
+    """
+    The category of gcd domains
+    domains where gcd can be computed but where there is no guarantee of
+    factorisation into irreducibles
+
+    EXAMPLES:
+      sage: GcdDomains()
+      Category of gcd domains
+      sage: GcdDomains().super_categories()
+      [Category of integral domains]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        from sage.categories.integral_domains import IntegralDomains
+        return [IntegralDomains()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        # gcd(x,y)
+        # lcm(x,y)
+        pass
diff --git a/sage/categories/graded_algebras.py b/sage/categories/graded_algebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_algebras.py
@@ -0,0 +1,46 @@
+r"""
+Graded Algebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import Algebras, GradedModules
+from sage.misc.cachefunc import cached_method
+
+class GradedAlgebras(Category_over_base_ring):
+    """
+    The category of graded algebras
+
+    EXAMPLES::
+
+        sage: GradedAlgebras(ZZ)
+        Category of graded algebras over Integer Ring
+        sage: GradedAlgebras(ZZ).super_categories()
+        [Category of graded modules over Integer Ring, Category of algebras over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedModules(R), Algebras(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/graded_algebras_with_basis.py b/sage/categories/graded_algebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_algebras_with_basis.py
@@ -0,0 +1,45 @@
+r"""
+GradedAlgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import GradedAlgebras, GradedModulesWithBasis, AlgebrasWithBasis
+from sage.misc.cachefunc import cached_method
+
+class GradedAlgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of graded algebras with a distinguished basis
+
+    EXAMPLES::
+
+        sage: GradedAlgebrasWithBasis(ZZ)
+        Category of graded algebras with basis over Integer Ring
+        sage: GradedAlgebrasWithBasis(ZZ).super_categories()
+        [Category of graded modules with basis over Integer Ring, Category of graded algebras over Integer Ring, Category of algebras with basis over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedModulesWithBasis(R),GradedAlgebras(R), AlgebrasWithBasis(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/graded_bialgebras.py b/sage/categories/graded_bialgebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_bialgebras.py
@@ -0,0 +1,46 @@
+r"""
+GradedBialgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import Bialgebras, GradedAlgebras, GradedCoalgebras
+from sage.misc.cachefunc import cached_method
+
+class GradedBialgebras(Category_over_base_ring):
+    """
+    The category of bialgebras with several bases
+
+    EXAMPLES::
+
+        sage: GradedBialgebras(ZZ)
+        Category of graded bialgebras over Integer Ring
+        sage: GradedBialgebras(ZZ).super_categories()
+        [Category of graded algebras over Integer Ring, Category of graded coalgebras over Integer Ring, Category of bialgebras over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedAlgebras(R), GradedCoalgebras(R), Bialgebras(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/graded_bialgebras_with_basis.py b/sage/categories/graded_bialgebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_bialgebras_with_basis.py
@@ -0,0 +1,45 @@
+r"""
+GradedBialgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import GradedBialgebras, GradedAlgebrasWithBasis, GradedCoalgebrasWithBasis
+from sage.misc.cachefunc import cached_method
+
+class GradedBialgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of graded bialgebras with a distinguished basis
+
+    EXAMPLES::
+
+        sage: GradedBialgebrasWithBasis(ZZ)
+        Category of graded bialgebras with basis over Integer Ring
+        sage: GradedBialgebrasWithBasis(ZZ).super_categories()
+        [Category of graded algebras with basis over Integer Ring, Category of graded coalgebras with basis over Integer Ring, Category of graded bialgebras over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedAlgebrasWithBasis(R), GradedCoalgebrasWithBasis(R), GradedBialgebras(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/graded_coalgebras.py b/sage/categories/graded_coalgebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_coalgebras.py
@@ -0,0 +1,45 @@
+r"""
+Graded Coalgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import Coalgebras, GradedModules
+from sage.misc.cachefunc import cached_method
+
+class GradedCoalgebras(Category_over_base_ring):
+    """
+    The category of graded coalgebras
+
+    EXAMPLES::
+
+        sage: GradedCoalgebras(ZZ)
+        Category of graded coalgebras over Integer Ring
+        sage: GradedCoalgebras(ZZ).super_categories()
+        [Category of graded modules over Integer Ring, Category of coalgebras over Integer Ring]
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedModules(R), Coalgebras(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/graded_coalgebras_with_basis.py b/sage/categories/graded_coalgebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_coalgebras_with_basis.py
@@ -0,0 +1,45 @@
+r"""
+GradedCoalgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import GradedCoalgebras, GradedModulesWithBasis, CoalgebrasWithBasis
+from sage.misc.cachefunc import cached_method
+
+class GradedCoalgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of graded coalgebras with a distinguished basis
+
+    EXAMPLES::
+    
+        sage: GradedCoalgebrasWithBasis(ZZ)
+        Category of graded coalgebras with basis over Integer Ring
+        sage: GradedCoalgebrasWithBasis(ZZ).super_categories()
+        [Category of graded modules with basis over Integer Ring, Category of graded coalgebras over Integer Ring, Category of coalgebras with basis over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedModulesWithBasis(R), GradedCoalgebras(R), CoalgebrasWithBasis(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/graded_hopf_algebras.py b/sage/categories/graded_hopf_algebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_hopf_algebras.py
@@ -0,0 +1,46 @@
+r"""
+Graded Hopf algebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import HopfAlgebras, GradedBialgebras
+from sage.misc.cachefunc import cached_method
+
+class GradedHopfAlgebras(Category_over_base_ring):
+    """
+    The category of GradedHopf algebras with several bases
+
+    EXAMPLES::
+
+        sage: GradedHopfAlgebras(ZZ)
+        Category of graded hopf algebras over Integer Ring
+        sage: GradedHopfAlgebras(ZZ).super_categories()
+        [Category of graded bialgebras over Integer Ring, Category of hopf algebras over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedBialgebras(R), HopfAlgebras(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/graded_hopf_algebras_with_basis.py b/sage/categories/graded_hopf_algebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_hopf_algebras_with_basis.py
@@ -0,0 +1,53 @@
+r"""
+GradedHopfAlgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import AbstractCategory, GradedHopfAlgebras, HopfAlgebrasWithBasis, GradedBialgebrasWithBasis
+from sage.misc.cachefunc import cached_method
+
+class GradedHopfAlgebrasWithBasis(Category_over_base_ring):
+    """
+    The category of graded Hopf algebras with a distinguished basis
+
+    EXAMPLES::
+
+        sage: GradedHopfAlgebrasWithBasis(ZZ)
+        Category of graded hopf algebras with basis over Integer Ring
+        sage: GradedHopfAlgebrasWithBasis(ZZ).super_categories()
+        [Category of graded bialgebras with basis over Integer Ring, Category of graded hopf algebras over Integer Ring, Category of hopf algebras with basis over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedBialgebrasWithBasis(R), GradedHopfAlgebras(R), HopfAlgebrasWithBasis(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
+
+    class AbstractCategory(AbstractCategory):
+        @cached_method
+        def super_categories(self):
+            from sage.categories.graded_hopf_algebras import GradedHopfAlgebras
+            R = self.base_category.base_ring()
+            return [GradedHopfAlgebras(R)]
+
diff --git a/sage/categories/graded_modules.py b/sage/categories/graded_modules.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_modules.py
@@ -0,0 +1,45 @@
+r"""
+GradedModules
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import Modules
+from sage.misc.cachefunc import cached_method
+
+class GradedModules(Category_over_base_ring):
+    """
+    The category of graded modules
+
+    EXAMPLES:
+      sage: GradedModules(ZZ)
+      Category of graded modules over Integer Ring
+      sage: GradedModules(ZZ).super_categories()
+      [Category of modules over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [Modules(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/graded_modules_with_basis.py b/sage/categories/graded_modules_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/graded_modules_with_basis.py
@@ -0,0 +1,45 @@
+r"""
+GradedModulesWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import GradedModules, ModulesWithBasis
+from sage.misc.cachefunc import cached_method
+
+class GradedModulesWithBasis(Category_over_base_ring):
+    """
+    The category of graded modules with a distinguished basis
+
+    EXAMPLES::
+
+        sage: GradedModulesWithBasis(ZZ)
+        Category of graded modules with basis over Integer Ring
+        sage: GradedModulesWithBasis(ZZ).super_categories()
+        [Category of graded modules over Integer Ring, Category of modules with basis over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [GradedModules(R), ModulesWithBasis(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/group_algebras.py b/sage/categories/group_algebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/group_algebras.py
@@ -0,0 +1,42 @@
+r"""
+GroupAlgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.misc.cachefunc import cached_method
+
+class GroupAlgebras(Category_over_base_ring):
+    """
+    EXAMPLES:
+        sage: GroupAlgebras(IntegerRing())
+        Category of group algebras over Integer Ring
+        sage: GroupAlgebras(IntegerRing()).super_categories()
+        [Category of monoid algebras over Integer Ring]
+
+    TESTS:
+        sage: C = GroupAlgebras(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        from monoid_algebras import MonoidAlgebras
+        R = self.base_ring()
+        return [MonoidAlgebras(R)] # TODO: could become Kac algebras / Hopf algebras
diff --git a/sage/categories/groupoid.py b/sage/categories/groupoid.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/groupoid.py
@@ -0,0 +1,56 @@
+r"""
+PointedSets
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class Groupoid(Category):
+    """
+    The category of groupoids, for a set (usually a group) $G$.
+
+    FIXME:
+     - Groupoid or Groupoids ?
+     - def and link with http://en.wikipedia.org/wiki/Groupoid
+
+    EXAMPLES:
+        sage: Groupoid(DihedralGroup(3))
+        Groupoid with underlying set Dihedral group of order 6 as a permutation group
+
+    TESTS:
+        sage: S8 = SymmetricGroup(8)
+        sage: C = Groupoid(S8)
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, G):
+        Category.__init__(self, "Groupoid")
+        self.__G = G
+
+    def __repr__(self):
+        return "Groupoid with underlying set %s"%self.__G
+        
+    def construction(self):
+        return (self.__class__, self.__G)
+
+    @cached_method
+    def super_categories(self):
+        from sets_cat import Sets
+        return [Sets()] # ???
+
diff --git a/sage/categories/groups.py b/sage/categories/groups.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/groups.py
@@ -0,0 +1,55 @@
+r"""
+Groups
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.monoids import Monoids
+from sage.misc.cachefunc import cached_method
+
+class Groups(Category):
+    """
+    The category of (multiplicative) groups, i.e. monoids with
+    inverses
+
+
+    EXAMPLES:
+        sage: Groups()
+        Category of groups
+        sage: Groups().super_categories()
+        [Category of monoids]
+
+    TESTS:
+        sage: C = Groups()
+        sage: loads(C.dumps()) == C
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [Monoids()]
+
+    class ParentMethods:
+
+        def test_inverse(self, **options):
+            tester = self.tester(**options)
+            for x in tester.some_elements():
+                tester.assertEquals(x * ~x, self.one())
+                tester.assertEquals(~x * x, self.one())
+
+    class ElementMethods:
+        ## inv(x), x/y
+        pass
diff --git a/sage/categories/hecke_modules.py b/sage/categories/hecke_modules.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/hecke_modules.py
@@ -0,0 +1,82 @@
+r"""
+Hecke modules
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category_types import Category_module
+from sage.misc.cachefunc import cached_method
+from sage.categories.category import HomCategory
+
+class HeckeModules(Category_module):
+    r"""
+    The category of Hecke modules.
+
+    A Hecke module is a module $M$ over the \emph{anemic} Hecke
+    algebra, i.e., the Hecke algebra generated by Hecke operators
+    $T_n$ with $n$ coprime to the level of $M$.  (Every Hecke module
+    defines a level function, which is a positive integer.)  The
+    reason we require that $M$ only be a module over the anemic Hecke
+    algebra is that many natural maps, e.g., degeneracy maps,
+    Atkin-Lehner operators, etc., are $\T$-module homomorphisms; but
+    they are homomorphisms over the anemic Hecke algebra.
+    
+    EXAMPLES:
+    We create the category of Hecke modules over $\Q$.
+        sage: C = HeckeModules(RationalField()); C
+        Category of Hecke modules over Rational Field
+
+    TODO: check that this is what we want:
+        sage: C.super_categories()
+        [Category of modules with basis over Rational Field]
+
+    # [Category of vector spaces over Rational Field]
+        
+    Note that the base ring can be an arbitrary commutative ring.
+        sage: HeckeModules(IntegerRing())
+        Category of Hecke modules over Integer Ring
+        sage: HeckeModules(FiniteField(5))
+        Category of Hecke modules over Finite Field of size 5
+
+    The base ring doesn't have to be a principal ideal domain.
+        sage: HeckeModules(PolynomialRing(IntegerRing(), 'x'))
+        Category of Hecke modules over Univariate Polynomial Ring in x over Integer Ring
+
+    TESTS:
+        sage: C = HeckeModules(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, R):
+        from commutative_rings import CommutativeRings
+        if R not in CommutativeRings():
+            raise TypeError, "R (=%s) must be a commutative ring"%R
+        Category_module.__init__(self, R, "Hecke modules")
+        
+    @cached_method
+    def super_categories(self):
+        from sage.categories.all import ModulesWithBasis
+        R = self.base_ring()
+        return [ModulesWithBasis(R)]
+
+    class HomCategory(HomCategory):
+        def extra_super_categories(self):
+            return [] # FIXME: what category structure is there on Homsets of hecke modules? 
+
+        import sage.modular.hecke.homspace
+        class ParentMethods(sage.modular.hecke.homspace.HeckeModuleHomspace):
+            pass
diff --git a/sage/categories/hopf_algebras.py b/sage/categories/hopf_algebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/hopf_algebras.py
@@ -0,0 +1,105 @@
+r"""
+HopfAlgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import Category, TensorialCategory, TensorCategory, DualityCategory, Bialgebras
+from sage.categories.tensor import tensor
+from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_attribute import lazy_attribute
+
+class HopfAlgebras(Category_over_base_ring, TensorialCategory, DualityCategory):
+    """
+    The category of Hopf algebras
+
+    EXAMPLES::
+
+        sage: HopfAlgebras(QQ)
+        Category of hopf algebras over Rational Field
+        sage: HopfAlgebras(QQ).super_categories()
+        [Category of bialgebras over Rational Field]
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [Bialgebras(R)]
+
+    def dual(self): # The category of Hopf Algebra is self dual
+        self
+        
+    class ElementMethods:
+        def antipode(self):
+            return self.parent().antipode(self)
+            # Variant: delegates to the overloading mechanism
+            # result not guaranted to be in self
+            # This choice should be done consistently with coproduct, ...
+            # return operator.antipode(self) 
+
+    class ParentMethods:
+        def __setup__(self): # Check the conventions for _setup_ or __setup__
+            if self.implements("antipode"):
+                coercion.declare(operator.antipode, [self], self.antipode)
+
+        @lazy_attribute
+        def antipode(self):
+            # delegates to the overloading mechanism but
+            # guarantees that the result is in self
+            compose(self, operator.antipode, domain=self)
+
+    class Morphism(Category):
+        """
+        The category of Hopf algebra morphisms
+        """
+        pass
+
+
+    class TensorCategory(TensorCategory):
+        """
+        The category of Hopf algebras constructed by tensor product of Hopf algebras
+        """
+        @cached_method
+        def super_categories(self):
+            return [HopfAlgebras(self.base_category.base_ring())]
+
+        class ParentMethods:
+            """
+            implements operations on tensor products of Hopf algebras
+            """
+            @lazy_attribute
+            def antipode(self):
+                return tensor([module.antipode for module in self.modules])
+
+        class ElementMethods:
+            """
+            implements operations on elements of tensor products of Hopf algebras
+            """
+            pass
+
+    class DualCategory(Category_over_base_ring):
+        """
+        The category of Hopf algebras constructed as dual of a Hopf algebra
+        """
+
+        class ParentMethods:
+            """
+            implements operations on the dual of a Hopf algebra
+            """
+            @lazy_attribute
+            def antipode(self):
+                self.dual().antipode.dual() # Check that this is the correct formula
diff --git a/sage/categories/hopf_algebras_with_basis.py b/sage/categories/hopf_algebras_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/hopf_algebras_with_basis.py
@@ -0,0 +1,158 @@
+r"""
+HopfAlgebrasWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Nicolas Thiery
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category_types import Category_over_base_ring
+from sage.categories.all import Category, TensorialCategory, TensorCategory, DualityCategory, HopfAlgebras, BialgebrasWithBasis, End
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.misc.cachefunc import cached_method
+
+class HopfAlgebrasWithBasis(Category_over_base_ring, TensorialCategory, DualityCategory):
+    """
+    The category of Hopf algebras with a distinguished basis
+
+    EXAMPLES::
+
+        sage: C = HopfAlgebrasWithBasis(QQ)
+        sage: C
+        Category of hopf algebras with basis over Rational Field
+        sage: C.super_categories()
+        [Category of bialgebras with basis over Rational Field, Category of hopf algebras over Rational Field]
+
+    We now show how to use a simple hopf algebra, namely the group algebra of the dihedral group
+    (see also AlgebrasWithBasis)::
+
+        sage: A = C.example(); A
+        The Hopf algebra of the Dihedral group of order 6 as a permutation group over Rational Field
+        sage: A.__custom_name = "A"
+        sage: A.category()
+        Category of hopf algebras with basis over Rational Field
+
+        sage: A.one_basis()
+        ()
+        sage: A.one()
+        B[()]
+
+        sage: A.base_ring()
+        Rational Field
+        sage: A.basis().keys()
+        Dihedral group of order 6 as a permutation group
+
+        sage: [a,b] = A.algebra_generators()
+        sage: a, b
+        (B[(1,2,3)], B[(1,3)])
+        sage: a^3, b^2
+        (B[()], B[()])
+        sage: a*b
+        B[(1,2)]
+
+        sage: A.product           # todo: not quite ...
+        Generic endomorphism of A
+        sage: A.product(b,b)
+        B[()]
+
+        sage: A.zero().coproduct()
+        0
+        sage: A.zero().coproduct().parent()
+        A # A
+        sage: a.coproduct()
+        B[(1,2,3)] # B[(1,2,3)]
+
+        sage: A.check(verbose=True)
+        running test_additive_associativity ... done
+        running test_an_element ... done
+        running test_associativity ... done
+        running test_element_pickling ... done
+        running test_not_implemented_methods ... done
+        running test_one ... done
+        running test_pickling ... done
+        running test_prod ... done
+        running test_product ... done
+        running test_some_elements ... done
+        sage: A.__class__
+        <class 'sage.categories.examples.hopf_algebras_with_basis.MyGroupAlgebra_with_category'>
+        sage: A.element_class
+        <class 'sage.combinat.free_module.MyGroupAlgebra_with_category.element_class'>
+
+    Let us look at the code for implementing A::
+
+        sage: A??                       # todo: not implemented
+
+    TESTS::
+
+        sage: loads(dumps(A)) is A
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [BialgebrasWithBasis(R), HopfAlgebras(R)]
+
+    def example(self, G = None):
+        """
+        Returns an example of algebra with basis::
+
+            sage: HopfAlgebrasWithBasis(QQ[x]).example()
+            The Hopf algebra of the Dihedral group of order 6 as a permutation group over Univariate Polynomial Ring in x over Rational Field
+
+        An other group can be specified as optional argument::
+        
+            sage: HopfAlgebrasWithBasis(QQ).example(SymmetricGroup(4))
+            The Hopf algebra of the SymmetricGroup(4) over Rational Field
+
+        """
+        from sage.categories.examples.hopf_algebras_with_basis import MyGroupAlgebra
+        from sage.groups.perm_gps.permgroup_named import DihedralGroup
+        if G is None:
+            G = DihedralGroup(3)
+        return MyGroupAlgebra(self.base_ring(), G)
+
+    class ParentMethods:
+
+        @lazy_attribute
+        def antipode(self, existence_only=False):
+            if hasattr(self, "antipode_on_basis"):
+                # Should give the information that this is an anti-morphism of algebra
+                return self._module_morphism(self.antipode_on_basis, codomain = self)
+
+    class ElementMethods:
+        pass
+
+    class TensorCategory(TensorCategory):
+        """
+        The category of hopf algebras with basis constructed by tensor product of hopf algebras with basis
+        """
+
+        @cached_method
+        def super_categories(self):
+            return [HopfAlgebrasWithBasis(self.base_category.base_ring())]
+
+        class ParentMethods:
+            """
+            implements operations on tensor products of modules with basis
+            """
+            # todo: antipode
+            pass
+
+        class ElementMethods:
+            """
+            implements operations on elements of tensor products of Hopf algebras
+            """
+            pass
+
diff --git a/sage/categories/infinite_enumerated_sets.py b/sage/categories/infinite_enumerated_sets.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/infinite_enumerated_sets.py
@@ -0,0 +1,134 @@
+r"""
+Infinite Enumerated Sets
+"""
+#*****************************************************************************
+#  Copyright (C) 2009 Florent Hivert <Florent.Hivert@univ-rouen.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+
+from category_types import Category
+from sage.misc.cachefunc import cached_method
+from sage.categories.enumerated_sets import EnumeratedSets
+
+#################################################################    
+class InfiniteEnumeratedSets(Category):
+    """
+    The category of infinite enumerated sets
+
+    An infinte enumerated sets is a countable sets together with a canonical
+    enumeration of its elements; It is a subcategory of ``EnumeratedSet()``.
+
+    EXAMPLES::
+
+        sage: InfiniteEnumeratedSets()
+        Category of infinite enumerated sets
+        sage: InfiniteEnumeratedSets().super_categories()
+        [Category of enumerated sets]
+        sage: InfiniteEnumeratedSets().all_super_categories()
+        [Category of infinite enumerated sets,
+         Category of enumerated sets,
+         Category of sets,
+         Category of objects]
+
+    TESTS::
+
+        sage: C = InfiniteEnumeratedSets()
+        sage: loads(C.dumps()) == C
+        True
+    """
+    @cached_method
+    def super_categories(self):
+        return [EnumeratedSets()]
+
+    def example(self):
+        """
+        The simplest example of infinite enumerated sets: the non-negative
+        integers. 
+
+        EXAMPLES::
+
+            sage: InfiniteEnumeratedSets().example()
+            Set of non negative integers
+        """
+        from sage.categories.examples.infinite_enumerated_sets import NonNegativeIntegers
+        return NonNegativeIntegers()
+
+    class ParentMethods:
+        def cardinality(self):
+            from sage.rings.infinity import infinity
+            """
+            Counts the elements of the enumerated set.
+            
+            EXAMPLES::
+            
+                sage: NN = InfiniteEnumeratedSets().example()
+                sage: NN.cardinality()
+                +Infinity
+            """
+            return infinity
+
+        def random_element(self):
+            """
+            Returns an error since self is an infinite enumerated set.
+        
+            EXAMPLES::
+
+                sage: NN = InfiniteEnumeratedSets().example()
+                sage: NN.random_element()
+                Traceback (most recent call last):
+                ...
+                NotImplementedError: infinite set
+            """
+            raise NotImplementedError, "infinite set"
+            
+        def list(self):
+            """
+            Returns an error since self is an infinite enumerated set.
+        
+            EXAMPLES::
+
+                sage: NN = InfiniteEnumeratedSets().example()
+                sage: NN.list()
+                Traceback (most recent call last):
+                ...
+                NotImplementedError: infinite list
+            """
+            raise NotImplementedError, "infinite list"
+        _list_default  = list # needed by the check system. 
+
+        # The following function overload the one
+        max_test_enumerated_set_loop=100 # number of element tested in self
+        def test_enumerated_set_iter_cardinality(self, **options):
+            tester = self.tester(**options)
+            """
+            Check the coherency between methods ``cardinality`` and
+            ``__iter__``. Automagically called by ``check()``
+
+            For infinite enumerated sets:
+            
+               * ``cardinality`` is supposed to return ``Infinity``
+
+               * ``list`` is supposed to raise a ``NotImplementedError``.
+
+            EXAMPLE::
+
+                sage: NN = InfiniteEnumeratedSets().example()
+                sage: NN.test_enumerated_set_iter_cardinality()
+            """
+            from sage.rings.infinity import infinity
+            tester.assertEqual(self.cardinality(), infinity)
+            tester.assertRaises(NotImplementedError, self.list)
+            
+    class ElementMethods:
+        pass
diff --git a/sage/categories/integral_domains.py b/sage/categories/integral_domains.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/integral_domains.py
@@ -0,0 +1,45 @@
+r"""
+IntegralDomains
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.basic import CommutativeRings, EntireRings
+from sage.misc.cachefunc import cached_method
+
+class IntegralDomains(Category):
+    """
+    The category of integral domains
+    commutative rings with no zero divisors
+
+    EXAMPLES:
+      sage: IntegralDomains()
+      Category of integral domains
+      sage: IntegralDomains().super_categories()
+      [Category of commutative rings, Category of entire rings]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        from sage.categories.basic import CommutativeRings, EntireRings
+        return [CommutativeRings(), EntireRings()] # TODO: Algebras(R) ?
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/left_modules.py b/sage/categories/left_modules.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/left_modules.py
@@ -0,0 +1,47 @@
+r"""
+LeftModules
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.all import AbelianGroups
+from category_types import Category_over_base_ring
+from sage.misc.cachefunc import cached_method
+
+#?class LeftModules(Category_over_base_rng):
+class LeftModules(Category_over_base_ring):
+    """
+    The category of left modules
+    left modules over an rng (ring not necessarily with unit), i.e.
+    an abelian group with left multiplation by elements of the rng
+
+    EXAMPLES:
+      sage: LeftModules(ZZ)
+      Category of left modules over Integer Ring
+      sage: LeftModules(ZZ).super_categories()
+      [Category of abelian groups]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [AbelianGroups()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        ## r * x
+        pass
diff --git a/sage/categories/matrix_algebras.py b/sage/categories/matrix_algebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/matrix_algebras.py
@@ -0,0 +1,42 @@
+r"""
+MatrixAlgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.misc.cachefunc import cached_method
+
+class MatrixAlgebras(Category_over_base_ring):
+    """
+    The category of matrix algebras over a field.
+    
+    EXAMPLES:
+        sage: MatrixAlgebras(RationalField())
+        Category of matrix algebras over Rational Field
+
+    TESTS:
+        sage: C = MatrixAlgebras(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        from algebras import Algebras
+        R = self.base_ring()
+        return [Algebras(R)]
diff --git a/sage/categories/modular_abelian_varieties.py b/sage/categories/modular_abelian_varieties.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/modular_abelian_varieties.py
@@ -0,0 +1,51 @@
+r"""
+ModularAbelianVarieties
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base
+from sage.misc.cachefunc import cached_method
+
+class ModularAbelianVarieties(Category_over_base):
+    """
+    The category of modular abelian varieties over a given field.
+
+    EXAMPLES:
+        sage: ModularAbelianVarieties(QQ)
+        Category of modular abelian varieties over Rational Field
+
+    TESTS:
+        sage: C = ModularAbelianVarieties(QQ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, Y):
+        assert Y.is_field()
+        Category_over_base.__init__(self, Y)
+        
+    def base_field(self):
+        return self.base()
+
+    @cached_method
+    def super_categories(self):
+        from sets_cat import Sets
+        return [Sets()] # FIXME
+
+    def _repr_(self):
+        return "Category of modular abelian varieties over %s"%self.base_field()
+
diff --git a/sage/categories/modules.py b/sage/categories/modules.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/modules.py
@@ -0,0 +1,101 @@
+r"""
+Modules
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.all import Bimodules, HomCategory
+from category_types import Category_over_base_ring
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.misc.cachefunc import cached_method
+
+class Modules(Category_over_base_ring):
+    """
+    The category of all modules over a base ring.
+
+ R-left and R-right modules
+    modules over a commutative ring
+    ##  r*(x*s) = (r*x)*s
+
+    EXAMPLES:
+        sage: Modules(RationalField())
+        Category of modules over Rational Field
+
+        sage: Modules(Integers(9))
+        Category of modules over Ring of integers modulo 9
+
+        sage: RingModules(Integers(9)).super_categories()
+        [Category of bimodules over Ring of integers modulo 9 on the left and Ring of integers modulo 9 on the right]
+        sage: RingModules(Integers(9)).all_super_categories()
+        [Category of modules over Ring of integers modulo 9,
+         Category of bimodules over Ring of integers modulo 9 on the left and Ring of integers modulo 9 on the right,
+         Category of left modules over Ring of integers modulo 9,
+         Category of right modules over Ring of integers modulo 9,
+         Category of abelian groups,
+         Category of abelian monoids,
+         Category of abelian semigroups,
+         Category of sets,
+         Category of objects]
+
+        sage: Modules(ZZ).super_categories()
+        [Category of bimodules over Integer Ring on the left and Integer Ring on the right]
+
+    TESTS:
+        sage: C = RingModules(ZZ)
+        sage: loads(dumps(C)) == C
+        True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [Bimodules(R,R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        def __mul__(left, right): 
+            from sage.structure.element import get_coercion_model
+            import operator
+            return get_coercion_model().bin_op(left, right, operator.mul)
+
+        def __rmul__(right, left): 
+            from sage.structure.element import get_coercion_model
+            import operator
+            return get_coercion_model().bin_op(left, right, operator.mul)
+
+
+    class HomCategory(HomCategory):
+        """
+        The category of homomorphisms sets Hom(X,Y) for X, Y modules
+        """
+        
+        def extra_super_categories(self):
+            return [Modules(self.base_category.base_ring())]
+
+        class ParentMethods:
+            @cached_method
+            def zero(self):
+                return self(lambda x: self.codomain().zero())
+
+    class EndCategory(HomCategory):
+        """
+        The category of endomorphisms sets End(X) for X module
+        """
+        
+        def extra_super_categories(self):
+            return [Algebras(self.base_category.base_ring())]
diff --git a/sage/categories/modules_with_basis.py b/sage/categories/modules_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/modules_with_basis.py
@@ -0,0 +1,509 @@
+r"""
+ModulesWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.all import Modules, Rings, Fields, VectorSpaces, HomCategory, Homset, AbelianCategory, DirectSumCategory, TensorialCategory, TensorCategory
+from category_types import Category_over_base_ring
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.misc.cachefunc import cached_method
+from sage.structure.element import ModuleElement
+from sage.categories.morphism import SetMorphism, Morphism
+from sage.categories.homset import Hom
+
+
+class ModulesWithBasis(Category_over_base_ring, AbelianCategory, TensorialCategory): #, DualityCategory):
+    """
+    The category of modules with a distinguished basis
+
+    EXAMPLES:
+        sage: ModulesWithBasis(ZZ)
+        Category of modules with basis over Integer Ring
+        sage: ModulesWithBasis(ZZ).super_categories()
+        [Category of modules over Integer Ring]
+
+      If the base ring is actually a field, this is a subcategory of
+      the category of abstract vector fields:
+
+        sage: ModulesWithBasis(RationalField()).super_categories()
+        [Category of vector spaces over Rational Field]
+
+      Let $X$ and $Y$ be two modules with basis. We can build $Hom(X,Y)$:
+        sage: X = CombinatorialFreeModule(QQ, [1,2]); X.__custom_name = "X"
+        sage: Y = CombinatorialFreeModule(QQ, [3,4]); Y.__custom_name = "Y"
+        sage: H = Hom(X, Y); H
+        Set of Morphisms from X to Y in Category of modules with basis over Rational Field
+
+      The simplest morphism is the zero map:
+
+        sage: H.zero()         # todo: move this test into module once we have an example
+        Generic morphism:
+          From: X
+          To:   Y
+
+      which we can apply to elements of X:
+        sage: x = X.term(1) + 3 * X.term(2)
+        sage: H.zero()(x)
+        0
+
+    TESTS:
+        sage: f = H.zero().on_basis()
+        sage: f(1)
+        0
+        sage: f(2)
+        0
+
+    EXAMPLES:
+      We now construct a more interesting morphism by extending a
+      function by linearity:
+
+        sage: phi = H(on_basis = lambda i: Y.term(i+2)); phi
+        Generic morphism:
+          From: X
+          To:   Y
+        sage: phi(x)
+        B[3] + 3*B[4]
+
+      We can retrieve the function acting on indices of the basis:
+        sage: f = phi.on_basis()
+        sage: f(1), f(2)
+        (B[3], B[4])
+
+      $Hom(X,Y)$ has a natural module structure (except for the zero,
+      the operations are not yet implemented though). However since
+      the dimension is not necessarily finite, it is not a module with
+      basis; but see FiniteDimensionalModulesWithBasis and
+      GradedModulesWithBasis:
+
+        sage: H in ModulesWithBasis(QQ), H in Modules(QQ)
+        (False, True)
+
+      Some more playing around with categories and higher order homsets:
+
+        sage: H.category()
+        Category of hom sets of Category of modules with basis over Rational Field
+        sage: Hom(H, H).category()
+        Category of hom sets of Category of modules over Rational Field
+
+      # TODO: End(X) is an algebra
+
+    TESTS:
+        sage: C = ModulesWithBasis(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        if R in Fields():
+            return [VectorSpaces(R)]
+        else:
+            return [Modules(R)]
+
+    def __call__(self, x):
+        try:
+            M = x.free_module()
+            if M.base_ring() != self.base_ring():
+                M = M.change_ring(self.base_ring())
+        except (TypeError, AttributeError), msg:
+            raise TypeError, "%s\nunable to coerce x (=%s) into %s"%(msg,x,self)            
+        return M
+
+    def is_abelian(self):
+        return self.base_ring().is_field()
+
+    # TODO: find something better to get this inheritance from TensorialCategory.Element
+    class ParentMethods(TensorialCategory.ParentMethods, AbelianCategory.ParentMethods):
+        def module_morphism(self, on_basis = None, diagonal = None,  **keywords):
+            """
+            Constructs functions by linearity
+
+            INPUT:
+             - self: a parent `X` in ModulesWithBasis(R), with basis `x` indexed by `I`
+             - codomain: the codomain `Y` of f: defaults to `f.codomain if the later is defined
+             - zero: the zero of the codomain; defaults to codomain.zero() or 0 if codomain is not specified
+             - position: a non negative integer; defaults to 0
+             - on_basis: a function `f` which accepts elements of `I`
+               as position-th argument and returns  elements of `Y`
+             - diagonal: a function `d` from `I` to `R`
+             - category: a category. By default, this is
+               ``ModulesWithBasis(R)`` if `Y` is in this category, and
+               otherwise this lets `Hom(X,Y)` decide
+            
+            Exactly one of ``on_basis`` and ``diagonal`` options should be specified.
+
+            With the ``on_basis`` option, this returns a function `g`
+            obtained by extending `f` by linearity on the position-th
+            positional argument. For example, for position == 1 and a
+            ternary function `f`, and denoting by x_i the basis of
+            `X`, one has:
+
+                `g(a, \sum \lambda_i x_i, c) = \sum \lambda_i f(a, i, c)`
+            
+            EXAMPLES::
+                sage: X = CombinatorialFreeModule(QQ, [1,2,3]);   X.rename("X")
+                sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y")
+                sage: phi = X.module_morphism(lambda i: Y.term(i) + 2*Y.term(i+1), codomain = Y)
+                sage: phi
+                Generic morphism:
+                From: X
+                To:   Y
+                sage: x = X.basis()
+                sage: phi(x[1] + x[3])
+                B[1] + 2*B[2] + B[3] + 2*B[4]
+
+            With the ``diagonal`` argument, this returns the module morphism `g` such that:
+
+                `g(x_i) = d(i) y_i`
+
+            This assumes that the respective bases `x` and `y` of `X`
+            and `Y` have the same index set `I`.
+
+
+            Caveat: the returned element is in ``Hom(codomain, domain,
+            category``). This is only correct for unary functions.
+
+            Todo: should codomain be self by default in the diagonal case?
+            
+            """
+            if diagonal is not None:
+                return DiagonalModuleMorphism(diagonal = diagonal, domain = self, **keywords)
+            elif on_basis is not None:
+                return ModuleMorphismByLinearity(on_basis = on_basis, domain = self, **keywords)
+            else:
+                raise ValueError("module morphism requires either on_basis or diagonal argument")
+
+        _module_morphism = module_morphism
+
+    # TODO: find something better to get this inheritance from TensorialCategory.Element
+    class ElementMethods(TensorialCategory.ElementMethods, AbelianCategory.ElementMethods):
+
+        def _neg_(self):
+            """
+            Default implementation of negation by trying to multiply by -1.
+            """
+            return self._lmul_(-self.parent()(1), self) # FIXME: use .parent().one()
+
+    class HomCategory(HomCategory):
+        """
+        The category of homomorphisms sets Hom(X,Y) for X, Y modules with basis
+        """
+
+        class ParentMethods: #(sage.modules.free_module_homspace.FreeModuleHomspace): #    Only works for plain FreeModule's
+            """
+            Abstract class for hom sets 
+            """
+
+            def __call__(self, on_basis = None, *args, **options):
+                if on_basis is not None:
+                    args = (self.domain()._module_morphism(on_basis, codomain = self.codomain()),) + args
+                h = Homset.__call__(self, *args, **options)
+                if on_basis is not None:
+                    h._on_basis = on_basis
+                return h
+
+            # Temporary hack
+            __call_on_basis__ = __call__
+
+            @lazy_attribute
+            def element_class_set_morphism(self):
+                return self.__make_element_class__(SetMorphism, "%s.element_class"%self.__class__.__name__, inherit = True)
+
+        class ElementMethods:
+            """
+            Abstract class for morphisms of modules with basis
+            """
+            def on_basis(self): # or lazy_attribute?
+                if not hasattr(self, "_on_basis"):
+                    term = self.domain().term
+                    self._on_basis = lambda t: self(term(t))
+                return self._on_basis
+
+
+    class DirectSumCategory(DirectSumCategory):
+        """
+        The category of modules with basis constructed by direct sums of modules with basis
+        """
+        @cached_method
+        def super_categories(self):
+            return [ModulesWithBasis(self.base_category.base_ring())]
+
+    
+        class ParentMethods:
+            # Will there be an super category with direct sum?
+            def _an_element_(self):
+                return direct_sum([module.an_element() for module in self.modules])
+
+    class TensorCategory(TensorCategory):
+        """
+        The category of modules with basis constructed by tensor product of modules with basis
+        """
+        @cached_method
+        def super_categories(self):
+            return [ModulesWithBasis(self.base_category.base_ring())]
+
+        class ParentMethods:
+            """
+            implements operations on tensor products of modules with basis
+            """
+            pass
+
+        class ElementMethods:
+            """
+            implements operations on elements of tensor products of Hopf algebras
+            """
+            pass
+
+class ModuleMorphismByLinearity(Morphism):
+    """
+    A class for module morphisms obtained by extending a function by linearity
+
+    EXAMPLES::
+        sage: X = CombinatorialFreeModule(QQ, [1,2])
+        sage: phi = sage.categories.modules_with_basis.ModuleMorphismByLinearity(X, QQ, zero = 0, codomain = QQ)
+        sage: phi
+        Generic morphism:
+          From: X
+          To:   Rational Field
+
+    TESTS::
+        sage: loads(dumps(phi))
+        Generic morphism:
+          From: X
+          To:   Rational Field
+        sage: loads(dumps(phi)) == phi # Todo: not implemented
+        True
+
+    """
+
+    
+    def __init__(self, domain, on_basis = None, position = 0, zero = None, codomain = None, category = None):
+        """
+        Constructs a module morphism by linearity
+        
+        INPUT:
+        - domain: a parent in ModulesWithBasis(...)
+        - codomain: a parent in Modules(...); defaults to f.codomain() if the later is defined
+        - position: a non negative integer; defaults to 0
+        - on_basis: a function which accepts indices of the basis of domain as position-th argument
+        - zero: the zero of the codomain; defaults to codomain.zero() or 0 if codomain is not specified
+
+        """
+        if codomain is None and hasattr(on_basis, 'codomain'):
+            codomain = on_basis.codomain()
+        if zero is None:
+            if codomain is not None:
+                zero = codomain.zero()
+            else:
+                zero = 0
+        if category is None and codomain is not None and codomain.category().is_subcategory(ModulesWithBasis(domain.base_ring())):
+            category = ModulesWithBasis(domain.base_ring())
+        if codomain is not None:
+            parent = Hom(domain, codomain, category = category)
+        Morphism.__init__(self, parent)
+        self._zero = zero
+        self.position = position
+        if on_basis is not None:
+            self._on_basis = on_basis
+
+    def on_basis(self):
+        return self._on_basis
+
+    def __call__(self, *args):
+        before = args[0:self.position]
+        after = args[self.position+1:len(args)]
+        x = args[self.position]
+        assert(x.parent() is self.domain())
+        return sum([self._on_basis(*(before+(index,)+after))._lmul_(coeff) for (index, coeff) in args[self.position]], self._zero)
+
+    # As per the specs of Map, we should in fact implement _call_ but
+    # Map.__call__ does strict type checking which prevents
+    # multi-parameter module morphisms
+    # To be cleaned up
+    _call_ = __call__ 
+
+class DiagonalModuleMorphism(ModuleMorphismByLinearity):
+    """
+    A class for diagonal module morphisms.
+
+    See :meth:`module_morphism` of ModulesWithBasis
+
+    EXAMPLES::
+        sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X")
+        sage: phi = X.module_morphism(diagonal = factorial, codomain = X)
+
+    TESTS::
+        sage: phi.__class__
+        <class 'sage.categories.modules_with_basis.DiagonalModuleMorphism'>
+        sage: loads(dumps(phi))
+        Generic endomorphism of X
+        sage: loads(dumps(phi)) == phi # Todo: not implemented
+        True
+
+    Todo:
+     - implement an optimized _call_ function
+     - generalize to a mapcoeffs
+     - generalize to a mapterms
+
+    """
+
+    def __init__(self, diagonal, domain, codomain = None, category = None):
+        """
+        INPUT:
+         - domain, codomain: two modules with basis `F` and `G`
+         - diagonal: a function `d`
+
+        Assumptions:
+         - `F` and `G` have the same base ring `R`
+         - Their respective bases `f` and `g` have the same index set `I`
+         - `d` is a function `I\mapsto R`
+
+        Returns the diagonal module morphism from F to G which maps
+        `f_\lambda` to `d(\lambda) g_\lambda`.
+
+        By default, codomain is currently assumed to be domain (Todo:
+        make a consistent choice with ModuleMorphism)
+        """
+        assert codomain is not None
+        assert domain.basis().keys() == codomain.basis().keys()
+        assert domain.base_ring()    == codomain.base_ring()
+        if category is None:
+            category = ModulesWithBasis(domain.base_ring())
+        ModuleMorphismByLinearity.__init__(self, domain = domain, codomain = codomain, category = category)
+        self._diagonal = diagonal
+
+    def _on_basis(self, i):
+        """
+        Returns the image by self of the basis element indexed by i
+        
+        TESTS::
+            sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X"); x = X.basis()
+            sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("Y"); y = Y.basis()
+            sage: phi = X.module_morphism(diagonal = factorial, codomain = X)
+            sage: phi._on_basis(3)
+            6*B[3]
+        """
+        return self.codomain().monomial(i, self._diagonal(i))
+
+    def __invert__(self):
+        """
+        Returns the inverse diagonal morphism
+
+            sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X"); x = X.basis()
+            sage: Y = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("Y"); y = Y.basis()
+            sage: phi = X.module_morphism(diagonal = factorial, codomain = X)
+            sage: phi_inv = ~phi
+            sage: phi_inv
+            Generic endomorphism of Y
+            sage: phi_inv(y[3])
+            1/6*B[3]
+
+        Caveat: this inverse morphism is only well defined if
+        `d(\lambda)` is always invertible in the base ring. This is
+        condition is *not* tested for, so using an ill defined inverse
+        morphism will trigger arithmetic errors.
+        """
+        return self.__class__(
+            pointwise_inverse_function(self._diagonal),
+            domain = self.codomain(), codomain = self.domain(), category = self.category_for())
+
+
+def pointwise_inverse_function(f):
+    """
+    INPUT:
+     - f: a function
+
+    Returns the function (...) -> 1 / f(...)
+
+    EXAMPLES:
+        sage: from sage.categories.modules_with_basis import pointwise_inverse_function
+        sage: def f(x): return x
+        ...
+        sage: g = pointwise_inverse_function(f)
+        sage: g(1), g(2), g(3)
+        (1, 1/2, 1/3)
+
+    pointwise_inverse_function is an involution:
+
+        sage: f is pointwise_inverse_function(g)
+        True
+
+    Todo: this has nothing to do here!!! Should there be a library for
+    pointwise operations on functions somewhere in Sage?
+    
+    """
+    if hasattr(f, "pointwise_inverse"):
+        return f.pointwise_inverse()
+    else:
+        return PointwiseInverseFunction(f)
+
+from sage.structure.sage_object import SageObject
+class PointwiseInverseFunction(SageObject):
+    """
+    A class for point wise inverse functions
+
+    EXAMPLES:
+        sage: from sage.categories.modules_with_basis import PointwiseInverseFunction
+        sage: f = PointwiseInverseFunction(factorial)
+        sage: f(0), f(1), f(2), f(3)
+        (1, 1, 1/2, 1/6)
+    """
+
+    def __eq__(self, other):
+        """
+        TESTS:
+            sage: from sage.categories.modules_with_basis import PointwiseInverseFunction
+            sage: f = PointwiseInverseFunction(factorial)
+            sage: g = PointwiseInverseFunction(factorial)
+            sage: f is g
+            False
+            sage: f == g
+            True
+        """
+        return self.__class__ is other.__class__ and self.__dict__ == other.__dict__
+
+    def __init__(self, f):
+        """
+        TESTS:
+            sage: from sage.categories.modules_with_basis import PointwiseInverseFunction
+            sage: f = PointwiseInverseFunction(factorial)
+            sage: f(0), f(1), f(2), f(3)
+            (1, 1, 1/2, 1/6)
+            sage: loads(dumps(f)) == f
+            True
+        """
+        self._pointwise_inverse = f
+
+    def __call__(self, *args):
+        """
+        TESTS:
+            sage: from sage.categories.modules_with_basis import PointwiseInverseFunction
+            sage: g = PointwiseInverseFunction(operator.mul)
+            sage: g(5,7)
+            1/35
+        """
+        return ~(self._pointwise_inverse(*args))
+
+    def pointwise_inverse(self):
+        """
+        TESTS:
+            sage: from sage.categories.modules_with_basis import PointwiseInverseFunction
+            sage: g = PointwiseInverseFunction(operator.mul)
+            sage: g.pointwise_inverse() is operator.mul
+            True
+        """
+        return self._pointwise_inverse
diff --git a/sage/categories/monoid_algebras.py b/sage/categories/monoid_algebras.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/monoid_algebras.py
@@ -0,0 +1,41 @@
+r"""
+MonoidAlgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.misc.cachefunc import cached_method
+
+class MonoidAlgebras(Category_over_base_ring):
+    """
+    The category of all monoid algebras over a given base ring.
+    EXAMPLES:
+        sage: MonoidAlgebras(GF(2))
+        Category of monoid algebras over Finite Field of size 2
+
+    TESTS:
+        sage: C = MonoidAlgebras(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        from algebras import Algebras
+        R = self.base_ring()
+        return [Algebras(R)]
diff --git a/sage/categories/monoids.py b/sage/categories/monoids.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/monoids.py
@@ -0,0 +1,135 @@
+r"""
+Monoids
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.semigroups import Semigroups
+from sage.misc.cachefunc import cached_method
+from sage.misc.misc_c import prod
+from sage.structure.element import Element, generic_power
+
+class Monoids(Category):
+    """
+    The category of (multiplicative) monoids, i.e. semigroups with a unit
+
+    EXAMPLES:
+        sage: Monoids()
+        Category of monoids
+        sage: Monoids().super_categories()
+        [Category of semigroups]
+        sage: Monoids().all_super_categories()
+        [Category of monoids,
+         Category of semigroups,
+         Category of sets,
+         Category of objects]
+
+    TESTS:
+        sage: C = Monoids()
+        sage: loads(C.dumps()) == C
+        True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [Semigroups()]
+
+    class ParentMethods:
+
+        @cached_method
+        def one(self):
+            """
+            Returns the one of the monoid, that is the unique neutral element for `*`.
+
+            The default implementation is to coerce `1` into self.
+
+            It is recommended to override this method because the
+            coercion from the integers:
+             - is not always meaningful (except for `1`),
+             - often uses self.one() otherwise.
+            """
+            return self(1)
+
+        def one_element(self):
+            """
+            Alias for self.one(), for backward compatibility
+            """
+            return self.one()
+
+        def test_one(self, **options):
+            tester = self.tester(**options)
+            for x in tester.some_elements():
+                tester.assert_(x * self.one() == x)
+                tester.assert_(self.one() * x == x)
+
+        def prod(self, args):
+            return prod(args, self.one())
+
+        def test_prod(self, **options):
+            tester = self.tester(**options)
+            tester.assert_(self.prod([]) == self.one())
+            for x in tester.some_elements():
+                tester.assert_(self.prod([x]) == x)
+                tester.assert_(self.prod([x, x]) == x**2)
+                tester.assert_(self.prod([x, x, x]) == x**3)
+
+    class ElementMethods:
+
+        def __pow__(self, n):
+            """
+            INPUTS:
+             - n: a non negative integer
+            
+            Returns self to the $n^{th}$ power.
+
+            EXAMPLES::
+
+                sage: S = Monoids().example("free")
+                sage: x = S("aa")
+                sage: x^0, x^1, x^2, x^3, x^4, x^5
+                ('', 'aa', 'aaaa', 'aaaaaa', 'aaaaaaaa', 'aaaaaaaaaa')
+
+            """
+            if not n: # FIXME: why do we need to do that?
+                return self.parent().one()
+            return generic_power(self, n, self.parent().one())
+
+        def _pow_naive(self, n):
+            """
+            A naive implementation of __pow__
+
+            INPUTS:
+             - n: a non negative integer
+            
+            Returns self to the $n^{th}$ power, without using binary
+            exponentiation (there are cases where this can actually be
+            faster du to size explotion).
+
+            EXAMPLES::
+
+                sage: S = Monoids().example("free")
+                sage: x = S("aa")
+                sage: [x._pow_naive(i) for i in range(6)]
+                ['', 'aa', 'aaaa', 'aaaaaa', 'aaaaaaaa', 'aaaaaaaaaa']
+            """
+            if not n:
+                return self.parent().one()
+            result = self
+            for i in range(n-1):
+                result *= self
+            return result
+            
diff --git a/sage/categories/number_fields.py b/sage/categories/number_fields.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/number_fields.py
@@ -0,0 +1,82 @@
+r"""
+Fields
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+from sage.categories.basic import Fields
+from sage.rings.field import is_Field
+
+class NumberFields(Category):
+    r"""
+    The category of number fields.
+    
+    EXAMPLES:
+    We create the category of number fields.
+        sage: C = NumberFields()
+        sage: C
+        Category of number fields
+
+    Notice that the rational numbers $\Q$ *are* considered as
+    an object in this category.
+        sage: RationalField() in C
+        True
+
+    However, we can define a degree 1 extension of $\Q$, which is of
+    course also in this category.
+        sage: x = PolynomialRing(RationalField(), 'x').gen()
+        sage: K = NumberField(x - 1, 'a'); K
+        Number Field in a with defining polynomial x - 1
+        sage: K in C
+        True
+
+    Number fields all lie in this category, regardless of the name
+    of the variable.
+        sage: K = NumberField(x^2 + 1, 'a')
+        sage: K in C
+        True
+
+    TESTS:
+        sage: C = NumberFields()
+        sage: loads(C.dumps()) == C
+        True
+    """
+
+    @cached_method
+    def super_categories(self):
+        return[Fields()]
+
+    def __contains__(self, x):
+        import sage.rings.all
+        return sage.rings.all.is_NumberField(x)
+
+    def __call__(self, x):
+        if x in self:
+            return x
+        try:
+            return x.number_field()
+        except AttributeError:
+            raise TypeError, "unable to canonically associate a number field to %s"%x
+
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/objects.py b/sage/categories/objects.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/objects.py
@@ -0,0 +1,66 @@
+r"""
+Objects
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import HomCategory
+from sage.categories.category import Category
+from sage.categories.homset import Homset
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+#############################################################
+# Generic category (default when requesting category of
+# an object using misc.functional.category
+#############################################################
+
+class Objects(Category):
+    """
+    The category of all objects
+    the basic category
+
+    EXAMPLES:
+      sage: Objects()
+      Category of objects
+      sage: Objects().super_categories()
+      []
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return []
+
+    def __contains__(self, x):
+        return True
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        ## basic operations which are no math
+        ## latex, hash, ...
+        pass
+
+    class HomCategory(HomCategory):
+        def extra_super_categories(self):
+            # This more or less assumes that the category is locally small.
+            # See http://en.wikipedia.org/wiki/Category_(mathematics)
+            from sets_cat import Sets
+            return [Sets()]
+
+        class ParentMethods(Homset):
+            pass
diff --git a/sage/categories/operads.py b/sage/categories/operads.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/operads.py
@@ -0,0 +1,44 @@
+r"""
+Operads
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import Modules
+from sage.misc.cachefunc import cached_method
+
+class Operads(Category_over_base_ring):
+    """
+    The category of operads
+
+    EXAMPLES:
+      sage: Operads(ZZ)
+      Category of operads over Integer Ring
+      sage: Operads(ZZ).super_categories()
+      [Category of modules over Integer Ring]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [Modules(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/operads_with_basis.py b/sage/categories/operads_with_basis.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/operads_with_basis.py
@@ -0,0 +1,44 @@
+r"""
+OperadsWithBasis
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_over_base_ring
+from sage.categories.all import Operads
+from sage.misc.cachefunc import cached_method
+
+class OperadsWithBasis(Category_over_base_ring):
+    """
+    The category of operads with a distinguished basis
+
+    EXAMPLES:
+      sage: OperadsWithBasis(QQ)
+      Category of operads with basis over Rational Field
+      sage: OperadsWithBasis(QQ).super_categories()
+      [Category of operads over Rational Field]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_ring()
+        return [Operads(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/ordered_monoids.py b/sage/categories/ordered_monoids.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/ordered_monoids.py
@@ -0,0 +1,45 @@
+r"""
+OrderedMonoids
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.basic import OrderedSets, Monoids
+from sage.misc.cachefunc import cached_method
+
+class OrderedMonoids(Category):
+    """
+    The category of ordered monoids
+    ordered sets which are also monoids, st. multiplication preserves the ordering
+
+
+    EXAMPLES:
+      sage: OrderedMonoids()
+      Category of ordered monoids
+      sage: OrderedMonoids().super_categories()
+      [Category of ordered sets, Category of monoids]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [OrderedSets(), Monoids()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/ordered_sets.py b/sage/categories/ordered_sets.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/ordered_sets.py
@@ -0,0 +1,45 @@
+r"""
+OrderedSets
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.basic import Sets
+from sage.misc.cachefunc import cached_method
+
+class OrderedSets(Category):
+    """
+    The category of ordered sets
+    #? totally # ordered sets
+
+    EXAMPLES:
+      sage: OrderedSets()
+      Category of ordered sets
+      sage: OrderedSets().super_categories()
+      [Category of sets]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [Sets()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        ##def <(x,y):
+        pass
diff --git a/sage/categories/pointed_sets.py b/sage/categories/pointed_sets.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/pointed_sets.py
@@ -0,0 +1,39 @@
+r"""
+PointedSets
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class PointedSets(Category):
+    """
+    The category of pointed sets.
+
+    EXAMPLES:
+        sage: PointedSets()
+        Category of pointed sets
+    """
+    def __call__(self, X, pt):
+        import sage.sets.all
+        return sage.sets.all.Set(X, pt)
+
+    @cached_method
+    def super_categories(self):
+        from sets_cat import Sets
+        return [Sets()] # ???
diff --git a/sage/categories/principal_ideal_domains.py b/sage/categories/principal_ideal_domains.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/principal_ideal_domains.py
@@ -0,0 +1,49 @@
+r"""
+PrincipalIdealDomains
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.basic import GcdDomains
+from sage.misc.cachefunc import cached_method
+
+class PrincipalIdealDomains(Category):
+    """
+    The category of unique factorization domains
+    constructive principal ideal domains, i.e. where a single generator can be 
+    constructively found for any ideal given by a finite set of generators
+    ++ Note that this constructive definition only implies that
+    ++ finitely generated ideals are principal. It is not clear
+    ++ what we would mean by an infinitely generated ideal.
+
+
+    EXAMPLES:
+      sage: PrincipalIdealDomains()
+      Category of principal ideal domains
+      sage: PrincipalIdealDomains().super_categories()
+      [Category of gcd domains]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [GcdDomains()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/quotient_fields.py b/sage/categories/quotient_fields.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/quotient_fields.py
@@ -0,0 +1,43 @@
+r"""
+QuotientFields
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.categories.all import Fields
+from sage.misc.cachefunc import cached_method
+
+class QuotientFields(Category):
+    """
+    The category of qoutient fields over a integral domain
+
+    EXAMPLES:
+      sage: QuotientFields()
+      Category of quotient fields
+      sage: QuotientFields().super_categories()
+      [Category of fields]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [Fields()] # TODO: Algebras(R) ?????
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/right_modules.py b/sage/categories/right_modules.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/right_modules.py
@@ -0,0 +1,47 @@
+r"""
+RightModules
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.all import AbelianGroups
+from category_types import Category_over_base_ring
+from sage.misc.cachefunc import cached_method
+
+##?class RightModules(Category_over_base_rng):
+class RightModules(Category_over_base_ring):
+    """
+    The category of right modules
+    right modules over an rng (ring not necessarily with unit), i.e.
+    an abelian group with right multiplation by elements of the rng
+
+    EXAMPLES:
+      sage: RightModules(QQ)
+      Category of right modules over Rational Field
+      sage: RightModules(QQ).super_categories()
+      [Category of abelian groups]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [AbelianGroups()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        ## x * r
+        pass
diff --git a/sage/categories/ring_ideals.py b/sage/categories/ring_ideals.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/ring_ideals.py
@@ -0,0 +1,52 @@
+r"""
+MonoidAlgebras
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_ideal
+from sage.misc.cachefunc import cached_method
+
+class RingIdeals(Category_ideal):
+    """
+    The category of all ideals in a fixed ring.
+    
+    EXAMPLES:
+        sage: Ideals(Integers(200))
+        Category of ring ideals in Ring of integers modulo 200
+        sage: C = Ideals(IntegerRing()); C
+        Category of ring ideals in Integer Ring
+        sage: I = C([8,12,18])
+        sage: I
+        Principal ideal (2) of Integer Ring
+
+    TESTS:
+        sage: C = RingIdeals(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, R):
+        from rings import Rings
+        if R not in Rings():
+            raise TypeError, "R (=%s) must be a ring"%R
+        Category_ideal.__init__(self, R)
+
+    @cached_method
+    def super_categories(self):
+        from modules import Modules
+        R = self.ring()
+        return [Modules(R)]
diff --git a/sage/categories/rings.py b/sage/categories/rings.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/rings.py
@@ -0,0 +1,102 @@
+r"""
+Rings
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from category import HomCategory
+import sage.rings.homset
+from sage.misc.cachefunc import cached_method
+
+class Rings(Category):
+    """
+    The category of rings
+    rings with unity, always associative, but not necessarily commutative
+
+    EXAMPLES:
+      sage: Rings()
+      Category of rings
+      sage: Rings().super_categories()
+      [Category of rngs, Category of monoids]
+
+    TESTS:
+        sage: C = Rings()
+        sage: loads(C.dumps()) == C
+        True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        from sage.categories.rngs import Rngs
+        from sage.categories.monoids import Monoids
+        # TODO? LeftModules(thering) / Modules(thering)
+        return [Rngs(), Monoids()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
+
+
+    class HomCategory(HomCategory):
+        def extra_super_categories(self):
+            from sage.categories.sets_cat import Sets
+            return [Sets()]
+
+        class ParentMethods:
+            # Design issue: when X is a quotient field, we can build
+            # morphisms from X to Y by specifying the images of the
+            # generators. This is not something about the category,
+            # because Y need not be a quotient field.
+
+            # Currently, and to minimize the changes, this is done by
+            # delegating the job to RingHomset. This is not very robust:
+            # for example, only one category can do this hack.
+
+            def __new__(cls, X, Y, category):
+                from sage.rings.homset import RingHomset
+                return RingHomset(X, Y, category = category)
+
+            # Without this, __new__ above gets called with no argument upon unpickling
+            # maybe it would be better to have __new__ accept to be called without arguments.
+            def __getnewargs__(self):
+                return (self.domain(), self.codomain(), self.category())
+
+    def get_Parent(self, X, Y):
+        """
+        Given two objects X and Y in this category, returns the parent
+        class to be used for the collection of the morphisms of this
+        category between X and Y.
+
+        Returns self.ParentMethods by default.
+
+        Rationale: some categories, like Rings or Schemes, currently
+        use different classes for their homset, depending on some
+        specific properties of X or Y which do not fit in the category
+        hierarchy. For example, if X is a quotient field, morphisms
+        can be defined by the image of the generators, even if Y
+        itself is not a quotient field.
+
+        Design question: should this really concern the parent for the
+        homset, or just the possible classes for the elements?
+        """
+        category = self.base_category
+        assert(X in category and Y in category)
+        # return self.hom_category()(X, Y)?
+        #print self.hom_category(), X, Y, self.hom_category().parent_class, self.hom_category().parent_class.mro()
+        return self.ParentMethods
diff --git a/sage/categories/rngs.py b/sage/categories/rngs.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/rngs.py
@@ -0,0 +1,47 @@
+r"""
+Rngs
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class Rngs(Category):
+    """
+    The category of rngs
+    associative rings, not necessarily commutative, and not necessarily with  1
+    This is a combination of an abelian group (+) and a semigroup (*), 
+    with * distributing over + 
+
+    EXAMPLES:
+      sage: Rngs()
+      Category of rngs
+      sage: Rngs().super_categories()
+      [Category of abelian groups, Category of semigroups]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        from abelian_groups import AbelianGroups
+        from semigroups import Semigroups
+        return [AbelianGroups(), Semigroups()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/schemes.py b/sage/categories/schemes.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/schemes.py
@@ -0,0 +1,153 @@
+r"""
+Schemes
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category, HomCategory
+from sage.categories.category_types import Category_over_base
+from sage.categories.all import Rings, Modules
+from sage.misc.cachefunc import cached_method
+from sage.structure.element import AlgebraElement, get_coercion_model
+from sage.rings.integer import Integer
+import operator
+
+def Schemes(X=None):
+    if X is None:
+        return Schemes_abstract()
+    from sage.schemes.all import is_Scheme
+    if not is_Scheme(X):
+        X = Schemes()(X)
+    return Schemes_over_base(X)
+    
+# TODO: rename into AbstractSchemes ???
+class Schemes_abstract(Category):
+    """
+    The category of all abstract schemes.
+
+    EXAMPLES:
+        sage: Schemes()
+        Category of Schemes
+    """
+    def __init__(self):
+        Category.__init__(self, "Schemes")
+        
+    @cached_method
+    def super_categories(self):
+        from sets_cat import Sets
+        return [Sets()]
+
+    def __call__(self, x):
+        """
+        EXAMPLES:
+        Fetch the category of schemes.
+            sage: S = Schemes(); S
+            Category of Schemes
+
+        We create a scheme from a ring.
+            sage: X = S(ZZ); X
+            Spectrum of Integer Ring
+
+        We create a scheme from a scheme (do nothing).
+            sage: S(X)
+            Spectrum of Integer Ring
+
+        We create a scheme morphism from a ring homomorphism.x
+            sage: phi = ZZ.hom(QQ); phi
+            Ring Coercion morphism:
+              From: Integer Ring
+              To:   Rational Field
+            sage: f = S(phi); f
+            Affine Scheme morphism:
+              From: Spectrum of Rational Field
+              To:   Spectrum of Integer Ring
+              Defn: Ring Coercion morphism:
+                      From: Integer Ring
+                      To:   Rational Field
+
+            sage: f.domain()
+            Spectrum of Rational Field
+            sage: f.codomain()
+            Spectrum of Integer Ring
+            sage: S(f)
+            Affine Scheme morphism:
+              From: Spectrum of Rational Field
+              To:   Spectrum of Integer Ring
+              Defn: Ring Coercion morphism:
+                      From: Integer Ring
+                      To:   Rational Field
+
+        """
+        from sage.rings.all import is_CommutativeRing, is_RingHomomorphism
+        from sage.schemes.all import is_Scheme, Spec, is_SchemeMorphism
+        if is_Scheme(x) or is_SchemeMorphism(x):
+            return x
+        elif is_CommutativeRing(x):
+            return Spec(x)
+        elif is_RingHomomorphism(x):
+            A = Spec(x.codomain())
+            return A.hom(x)
+        else:
+            raise TypeError, "No way to create an object or morphism in %s from %s"%(self, x)
+
+
+    class HomCategory(HomCategory):
+        def extra_super_categories(self):
+            return [] # FIXME: what category structure is there on Homsets of schemes?
+
+        class ParentMethods:
+            # If both schemes R and S are actually specs, we want the
+            # parent for Hom(R, S) to be in a different class
+
+            # Currently, and to minimize the changes, this is done by
+            # delegating the job to SchemeHomset. This is not very robust:
+            # for example, only one category can do this hack.
+
+            # FIXME: this would be better handled by an extra Spec category
+            def __new__(cls, R, S, category):
+                from sage.schemes.generic.homset import SchemeHomset
+                return SchemeHomset(R, S, category=category)
+
+
+#############################################################
+# Schemes over a given base scheme.
+#############################################################
+class Schemes_over_base(Category_over_base):
+    """
+    The category of schemes over a given base scheme.
+
+    EXAMPLES:
+        sage: Schemes(Spec(ZZ))
+        Category of schemes over Spectrum of Integer Ring
+
+    TESTS:
+        sage: C = Schemes(ZZ)
+        sage: loads(C.dumps()) == C
+        True
+    """
+    def __init__(self, Y):
+        Category_over_base.__init__(self, Y)
+        
+    def base_scheme(self):
+        return self.base()
+    
+    @cached_method
+    def super_categories(self):
+        return [Schemes_abstract()]
+
+    def _repr_(self):
+        return "Category of schemes over %s"%self.base_scheme()
diff --git a/sage/categories/semigroups.py b/sage/categories/semigroups.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/semigroups.py
@@ -0,0 +1,223 @@
+r"""
+Semigroups
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Florent Hivert <florent.hivert at univ-rouen.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.abstract_method import abstract_method
+from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.categories.sets_cat import Sets
+from sage.structure.unique_representation import UniqueRepresentation
+from sage.structure.parent import Parent
+from sage.structure.element import Element, generic_power
+from sage.structure.sage_object import have_same_parent
+from sage.structure.element_wrapper import ElementWrapper
+from sage.misc.cachefunc import default_keywords
+
+class Semigroups(Category):
+    """
+    The category of (multiplicative) semigroups, i.e. sets with an
+    associative operation *.
+
+    EXAMPLES::
+
+        sage: Semigroups()
+        Category of semigroups
+        sage: Semigroups().super_categories()
+        [Category of sets]
+        sage: Semigroups().all_super_categories()
+        [Category of semigroups, Category of sets, Category of objects]
+
+    TESTS::
+
+        sage: C = Semigroups()
+        sage: loads(C.dumps()) == C
+        True
+    """
+    @cached_method
+    def super_categories(self):
+        return [Sets()]
+
+    def example(self, choice= "lrband"):
+        import sage.categories.examples.semigroups as examples
+        if choice == "lrband":
+            return examples.LeftmostProductSemigroup()
+        else:
+            return examples.FreeSemigroup()
+        
+    class ParentMethods:
+
+        def test_associativity(self, **options):
+            tester = self.tester(**options)
+            # Better than use all.  
+            for x in tester.some_elements():
+                for y in tester.some_elements():
+                    for z in tester.some_elements():
+                        tester.assert_((x * y) * z == x * (y * z))
+
+        @abstract_method("optional")  # Should this be optional or not? Do we want to define it by default by calling x*y
+        def product(self, x, y):
+            """
+            The binary multiplication of the semigroup
+
+            This must be implemented by any parent in Semigroups().
+            
+            INPUT:
+             - ``x``, ``y``: elements of this semigroup
+
+            Returns the product of ``x`` and ``y``
+
+            EXAMPLES::
+
+                sage: S = Semigroups().example("free")
+                sage: x = S('a'); y = S('b')
+                sage: S.product(x, y)
+                'ab'
+
+            By default, the multiplication method on elements
+            ``x._mul_(y)`` calls ``S.product(x,y)``.
+
+            As a bonus effect, ``S.product`` by itself models the
+            binary function from ``S`` to ``S``::
+
+                sage: bin = S.product
+                sage: bin(x,y)
+                'ab'
+
+            Here, ``S.product`` is just a bound method. Whenever
+            possible, it is recommended to enrich this ``S.product``
+            with extra mathematical structure. Lazy attributes can
+            come handy for this.
+
+            Todo: add an example.
+            """
+            pass
+
+        def __init_extra__(self):
+            # Temporary, until the parent can register a multiplication in the coercion model
+            if (self.product is not NotImplemented) and hasattr(self.element_class, "_mul_parent"):
+                self.element_class._mul_ = self.element_class._mul_parent
+
+    class ElementMethods:
+
+        def _mul_parent(self, other):
+            return self.parent().product(self, other)
+
+        def __mul__(self, right): 
+            if have_same_parent(self, right) and hasattr(self, "_mul_"):
+                return self._mul_(right)
+            from sage.structure.element import get_coercion_model
+            import operator
+            return get_coercion_model().bin_op(self, right, operator.mul)
+
+        __imul__ = __mul__
+
+        def _pow_(self, n):
+            """
+            INPUTS:
+             - n: a positive integer
+            
+            Returns self to the $n^{th}$ power.
+
+            EXAMPLES::
+            
+                sage: S = Semigroups().example("free")
+                sage: x = S("aa")
+                sage: x^1, x^2, x^3, x^4, x^5
+                ('aa', 'aaaa', 'aaaaaa', 'aaaaaaaa', 'aaaaaaaaaa')
+                sage: x^0
+                Traceback (most recent call last):
+                ...
+                AssertionError
+
+            """
+            assert n > 0
+            return generic_power(self, n)
+
+        __pow__ = _pow_
+
+        def is_idempotent(self):
+            """
+            Returns whether self is idempotent, that is ``self^2 == self``.
+
+            EXAMPLES::
+
+                sage: M = Semigroups().example()
+            """
+            return self * self == self
+
+        
+    #######################################
+    class SubQuotients(Category): # (SubQuotientCategory):
+        r"""
+        The category of sub/quotient semi-groups.
+
+        Let $G$ and $S$ be two semi-groups and $l: S \mapsto G$ and
+        $r: G \mapsto S$ be two maps such that:
+         - $r \circ l$ is the identity of $G$.
+         - for any two $a,b\in S$ the identity
+        $a \times_S b = r(l(a) \times_G l(b))$ holds.
+        The category SubQuotient implement the product $\times_S$ from $l$ and $r$
+        and the product of $G$. 
+
+        S is supposed to belongs the category Semigroups().SubQuotients() and to
+        specify $G$ under the name S.ambient() and to implement $x\to l(x)$ and
+        $y \to r(y)$ under the names S.lift(x) and S.retract(y). 
+        """
+        
+        @cached_method
+        def super_categories(self):
+            return [Semigroups()]
+
+        def example(self):
+            """
+            Returns an example of sub quotient of a semigroup
+
+            EXAMPLES::
+
+                sage: Semigroups().SubQuotients().example()
+                A subquotient of The leftmost-product semigroup
+            """
+            from sage.categories.examples.semigroups import SubQuotientOfLeftmostProductSemigroup
+            return SubQuotientOfLeftmostProductSemigroup()
+
+        class ParentMethods:
+            def product(self, x, y):
+                """
+                Returns the product of two elements of self.
+
+                EXAMPLE::
+                    sage: S = Semigroups().SubQuotients().example()
+                    sage: S.product(S(19), S(3))
+                    19
+                """
+                assert(x in self)
+                assert(y in self)
+                return self.retract(self.lift(x) * self.lift(y))
+
+            def _repr_(self):
+                """
+                EXAMPLES::
+
+                    sage: Semigroups().SubQuotients().example()
+                    A subquotient of The leftmost-product semigroup
+                """
+                return "A subquotient of %s"%(self.ambient())
+
+    # Should we declare lift and retract to the coercion mechanism ?  
+
diff --git a/sage/categories/sets_cat.py b/sage/categories/sets_cat.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/sets_cat.py
@@ -0,0 +1,531 @@
+r"""
+Sets
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.misc.cachefunc import cached_method
+from sage.misc.abstract_method import abstract_method, AbstractMethod
+from sage.misc.lazy_attribute import lazy_attribute
+from sage.categories.category import Category, HomCategory
+# Do not use sage.categories.all here to avoid initialization loop
+from sage.categories.objects import Objects
+
+class Sets(Category):
+    """
+    The category of sets
+
+    The base category for collections of elements with = (equality)
+
+    This is also the category whose objects are all parents.
+
+    EXAMPLES::
+
+        sage: Sets()
+        Category of sets
+        sage: Sets().super_categories()  # Or nothing?
+        [Category of objects]
+        sage: Sets().all_super_categories()
+        [Category of sets, Category of objects]
+
+    Let us consider an example of set::
+
+        sage: P = Sets().example()
+        sage: P
+        Set of prime numbers
+
+    See ``P??`` for the code.
+
+        
+    P is in the category of sets::
+
+        sage: P.category()
+        Category of sets
+
+    and therefore gets its methods from the following classes::
+
+        sage: P.__class__.mro()
+        [<class 'sage.categories.examples.sets_cat.PrimeNumbers_with_category'>,
+         <class 'sage.categories.examples.sets_cat.PrimeNumbers'>,
+         <class 'sage.structure.unique_representation.UniqueRepresentation'>,
+         <type 'sage.structure.parent.Parent'>,
+         <type 'sage.structure.category_object.CategoryObject'>,
+         <type 'sage.structure.sage_object.SageObject'>,
+         <class 'sage.categories.sets_cat.Sets.parent_class'>,
+         <class 'sage.categories.objects.Objects.parent_class'>,
+         <type 'object'>]
+
+        [<class '__main__.PrimeNumbers_with_category'>,
+         <class '__main__.PrimeNumbers'>,
+         <class 'sage.structure.unique_representation.UniqueRepresentation'>,
+         <type 'sage.structure.parent.Parent'>,
+         <type 'sage.structure.category_object.CategoryObject'>,
+         <type 'sage.structure.sage_object.SageObject'>,
+         <class 'sage.categories.sets_cat.Sets.parent_class'>,
+         <class 'sage.categories.objects.Objects.parent_class'>,
+         <type 'object'>]
+
+    We run some generic checks on P::
+
+        sage: P.check(verbose=True)
+        running test_an_element ... done
+        running test_element_pickling ... done
+        running test_pickling ... done
+        running test_some_elements ... done
+
+    Now, we manipulate some elements of P::
+
+        sage: P.an_element()
+        47
+        sage: x = P(3)
+        sage: x.parent()
+        Set of prime numbers
+        sage: x in P, 3 in P
+        (True, False)
+        sage: x.is_prime()
+        True
+
+    They get their methods from the following classes::
+
+
+        sage: x.__class__.mro()
+        [<class 'sage.categories.examples.sets_cat.PrimeNumbers_with_category.element_class'>,
+         <class 'sage.categories.examples.sets_cat.Element'>,
+         <type 'sage.rings.integer.IntegerWrapper'>,
+         <type 'sage.rings.integer.Integer'>,
+         <type 'sage.structure.element.EuclideanDomainElement'>,
+         <type 'sage.structure.element.PrincipalIdealDomainElement'>,
+         <type 'sage.structure.element.DedekindDomainElement'>,
+         <type 'sage.structure.element.IntegralDomainElement'>,
+         <type 'sage.structure.element.CommutativeRingElement'>,
+         <type 'sage.structure.element.RingElement'>,
+         <type 'sage.structure.element.ModuleElement'>,
+         <type 'sage.structure.element.Element'>,
+         <type 'sage.structure.sage_object.SageObject'>,
+         <class 'sage.categories.sets_cat.Sets.element_class'>,
+         <class 'sage.categories.objects.Objects.element_class'>,
+         <type 'object'>]
+
+        [<class '__main__.PrimeNumbers_with_category.element_class'>,
+         <class '__main__.PrimeNumbers.Element'>,
+         <type 'int'>,
+         <class 'sage.categories.sets_cat.Sets.element_class'>,
+         <class 'sage.categories.objects.Objects.element_class'>,
+         <type 'object'>]
+
+    FIXME: Objects.element_class is not very meaning full ...
+
+
+    TESTS::
+
+          sage: loads(dumps(Sets())) is Sets()
+          True
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        return [Objects()]
+
+    def __call__(self, X):
+        """
+        EXAMPLES::
+        
+            sage: Sets()(ZZ)
+            Set of elements of Integer Ring
+        """
+        import sage.sets.all
+        return sage.sets.all.Set(X)
+
+    def example(self, facade = False):
+        """
+        Returns examples of objects of Sets().
+
+        See ``Category.example``.
+        
+        EXAMPLES::
+
+            sage: Sets().example()
+            Set of prime numbers
+
+            sage: Sets().example(facade=True)
+            Set of prime numbers (facade implementation)
+        """
+        if facade:
+            from sage.categories.examples.sets_cat import PrimeNumbers_Facade
+            return PrimeNumbers_Facade()
+        else:
+            from sage.categories.examples.sets_cat import PrimeNumbers
+            return PrimeNumbers()
+
+    class ParentMethods:
+#         # currently overriden by the default implementation in sage.structure.Parent
+#         def __call__(self, *args, **options):
+#             return self.element_class(*args, **options)
+
+        # Todo: simplify the _element_constructor definition logic
+        # Todo: find a nicer mantra for conditionaly defined methods
+        @lazy_attribute
+        def _element_constructor_(self):
+            if hasattr(self, "element_class"):
+                return self._element_constructor_from_element_class
+            else:
+                return NotImplemented
+
+        def _element_constructor_from_element_class(self, *args, **keywords):
+            """
+            The default constructor for elements of this parent
+
+            Among other things, it is called upon my_parent(data) when
+            the coercion model did not find a way to coerce data into
+            this parent.
+            """
+            return self.element_class(parent = self, *args, **keywords)
+
+        @abstract_method
+        def __contains__(self, x):
+            """
+            Tests whether the set contains the object x.  This raises a
+            NotImplementedError as a default since _all_ parent in the
+            category ``Sets()`` should override this.
+        
+            TESTS::
+        
+                sage: P = sage.categories.examples.sets_cat.PrimeNumbers()
+                sage: 12 in P
+                False
+                sage: P(5) in P
+                True
+            """
+            pass
+
+
+        @cached_method
+        def an_element(self):
+            r"""
+            Implementation of a function that returns an element (often non-trivial)
+            of a parent object.  This is cached. Parent structures that are should
+            override :meth:`_an_element_` instead.
+
+            EXAMPLES::
+        
+               sage: CDF.an_element()
+               1.0*I
+               sage: ZZ[['t']].an_element()
+               t
+            """
+            return self._an_element_()
+#            if self.__an_element is None:
+#                self.__an_element = self._an_element_()
+#            return self.__an_element
+
+
+        def tester(self, tester = None, **options):
+            """
+            Returns a gadget attached to self providing testing utilities
+
+                sage: tester = Sets().example().tester()
+
+                sage: tester.assert_(1 == 1)
+                sage: tester.assert_(1 == 0)
+                Traceback (most recent call last):
+                ...
+                AssertionError
+                sage: tester.assert_(1 == 0, "this is expected to fail")
+                Traceback (most recent call last):
+                ...
+                AssertionError: this is expected to fail
+
+                sage: tester.assertEquals(1, 1)
+                sage: tester.assertEquals(1, 0)
+                Traceback (most recent call last):
+                ...
+                AssertionError: 1 != 0
+
+            The available assertion testing facilities are the same as in
+            :class:`unittest.TestCase`, which see (actually, by a slight
+            abuse, tester is currently an instance of this class).
+
+            """
+            if tester is None:
+                return ParentTester(parent = self, **options)
+            else:
+                assert len(options) == 0
+                assert tester._parent is self
+                return tester
+        
+        def check(self, category = None, **options):
+            """
+            Runs tests on this parent
+
+            EXAMPLES::
+
+                sage: Sets().example().check()
+
+            No output means that all tests passed. Which tests? In
+            practice this calls all the methods ``.test_*`` of this
+            parent, in alphabetic order::
+
+                sage: Sets().example().check(verbose = True)
+                running test_an_element ... done
+                running test_element_pickling ... done
+                running test_not_implemented_methods ... done
+                running test_pickling ... done
+                running test_some_elements ... done
+
+            Those methods are typically provided by categories. For
+            example if self is in the category of finite semigroups,
+            this checks that the multiplication is associative (at
+            least on some elements)::
+
+                sage: S = FiniteSemigroups().example(alphabet = ('a', 'b'))
+                sage: S.check(verbose = True)
+                running test_an_element ... done
+                running test_associativity ... done
+                running test_element_pickling ... done
+                running test_enumerated_set_contains ... done
+                running test_enumerated_set_iter_cardinality ... done
+                running test_enumerated_set_iter_list ... done
+                running test_not_implemented_methods ... done
+                running test_pickling ... done
+                running test_some_elements ... done
+
+            The different test methods can be called independently::
+
+                sage: S.test_associativity()
+
+            One can further customize on which elements the tests are
+            run. Here, we use it to *prove* that the multiplication is
+            indeed associative, by runing the test on all the elements::
+
+                sage: S.test_associativity(elements = S)
+
+            Adding a new test boils down to adding a new method in the
+            class of the parent or any superclass or category. This
+            method should use the utility :meth:tester to handle
+            standard options and report test failures. See the code of
+            :meth:`test_an_element` for an example.
+
+            TODO:
+             - should this be self.test() or self.check() ?
+             - allow for customized behavior in case of failing assertion
+               (warning, error, statistic accounting)
+               This involves reimplementing the method sfail / failIf
+               / ... of unittest.TestCase in ParentTester below
+             - Improve integration with doctests (statistics on failing/passing tests)
+             - Integration with unittest:
+               def suite(category=None):
+                   returns a test suite with all tests
+                   with category argument, only returns the tests for this category (and its super categories????)
+               with that, check could just call self.suite.run() or something similar
+
+             - Add some standard option ``proof = True``, asking for
+               the test method to choose appropriately the elements so
+               as to prove the desired property. The test method may
+               assume that the parent implements properly all the
+               super categories. For example, the test_commutative
+               method of the category ``CommutativeSemigroups()`` may
+               just check that the provided generators commute,
+               implicitly assuming that generators indeed generate the
+               semigroup (as required by ``Semigroups()``).
+             - 
+            """
+            
+            tester = self.tester(**options)
+            for method_name in dir(self):
+                # Note: testunit usually looks for methods called test* , but we don't want to catch self.test() here!
+                if method_name[0:5] == "test_":
+                    # TODO: improve pretty printing
+                    # could use the doc string of the test method
+                    tester.info("running %s ..."%method_name, newline = False)
+                    getattr(self, method_name)(tester = tester)
+                    tester.info("done")
+
+        def test_not_implemented_methods(self, **options):
+            """
+            Checks that all required methods are implemented
+
+            TESTS:
+                sage: class A(Parent):
+                ...       def __init__(self):
+                ...           Parent.__init__(self, category = AbelianSemigroups())
+                ...       class Element:
+                ...           pass
+                sage: S = Semigroups().example().test_not_implemented_methods()
+                sage: A().test_not_implemented_methods()
+                Traceback (most recent call last):
+                ...
+                AssertionError: Not implemented method: summation
+
+            """
+            tester = self.tester(**options)
+            for name in dir(self):
+                # This tries to reduce the occasions to trigger the
+                # calculation of a lazy attribute
+                # This won't work for classes using the getattr trick
+                # to pseudo inherit from category
+                if hasattr(self.__class__, name):
+                    f = getattr(self.__class__, name)
+                    if not isinstance(f, AbstractMethod):
+                        continue
+                try:
+                    # self.name may have been set explicitly in self.__dict__
+                    getattr(self, name)
+                except AttributeError:
+                    pass
+                except NotImplementedError:
+                    tester.fail("Not implemented method: %s"%name)
+
+        def test_an_element(self, **options):
+            tester = self.tester(**options)
+            tester.assert_(self.an_element() in self)
+
+        def test_some_elements(self, **options):
+            tester = self.tester(**options)
+            elements = self.some_elements()
+            #Todo: enable this once 
+            #tester.assert_(elements != iter(elements),
+            #               "self.some_elements() should return an iterable, not an iterator")
+            for x in elements:
+                tester.assert_(x in self)
+
+        def some_elements(self):
+            """
+            Returns a list (or iterable) of elements of self.
+
+            This is typically used for running generic tests (see :meth:`check`).
+
+            By default, this calls :meth:`an_element`.
+
+                sage: S = Sets().example(); S
+                Set of prime numbers
+                sage: S.an_element()
+                47
+                sage: S.some_elements()
+                [47]
+            """
+            return [ self.an_element() ]
+
+        def test_pickling(self, **options):
+            tester = self.tester(**options)
+            from sage.misc.all import loads, dumps
+            tester.assertEqual(loads(dumps(self)), self)
+
+        def test_element_pickling(self, **options):
+            tester = self.tester(**options)
+            from sage.misc.all import loads, dumps
+            x = self.an_element()
+            tester.assertEqual(loads(dumps(x)), x)
+
+    class ElementMethods:
+        ##def equal(x,y):
+        ##def =(x,y):
+        pass
+
+    class HomCategory(HomCategory):
+        pass
+
+
+##############################################################################
+
+import unittest
+class ParentTester(unittest.TestCase):
+    def __init__(self, parent, elements = None, verbose = False, **options):
+        """
+        A gadget attached to a parent providing it with testing utilities.
+
+        EXAMPLES::
+        
+            sage: from sage.categories.sets_cat import ParentTester
+            sage: ParentTester(parent = ZZ, verbose = True, elements = [1,2,3])
+            Testing utilities for Integer Ring
+
+        This is used by ``Sets.ParentMethods.tester``, which see::
+
+            sage: Sets().example().tester()
+            Testing utilities for Set of prime numbers
+
+        """
+        self._parent = parent
+        self._verbose = verbose
+        self._elements = elements
+    
+    def runTest():
+        pass
+
+    def info(self, message, newline = True):
+        """
+        Displays user information
+
+        EXAMPLES::
+
+            sage: from sage.categories.sets_cat import ParentTester
+            sage: tester = ParentTester(ZZ, verbose = True)
+
+            sage: tester.info("hello"); tester.info("world")
+            hello
+            world
+
+            sage: tester = ParentTester(ZZ, verbose = False)
+            sage: tester.info("hello"); tester.info("world")
+
+            sage: tester = ParentTester(ZZ, verbose = True)
+            sage: tester.info("hello", newline = False); tester.info("world")
+            hello world
+
+            
+        """
+        if self._verbose:
+            if newline:
+                print message
+            else:
+                print message,            
+
+    def __repr__(self):
+        """
+        EXAMPLES::
+
+            sage: from sage.categories.sets_cat import ParentTester
+            sage: ParentTester(ZZ, verbose = True)
+            Testing utilities for Integer Ring
+
+        """
+        return "Testing utilities for %s"%self._parent
+
+
+    def some_elements(self):
+        """
+        Returns a list (or iterable) of elements of the parent on which the tests should be run.
+
+        By default, this calls parent.some_elements()::
+
+            sage: from sage.categories.sets_cat import ParentTester
+            sage: F = FiniteEnumeratedSet([1,2,3,4,5])
+
+            sage: tester = ParentTester(F)
+            sage: list(tester.some_elements())
+            [1, 2, 3, 4, 5]
+
+            sage: tester = ParentTester(F, elements = [1,3,5])
+            sage: list(tester.some_elements())
+            [1, 3, 5]
+
+        """
+        if self._elements is None:
+            return self._parent.some_elements()
+        else:
+            return self._elements
+
diff --git a/sage/categories/sets_with_partial_maps.py b/sage/categories/sets_with_partial_maps.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/sets_with_partial_maps.py
@@ -0,0 +1,49 @@
+r"""
+SetsWithPartialMaps
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#                     Nicolas M. Thiery <nthiery at users.sf.net>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class SetsWithPartialMaps(Category):
+    """
+    The category whose objects are sets and whose morphisms are
+    maps that are allowed to raise a ValueError on some inputs.
+
+    This category is equivalent to the category of pointed sets,
+    via the equivalence sending an object X to X union {error},
+    a morphism f to the morphism of pointed sets that sends x
+    to f(x) if f does not raise an error on x, or to error if it
+    does.
+
+    EXAMPLES:
+        sage: SetsWithPartialMaps()
+        Category with objects Sets and morphisms partially defined maps
+    """
+    def __call__(self, X, pt):
+        import sage.sets.all
+        return sage.sets.all.Set(X, pt)
+
+    def __repr__(self):
+        return "Category with objects Sets and morphisms partially defined maps"
+
+#    @cached_method
+#    def super_categories(self):
+#        from sets import Sets
+#        return [Sets()] ???
diff --git a/sage/categories/unique_factorization_domains.py b/sage/categories/unique_factorization_domains.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/unique_factorization_domains.py
@@ -0,0 +1,48 @@
+r"""
+UniqueFactorizationDomains
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from sage.categories.category import Category
+from sage.misc.cachefunc import cached_method
+
+class UniqueFactorizationDomains(Category):
+    """
+    The category of unique factorization domains
+    constructive unique factorization domains, i.e. where one can constructively 
+    factor members into a product of a finite number of irreducible elements
+
+    EXAMPLES:
+      sage: UniqueFactorizationDomains()
+      Category of unique factorization domains
+      sage: UniqueFactorizationDomains().super_categories()
+      [Category of gcd domains]
+
+    """
+
+    @cached_method
+    def super_categories(self):
+        from sage.categories.gcd_domains import GcdDomains
+        return [GcdDomains()]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        # prime?
+        # squareFree
+        # factor
+        pass
diff --git a/sage/categories/vector_spaces.py b/sage/categories/vector_spaces.py
new file mode 100644
--- /dev/null
+++ b/sage/categories/vector_spaces.py
@@ -0,0 +1,68 @@
+r"""
+VectorSpaces
+"""
+#*****************************************************************************
+#  Copyright (C) 2008 Teresa Gomez-Diaz (CNRS) <Teresa.Gomez-Diaz@univ-mlv.fr>
+#                     David Kohel <kohel@maths.usyd.edu> and
+#                     William Stein <wstein@math.ucsd.edu>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful, 
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#******************************************************************************
+
+from category_types import Category_module
+from sage.categories.all import Fields, Modules
+from sage.misc.cachefunc import cached_method
+
+class VectorSpaces(Category_module):
+    """
+    The category of (abstract) vector spaces over a given field
+
+    with an embedding in an ambient vector space ???
+
+    EXAMPLES:
+        sage: VectorSpaces(RationalField())
+        Category of vector spaces over Rational Field
+        sage: VectorSpaces(QQ).super_categories()
+        [Category of modules over Rational Field]
+
+    TESTS:
+        sage: C = QQ^10      # vector space
+        sage: loads(C.dumps()) == C
+        True
+
+    """
+    def __init__(self, K):
+        assert K in Fields()
+        Category_module.__init__(self, K)
+        
+    def __call__(self, x):
+        try:
+            V = x.vector_space(self.base_field())
+            if V.base_field() != self.base_field():
+                V = V.change_ring(self.base_field())
+        except (TypeError, AttributeError), msg:
+            raise TypeError, "%s\nunable to coerce x (=%s) into %s"%(msg,x,self)
+        return V
+
+    def base_field(self):
+        return self.base_ring()
+
+    @cached_method
+    def super_categories(self):
+        R = self.base_field()
+        return [Modules(R)]
+
+    class ParentMethods:
+        pass
+
+    class ElementMethods:
+        pass
diff --git a/sage/categories/abelian_monoids.py b/sage/categories/abelian_monoids.py
--- a/sage/categories/abelian_monoids.py
+++ b/sage/categories/abelian_monoids.py
@@ -63,11 +63,34 @@ class AbelianMonoids(Category):
 
         def zero_element(self):
             """
-            Alias for self.zero(), for backward compatibility
+            Backward compatibility alias for self.zero()
+
+            TESTS::
+
+            #    sage: S = AbelianMonoids().example("free")
+            #    sage: S.zero_element()
+            #    1
             """
             return self.zero()
 
     class ElementMethods:
+
+        def is_zero(self):
+            """
+            Returns whether self is the zero of the monoid
+
+            The default implementation, is to compare with ``self.zero()``.
+
+            TESTS::
+
+            #    sage: S = AbelianMonoids().example("free")
+            #    sage: S.zero().is_zero()
+            #    True
+            #    sage: S("aa").is_zero()
+            #    False
+            """
+            return self == self.parent().zero()
+
         def __sub__(left, right):
             """
             Top-level subtraction operator for ModuleElements.
diff --git a/sage/categories/monoids.py b/sage/categories/monoids.py
--- a/sage/categories/monoids.py
+++ b/sage/categories/monoids.py
@@ -63,7 +63,14 @@ class Monoids(Category):
 
         def one_element(self):
             """
-            Alias for self.one(), for backward compatibility
+            Backward compatibility alias for self.zero()
+
+            TESTS::
+
+                sage: S = Monoids().example("free")
+                sage: S.one_element()
+                ''
+
             """
             return self.one()
 
@@ -86,6 +93,22 @@ class Monoids(Category):
 
     class ElementMethods:
 
+        def is_one(self):
+            """
+            Returns whether self is the one of the monoid
+
+            The default implementation, is to compare with ``self.one()``.
+
+            TESTS::
+
+                sage: S = Monoids().example("free")
+                sage: S.one().is_one()
+                True
+                sage: S("aa").is_one()
+                False
+            """
+            return self == self.parent().one()
+
         def __pow__(self, n):
             """
             INPUTS:
