proarrow
Safe HaskellNone
LanguageGHC2024

Proarrow.Category.Enriched.Finitary

Description

Profunctors whose hom-sets are finite and numbered: p a b is in bijection with an initial segment of the naturals. This is the profunctor form of the skeleton of the category of finite sets, and it is what makes limits and colimits computable. An element is an index, so a subset or a quotient of a hom-set is a table of indices, which a computation can produce and reify into a fresh object; an arbitrary profunctor offers no handle on its hom-set other than the type itself.

The numbering is deliberately a value, as in Proarrow.Category.Instance.FinHask: a size that had to be a type family could only ever be a formula in the sizes it is built from, which rules out every construction whose count depends on how arrows compose -- the exponential and the subobject classifier among them. As values, those are enumerations like any other.

This is the sibling of Proarrow.Category.Enriched.Thin, which it builds on: a DecidableProfunctor is the special case where every size is zero or one, its Decision being the pair toIndex/fromIndex, and decidableSize and decidableFromIndex build such an instance. As there, the class, the kind wrapper FINITARY and the instances for the basic profunctors all live together here.

Synopsis

Documentation

class Profunctor p => Finitary (p :: j +-> k) where Source Github #

A profunctor with finite, numbered hom-sets. toIndex and fromIndex are inverse for indices below size; fromIndex of anything else is an error, as is toIndex of an element that is not one the instance can produce (which only an unlawfully built value can be).

An instance whose elements are found by searching should define elements and read size off it, rather than let the default call fromIndex once per element and repeat the search each time.

Minimal complete definition

size, toIndex, fromIndex

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

How many elements the hom-set has.

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => p a b -> Natural Source Github #

Where an element sits in elements. Takes its objects like the others do, so that an instance that has to search can bind the search outside the argument lambda and a caller can share it with let toIndexP = toIndex @p @a @b.

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> p a b Source Github #

The element at a position.

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [p a b] Source Github #

All elements of a hom-set, in index order.

Instances

Instances details
Finitary Booleans Source Github #

BOOL is thin, so each hom-set holds at most the one arrow.

Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: BOOL) (b :: BOOL). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: BOOL) (b :: BOOL). (Ob a, Ob b) => Booleans a b -> Natural Source Github #

fromIndex :: forall (a :: BOOL) (b :: BOOL). (Ob a, Ob b) => Natural -> Booleans a b Source Github #

elements :: forall (a :: BOOL) (b :: BOOL). (Ob a, Ob b) => [Booleans a b] Source Github #

Finitary FinHask Source Github #

The hom-sets of FINHASK are finite, so its hom-profunctor is finitary, and it is numbered by the same universe the Finite instance above enumerates -- but arithmetically rather than by searching it. A morphism is a table of values indexed by universeF @a, so reading that table as a numeral in base |b|, most significant digit first, gives exactly universe's own order: universe is traverse (a -> (a,) <$> universe) universe, and for lists <*> varies its right operand fastest, so it is the last element of a that varies fastest.

Instance details

Defined in Proarrow.Category.Instance.FinHask

Methods

size :: forall (a :: FINHASK) (b :: FINHASK). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: FINHASK) (b :: FINHASK). (Ob a, Ob b) => FinHask a b -> Natural Source Github #

fromIndex :: forall (a :: FINHASK) (b :: FINHASK). (Ob a, Ob b) => Natural -> FinHask a b Source Github #

elements :: forall (a :: FINHASK) (b :: FINHASK). (Ob a, Ob b) => [FinHask a b] Source Github #

Finitary Unit Source Github #

The one-object category has one arrow.

Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: ()) (b :: ()). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: ()) (b :: ()). (Ob a, Ob b) => Unit a b -> Natural Source Github #

fromIndex :: forall (a :: ()) (b :: ()). (Ob a, Ob b) => Natural -> Unit a b Source Github #

elements :: forall (a :: ()) (b :: ()). (Ob a, Ob b) => [Unit a b] Source Github #

