# The `subcategories`

package

This package provides variants of functor-like structures,
with domain types are constrained.
In particular, this package provides an abstraction for functorial
containers, which can be expressed as a functor from a *full-subcategory*
of **Hask** to **Hask** itself [^1].

For example:

- We can treat
`Set`

as if it is a `Fuctor`

, `Foldable`

, `Applicative`

,
with their domain restricted to full-subcategory **Ord** of `Ord`

instances
of **Hask**.
- For
`MonoFoldable`

or `MonoTraversable`

types (from `mono-traversable`

package),
we provide `WrapMono`

wrapper with zero-cost coercion. Such `mono`

s can be
regarded as a functorial structure from the full subcategory consisting of just a single object,
say `Element mono`

.

[^1]: Strictly speaking, `CFoldable`

, a constrained counterpart of `Foldable`

, doesn’t require a functoriality as with the original `Foldable`

.

## Optimisation

This library is designed to keep the abstraction runtime overhead as minimum as possible.

Some notes:

- If a constrained term such as
`cmap`

or `czipWith`

has concrete type, it must have exactly the same representation as the corresponding operation modulo (zero-cost) coercion.
- The same still holds if the set of required constraints coincides.
- Although the constructor of
`WrapMono mono a`

is hidden, its just a `newtype`

-wrapper around `mono`

;
hence, constrained operators must have the same representations as the corresponding combinators
in `mono-traversable`

package.

- OTOH, for a polymorphic term, like
`cmap :: (Ord a, Ord b) => (a -> b) Set a -> Set b`

and `Set.map`

, they can have different representations; indeed, `Set.map`

doesn’t require `a`

to be `Ord`

-instance and therefore the implementation of `cmap`

discards the dictionary for `Ord a`

to call `Set.map`

.