(CategoryOf j, CategoryOf k) => Finitary (InitialProfunctor :: k -> j -> Type) Source Github #

The initial profunctor has no elements anywhere.

Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => InitialProfunctor a b -> Natural Source Github #

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> InitialProfunctor a b Source Github #

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [InitialProfunctor a b] Source Github #

(FiniteCat j, FiniteCat k) => Finitary (Sieve :: k -> j -> Type) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Sieve a b -> Natural Source Github #

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> Sieve a b Source Github #

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [Sieve a b] Source Github #

(CategoryOf j, CategoryOf k) => Finitary (TerminalProfunctor :: k -> j -> Type) Source Github #

The terminal profunctor has one element everywhere.

Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => TerminalProfunctor a b -> Natural Source Github #

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> TerminalProfunctor a b Source Github #

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [TerminalProfunctor a b] Source Github #

(Finitary p, Enumerable j, Enumerable k, KnownTable (Objects j) (Objects k) fs) => Finitary (Reindex p fs :: k -> j -> Type) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Reindex p fs a b -> Natural Source Github #

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> Reindex p fs a b Source Github #

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [Reindex p fs a b] Source Github #

(Finitary p, Finitary q) => Finitary (p :+: q :: k -> j -> Type) Source Github #

The indices of p first, then those of q.

Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => (p :+: q) a b -> Natural Source Github #

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> (p :+: q) a b Source Github #

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [(p :+: q) a b] Source Github #

(Finitary p, Finitary q, FiniteCat j, FiniteCat k) => Finitary (p :~>: q :: k -> j -> Type) Source Github #

The internal hom of finitary profunctors is finitary: its elements are the natural families, enumerated. Nothing here is a formula in the sizes of p and q -- the count depends on how the arrows of j and k compose -- which is why size is a value and not a type family.

Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => (p :~>: q) a b -> Natural Source Github #

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> (p :~>: q) a b Source Github #

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [(p :~>: q) a b] Source Github #

(Finitary p, Finitary q) => Finitary (p :*: q :: k -> j -> Type) Source Github #

A pair of indices as one index, row-major: i * size @q + j.

Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => (p :*: q) a b -> Natural Source Github #

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> (p :*: q) a b Source Github #

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [(p :*: q) a b] Source Github #

type FINITARY j k = SUBCAT (Finitary :: (j +-> k) -> Constraint) Source Github #

The subcategory of finitary profunctors, as Proarrow.Category.Instance.Rep does for representable ones.

type FIN (p :: j +-> k) = 'SUB p :: SUBCAT (Finitary :: (j +-> k) -> Constraint) Source Github #

indices :: Natural -> [Natural] Source Github #

[0 .. n-1], which n being a Natural rules out writing directly.

objIndex :: forall {k} (a :: k). (Enumerable k, Ob a) => Natural Source Github #

The position of an object in its kind's object list.

foreachOb :: Enumerable k => (forall (a :: k). Ob a => [r]) -> [r] Source Github #

Everything an enumeration of a kind's objects can do at each of them, concatenated.

Thin profunctors

decidableSize :: forall {j} {k} (p :: j +-> k) (a :: k) (b :: j). (DecidableProfunctor p, Ob a, Ob b) => Natural Source Github #

A decidable profunctor has one element where it holds and none where it does not. These cannot be default method bodies: size and fromIndex do not mention their objects except in a constraint, so GHC cannot tie a default body's objects to the instance's.

decidableFromIndex :: forall {j} {k} p (a :: k) (b :: j). (DecidableProfunctor p, Ob a, Ob b) => Natural -> p a b Source Github #

Hom-sets as finite sets

newtype Elt (p :: j +-> k) (a :: k) (b :: j) Source Github #

An element of a hom-set of p, viewed as an element of a finite set: every instance the universe package asks for is supplied by the numbering, with toIndex standing in for equality and ordering. This is what makes a finitary profunctor a profunctor enriched in FINHASK -- see its EnrichedProfunctor FINHASK instance -- exactly as a decided profunctor is one enriched in BOOL.

Constructors

Elt 

Fields

Instances

Instances details
Finitary p => Show (Elt p a b) Source Github #

Its Eq and Ord cost whatever toIndex costs, so an instance intended for enrichment should compute toIndex directly rather than by searching elements -- finiteToIndex searches, which is fine for small hom-sets and not for large ones.

The index, there being nothing else to show: a hom-set of a finitary profunctor is known only up to its numbering.

Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

showsPrec :: Int -> Elt p a b -> ShowS Github #

show :: Elt p a b -> String Github #

showList :: [Elt p a b] -> ShowS Github #

Finitary p => Eq (Elt p a b) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

(==) :: Elt p a b -> Elt p a b -> Bool Github #

(/=) :: Elt p a b -> Elt p a b -> Bool Github #

Finitary p => Ord (Elt p a b) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

compare :: Elt p a b -> Elt p a b -> Ordering Github #

(<) :: Elt p a b -> Elt p a b -> Bool Github #

(<=) :: Elt p a b -> Elt p a b -> Bool Github #

(>) :: Elt p a b -> Elt p a b -> Bool Github #

(>=) :: Elt p a b -> Elt p a b -> Bool Github #

max :: Elt p a b -> Elt p a b -> Elt p a b Github #

min :: Elt p a b -> Elt p a b -> Elt p a b Github #

(Finitary p, Ob a, Ob b) => Finite (Elt p a b) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

universeF :: [Elt p a b] Github #

cardinality :: Tagged (Elt p a b) Natural Github #

(Finitary p, Ob a, Ob b) => Universe (Elt p a b) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

universe :: [Elt p a b] Github #

class (CategoryOf k, Finitary (Hom k)) => LocallyFinite k Source Github #

A category whose hom-sets are finite: the Finitary counterpart of Decidable, and one half of FiniteCat.

Instances

Instances details
(CategoryOf k, Finitary (Hom k)) => LocallyFinite k Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

finiteSize :: forall {j} {k} (p :: j +-> k) (a :: k) (b :: j). Finite (p a b) => Natural Source Github #

A profunctor between categories with finite hom-sets is finitary exactly when it is enriched in finite sets, so a Finitary instance can be read off an enrichment as well as the other way round: these are the counterparts of decidableSize and decidableFromIndex one level up.

finiteToIndex and finiteFromIndex number a hom-set by searching its universeF, which is all a bare Finite instance allows. That is fine for small hom-sets, and an instance whose hom-sets are large should compute the index arithmetically instead -- FinHask does, because Elt's Ord is compare on indices and so pays for every comparison.

finiteToIndex :: forall {j} {k} p (a :: k) (b :: j). (Finite (p a b), Eq (p a b)) => p a b -> Natural Source Github #

finiteFromIndex :: forall {j} {k} p (a :: k) (b :: j). Finite (p a b) => Natural -> p a b Source Github #

Products and coproducts

Tables of fibres

class KnownNats (ns :: [Nat]) where Source Github #

A type-level list of naturals, reflected.

Instances

Instances details
KnownNats ('[] :: [Nat]) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

(SNatI n, KnownNats ns) => KnownNats (n ': ns) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

class KnownFibres (fs :: [[Nat]]) where Source Github #

A type-level list of lists of naturals, reflected: the fibres of a partial surjection out of one hom-set.

Instances

Instances details
KnownFibres ('[] :: [[Nat]]) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

(KnownNats f, KnownFibres fs) => KnownFibres (f ': fs) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

fibres :: [[Natural]] -> (forall (fs :: [[Nat]]). KnownFibres fs => r) -> r Source Github #

Reify a list of lists of naturals.

type KnownTable (bs :: [y]) (as :: [y1]) (t :: [[[[Nat]]]]) = KnownList (KnownList KnownFibres bs) as t Source Github #

A table: a row for each object of k, and in each row the fibres at each object of j.

buildTable :: (Enumerable j, Enumerable k) => (forall (a :: k) (b :: j). (Ob a, Ob b) => [[Natural]]) -> (forall (t :: [[[[Nat]]]]). KnownTable (Objects j) (Objects k) t => r) -> r Source Github #

Build a table by visiting every pair of objects, reifying each cell.

Reindexing along a table of fibres

newtype Reindex (p :: j +-> k) (fs :: [[[[Nat]]]]) (a :: k) (b :: j) Source Github #

p relabelled, at each pair of objects, along a partial surjection onto an initial segment of the naturals, given by its fibres: index i of the new hom-set stands for the elements of p in the i-th fibre. Singleton fibres cut out a subobject, a partition is a quotient. Well behaved exactly when the fibres are respected by p's dimap, which is the case for the tables equalize and coequalize build; dimap delegates to p and relies on it.

Constructors

Reindex (p a b) 

Instances

Instances details
(Finitary p, Enumerable j, Enumerable k, KnownTable (Objects j) (Objects k) fs) => Finitary (Reindex p fs :: k -> j -> Type) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

size :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural Source Github #

toIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Reindex p fs a b -> Natural Source Github #

fromIndex :: forall (a :: k) (b :: j). (Ob a, Ob b) => Natural -> Reindex p fs a b Source Github #

elements :: forall (a :: k) (b :: j). (Ob a, Ob b) => [Reindex p fs a b] Source Github #

Profunctor p => Profunctor (Reindex p fs :: k -> j -> Type) Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

Methods

dimap :: forall (c :: k) (a :: k) (b :: j) (d :: j). (c ~> a) -> (b ~> d) -> Reindex p fs a b -> Reindex p fs c d Source Github #

lmap :: forall (c :: k) (a :: k) (b :: j). (c ~> a) -> Reindex p fs a b -> Reindex p fs c b Source Github #

rmap :: forall (b :: j) (d :: j) (a :: k). (b ~> d) -> Reindex p fs a b -> Reindex p fs a d Source Github #

(\\) :: forall (a :: k) (b :: j) r. ((Ob a, Ob b) => r) -> Reindex p fs a b -> r Source Github #

type Cell (fs :: [[k]]) (a :: k1) (b :: j) = Entry (Entry fs (Index a)) (Index b) Source Github #

withCell :: forall {j} {k} (fs :: [[[[Nat]]]]) (a :: k) (b :: j) r. (Enumerable j, Enumerable k, KnownTable (Objects j) (Objects k) fs, Ob a, Ob b) => (KnownFibres (Cell fs a b) => r) -> r Source Github #

The fibres at a pair of objects, found by walking the table to the objects' positions.

closedUnder :: (Finitary p, FiniteCat j, FiniteCat k) => (forall (a :: k) (b :: j). (Ob a, Ob b) => p a b -> Bool) -> Bool Source Github #

Whether a predicate on p's elements picks out a subprofunctor: the elements it keeps must be closed under the action, since Reindex inherits its dimap from p and so can only carve out a set that is.

dimap l r is lmap l . rmap r, so closure under the two whiskerings separately is closure under the action: two walks over three objects rather than one over four.

withSubobject :: (Finitary p, FiniteCat j, FiniteCat k) => (forall (a :: k) (b :: j). (Ob a, Ob b) => p a b -> Bool) -> (forall (q :: j +-> k). Finitary q => (FIN q ~> FIN p) -> r) -> r -> r Source Github #

Carve a subprofunctor out of p, the caller choosing which elements to keep, and receiving the new object's inclusion. This is what equalize does with the elements two transformations agree on, exposed so that a caller can pick out a subobject of its own: it is how a value -- a graph read off a file, say -- becomes an object of FINITARY j k, as a subobject of a big enough ambient one. The failure continuation is taken when the kept set is not closedUnder the action, and so is no subobject.

Equalizers and coequalizers

preimage :: forall {j} {k} p q (a :: k) (b :: j). (Finitary p, Finitary q, Ob a, Ob b) => String -> (p a b -> q a b) -> q a b -> p a b Source Github #

The element of p that f sends to a given element of q, when f is injective and the element is in its image -- which is what both factorizations below need, in opposite directions.

classes :: [(Natural, Natural)] -> [Natural] -> [[Natural]] Source Github #

Partition a list of indices into the equivalence classes generated by a list of pairs. Both levels are sorted, so the classes come out ordered by their least member and the table is canonical.

Pullbacks, pushouts and images

Ends by enumeration

class (Enumerable k, Finitary (Hom k)) => FiniteCat k Source Github #

A finite category: finitely many objects, and finitely many arrows between them. The first is Enumerable, the second does not follow from it, and the ends below need both.

Instances

Instances details
(Enumerable k, Finitary (Hom k)) => FiniteCat k Source Github # 
Instance details

Defined in Proarrow.Category.Enriched.Finitary

type EndKey = (Natural, Natural, Natural, Natural, Natural) Source Github #

One point of the domain of an end at a/b, as a key into a tabulated family: an object pair and, there, an arrow into a, an arrow out of b and an element of p.

endDomain :: forall {j} {k} p (a :: k) (b :: j) r. (Finitary p, FiniteCat j, FiniteCat k, Ob a, Ob b) => (forall (c :: k) (d :: j). (Ob c, Ob d) => (c ~> a) -> (b ~> d) -> p c d -> r) -> [r] Source Github #

Visit every point of that domain, in one fixed order. Everything that tabulates or reads a family walks it with this, so that a family is a list of values in this order.

endKey :: forall {j} {k} (c :: k) (d :: j) p (a :: k) (b :: j). (FiniteCat j, FiniteCat k, Finitary p, Ob c, Ob d) => (c ~> a) -> (b ~> d) -> p c d -> EndKey Source Github #

endPositions :: forall {j} {k} (p :: j +-> k) (a :: k) (b :: j). (Finitary p, FiniteCat j, FiniteCat k, Ob a, Ob b) => Map EndKey Int Source Github #

Where each key sits in a tabulated family.

endLaws :: forall {j} {k} (p :: j +-> k) (q :: j +-> k) (a :: k) (b :: j). (Finitary p, Finitary q, FiniteCat j, FiniteCat k, Ob a, Ob b) => [(EndKey, EndKey, [Natural])] Source Github #

The naturality conditions on a family: at each pair of arrows g, h, the point a given point is carried to, and the transport of q's indices that the family must commute with. The transport is a table rather than a function, so that q is enumerated once per condition.

endElements :: [[v]] -> [(Int, Int, v -> v -> Bool)] -> [[v]] Source Github #

Enumerate an end by brute force: every way of choosing a value at each point of the domain, kept when it satisfies every condition. The candidate space is the product of the choices over the whole domain, so this is only ever run on small categories.

expElements :: forall {j} {k} (p :: j +-> k) (q :: j +-> k) (a :: k) (b :: j). (Finitary p, Finitary q, FiniteCat j, FiniteCat k, Ob a, Ob b) => [[Natural]] Source Github #

Every natural family, as its list of q-indices in endDomain order.

atKey :: forall {j} {k} (p :: j +-> k) (a :: k) (b :: j) v. (Finitary p, FiniteCat j, FiniteCat k, Ob a, Ob b) => [v] -> EndKey -> v Source Github #

Read a tabulated family back as a function on the keys.

familyIndex :: Eq v => String -> [[v]] -> [v] -> Natural Source Github #

Which of the enumerated families a tabulated one is.

The subobject classifier

sieveElements :: forall {j} {k} (a :: k) (b :: j). (FiniteCat j, FiniteCat k, Ob a, Ob b) => [[Bool]] Source Github #

Every sieve, as the points of the representable it contains, in endDomain order: all subsets, kept when closed. The representable at a/b is the domain of the end at the terminal object, and the closure conditions are that end's naturality conditions read as implications.

sieveAt :: forall {j} {k} (a :: k) (b :: j). (FiniteCat j, FiniteCat k, Ob a, Ob b) => [Bool] -> Sieve a b Source Github #

A tabulated sieve as a sieve.