proarrow
Safe HaskellNone
LanguageGHC2024

Proarrow.Category.Enriched.Finitary.Topos

Description

The topos of finitary profunctors. Everything built on the numbering in Proarrow.Category.Enriched.Finitary: a hom-set is an initial segment of the naturals, so a subobject or a quotient of one is a table of indices, and a computation can produce such a table and reify it into a fresh object. That is Reindex, and it gives equalizers, coequalizers, pullbacks, pushouts and epi-mono factorization.

The internal hom and the subobject classifier are the same construction one level up: both are ends, enumerated by choosing a value at every point of a domain and keeping the choices that commute with the action. Neither count is a formula in the sizes it is built from -- they depend on how the arrows of j and k compose -- which is exactly why the numbering is a value.

The punchline is ElementaryTopos (PROD (FINITARY j k)) at the end. PROD is what makes the tensor the product rather than Day convolution, as it does for j +-> k itself.

Synopsis

Documentation

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 #

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.Topos

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

Defined in Proarrow.Category.Enriched.Finitary.Topos

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.Topos

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

Defined in Proarrow.Category.Enriched.Finitary.Topos

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.Topos

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.Topos

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

Natural transformations, enumerated

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

Enumerate a set of families by brute force: every way of choosing a value at each point of the domain, kept when it satisfies every condition. A condition is checked as soon as both of its points have been chosen, so a violation prunes the whole subtree of completions rather than rejecting each of them in turn -- which is what keeps the candidate space from being the full product. Families come out in the same order as sequence choices would give them: the earliest point varies slowest.

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

Which of the enumerated families a tabulated one is.

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

One point of the domain of the end ∫ Set(p c d, q c d) whose elements are the natural transformations p -> q: an object pair and an element of p there. Every end below is one of these: the internal hom only changes the weight p, and the subobject classifier also changes what the conditions are read as. So this is the single enumeration the topos is built on.

natDomain :: (Finitary p, FiniteCat j, FiniteCat k) => (forall (a :: k) (b :: j). (Ob a, Ob b) => p a b -> r) -> [r] Source Github #

Visit every point of that domain, in one fixed order.

natKey :: forall {j} {k} (a :: k) (b :: j) p. (FiniteCat j, FiniteCat k, Finitary p, Ob a, Ob b) => p a b -> NatKey Source Github #

natPositions :: forall {j} {k} (p :: j +-> k). (Finitary p, FiniteCat j, FiniteCat k) => Map NatKey Int Source Github #

Where each point of the domain sits in a tabulated family. This is the same for every family over a given weight, so bind it once outside a loop over them.

atNatKey :: Map NatKey Int -> [v] -> NatKey -> v Source Github #

Read a tabulated family back as a function on the points, given those positions.

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

Every natural transformation p -> q, as its list of q-indices in natDomain order. Naturality is the only condition: the value at x and the value at dimap g h x must agree after transport.

natConditions :: forall {j} {k} (p :: j +-> k) (q :: j +-> k) v. (Finitary p, Finitary q, FiniteCat j, FiniteCat k) => ([Natural] -> v -> v -> Bool) -> [(Int, Int, v -> v -> Bool)] Source Github #

The conditions as positions in a tabulated family, with q's transport handed to the relation. Only the internal hom reads that transport; the sieves below ignore it, and pass TerminalProfunctor for q so that computing it costs nothing.

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

The naturality conditions on a transformation. As in closedUnder, dimap g h is lmap g . rmap h, so commuting with the two whiskerings separately is commuting with the action: two walks over three objects rather than one over four, and the transport table depends on the arrow alone rather than on each element.

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

A natural transformation as its table of q-indices, in natDomain order. That is everything there is to see of one, so it serves for both comparing and showing.

natTransformations :: forall {j} {k} (p :: j +-> k) (q :: j +-> k). (Finitary p, Finitary q, FiniteCat j, FiniteCat k) => [FIN p ~> FIN q] Source Github #

Every natural transformation p -> q, as an arrow of FINITARY j k. This is what makes the category of finitary profunctors testable: its hom-sets are enumerable, so a generator can pick from them, where in general a natural transformation is not something one can generate.

natAt :: forall {j} {k} (p :: j +-> k) (q :: j +-> k). (Finitary p, Finitary q, FiniteCat j, FiniteCat k) => Map NatKey Int -> [Natural] -> FIN p ~> FIN q Source Github #

A tabulated transformation as an arrow.

type ExpWeight (p :: j +-> k) (a :: k) (b :: j) = Yo a ('OP b) :*: p Source Github #

What the internal hom at a/b is a set of natural transformations out of. An element of it over c/d is an arrow into a, an arrow out of b and an element of p -- exactly the three arguments an Exp takes.

expAt :: 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) => Map NatKey Int -> [Natural] -> (p :~>: q) a b Source Github #

A tabulated family as an element of the internal hom.

The subobject classifier

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

Every sieve at a/b, as the points of Yo a (OP b) it contains, in natDomain order: all subsets, kept when closed. This is the same end again, at the weight Yo a (OP b) and valued in booleans, with the naturality conditions read as implications rather than equations.

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

A sieve as the tabulation of its membership, in natDomain order -- the inverse of sieveAt.

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

A tabulated sieve as a sieve.

Orphan instances

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

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 #

(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 transformations out of ExpWeight, 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

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 #

(FiniteCat j, FiniteCat k) => Closed (PROD (FINITARY j k)) Source Github #

Finitary profunctors are cartesian closed. The PROD wrapper is what makes the tensor the product rather than Day convolution, exactly as it does for j +-> k itself.

Instance details

Methods

withObExp :: forall (a :: PROD (FINITARY j k)) (b :: PROD (FINITARY j k)) r. (Ob a, Ob b) => (Ob (a ~~> b) => r) -> r Source Github #

curry :: forall (a :: PROD (FINITARY j k)) (b :: PROD (FINITARY j k)) (c :: PROD (FINITARY j k)). (Ob a, Ob b) => ((a ** b) ~> c) -> a ~> (b ~~> c) Source Github #

apply :: forall (a :: PROD (FINITARY j k)) (b :: PROD (FINITARY j k)). (Ob a, Ob b) => ((a ~~> b) ** a) ~> b Source Github #

(^^^) :: forall (a :: PROD (FINITARY j k)) (b :: PROD (FINITARY j k)) (x :: PROD (FINITARY j k)) (y :: PROD (FINITARY j k)). (b ~> y) -> (x ~> a) -> (a ~~> b) ~> (x ~~> y) Source Github #

(FiniteCat j, FiniteCat k) => ElementaryTopos (PROD (FINITARY j k)) Source Github #

Finitary profunctors between finite categories form an elementary topos: finite limits and colimits, cartesian closed, a subobject classifier, and image factorization.

Instance details

(FiniteCat j, FiniteCat k) => HasSubobjectClassifier (PROD (FINITARY j k)) Source Github #

The subobject classifier is the profunctor of sieves, and an arrow classifies its graph: the sieve of all the ways an element of p and one of q can be carried to a matching pair.

Instance details

Associated Types

type Omega 
Instance details

Defined in Proarrow.Category.Enriched.Finitary.Topos

type Omega = 'PR ('SUB (Sieve :: k -> j -> Type) :: SUBCAT (Finitary :: (j +-> k) -> Constraint))

Methods

true :: (TerminalObject :: PROD (FINITARY j k)) ~> (Omega :: PROD (FINITARY j k)) Source Github #

classifyGraph :: forall (a :: PROD (FINITARY j k)) (b :: PROD (FINITARY j k)). (a ~> b) -> (a && b) ~> (Omega :: PROD (FINITARY j k)) Source Github #

(Enumerable j, Enumerable k) => HasEpiMonoFactorization (FINITARY j k) Source Github #

The image of a natural transformation is the equalizer of its cokernel pair.

Instance details

Methods

factorize :: forall (a :: FINITARY j k) (b :: FINITARY j k). (a ~> b) -> (Hom (FINITARY j k) :.: Hom (FINITARY j k)) a b Source Github #

(CategoryOf j, CategoryOf k) => HasBinaryCoproducts (FINITARY j k) Source Github # 
Instance details

Methods

withObCoprod :: forall (a :: FINITARY j k) (b :: FINITARY j k) r. (Ob a, Ob b) => (Ob (a || b) => r) -> r Source Github #

lft :: forall (a :: FINITARY j k) (b :: FINITARY j k). (Ob a, Ob b) => a ~> (a || b) Source Github #

rgt :: forall (a :: FINITARY j k) (b :: FINITARY j k). (Ob a, Ob b) => b ~> (a || b) Source Github #

(|||) :: forall (x :: FINITARY j k) (a :: FINITARY j k) (y :: FINITARY j k). (x ~> a) -> (y ~> a) -> (x || y) ~> a Source Github #

(+++) :: forall (a :: FINITARY j k) (b :: FINITARY j k) (x :: FINITARY j k) (y :: FINITARY j k). (a ~> x) -> (b ~> y) -> (a || b) ~> (x || y) Source Github #

(Enumerable j, Enumerable k) => HasCoequalizers (FINITARY j k) Source Github #

Coequalizers: at each pair of objects, partition the indices by the equivalence relation the two natural transformations generate, and reify the table. Naturality makes the partition a congruence, so the quotient is again a profunctor.

Instance details

Methods

coequalize :: forall (a :: FINITARY j k) (b :: FINITARY j k) r. (a ~> b) -> (a ~> b) -> (forall (c :: FINITARY j k). (b ~> c) -> r) -> r Source Github #

factorCoequalizer :: forall (c :: FINITARY j k) (x :: FINITARY j k) (c' :: FINITARY j k). (x ~> c) -> (x ~> c') -> c ~> c' Source Github #

(CategoryOf j, CategoryOf k) => HasInitialObject (FINITARY j k) Source Github # 
Instance details

Associated Types

type InitialObject 
Instance details

Defined in Proarrow.Category.Enriched.Finitary.Topos

type InitialObject = FIN (InitialProfunctor :: k -> j -> Type)

Methods

initiate :: forall (a :: FINITARY j k). Ob a => (InitialObject :: FINITARY j k) ~> a Source Github #

(Enumerable j, Enumerable k) => HasPushouts (FINITARY j k) Source Github # 
Instance details

Methods

pushout :: forall (o :: FINITARY j k) (a :: FINITARY j k) (b :: FINITARY j k) r. (o ~> a) -> (o ~> b) -> (forall (p :: FINITARY j k). (a ~> p) -> (b ~> p) -> r) -> r Source Github #

factorPushout :: forall (a :: FINITARY j k) (b :: FINITARY j k) (p :: FINITARY j k) (q :: FINITARY j k). (a ~> p) -> (b ~> p) -> (a ~> q) -> (b ~> q) -> p ~> q Source Github #

(CategoryOf j, CategoryOf k) => HasBinaryProducts (FINITARY j k) Source Github # 
Instance details

Methods

withObProd :: forall (a :: FINITARY j k) (b :: FINITARY j k) r. (Ob a, Ob b) => (Ob (a && b) => r) -> r Source Github #

fst :: forall (a :: FINITARY j k) (b :: FINITARY j k). (Ob a, Ob b) => (a && b) ~> a Source Github #

snd :: forall (a :: FINITARY j k) (b :: FINITARY j k). (Ob a, Ob b) => (a && b) ~> b Source Github #

(&&&) :: forall (a :: FINITARY j k) (x :: FINITARY j k) (y :: FINITARY j k). (a ~> x) -> (a ~> y) -> a ~> (x && y) Source Github #

(***) :: forall (a :: FINITARY j k) (b :: FINITARY j k) (x :: FINITARY j k) (y :: FINITARY j k). (a ~> x) -> (b ~> y) -> (a && b) ~> (x && y) Source Github #

(Enumerable j, Enumerable k) => HasEqualizers (FINITARY j k) Source Github #

Equalizers of finitary profunctors between finite categories: at each pair of objects, keep the indices on which the two natural transformations agree, and reify the table.

Instance details

Methods

equalize :: forall (a :: FINITARY j k) (b :: FINITARY j k) r. (a ~> b) -> (a ~> b) -> (forall (e :: FINITARY j k). (e ~> a) -> r) -> r Source Github #

factorEqualizer :: forall (e :: FINITARY j k) (x :: FINITARY j k) (e' :: FINITARY j k). (e ~> x) -> (e' ~> x) -> e' ~> e Source Github #

(Enumerable j, Enumerable k) => HasPullbacks (FINITARY j k) Source Github #

Pullbacks are equalizers of products, and pushouts coequalizers of coproducts, all of which finitary profunctors have.

Instance details

Methods

pullback :: forall (o :: FINITARY j k) (a :: FINITARY j k) (b :: FINITARY j k) r. (a ~> o) -> (b ~> o) -> (forall (p :: FINITARY j k). (p ~> a) -> (p ~> b) -> r) -> r Source Github #

factorPullback :: forall (a :: FINITARY j k) (b :: FINITARY j k) (p :: FINITARY j k) (q :: FINITARY j k). (p ~> a) -> (p ~> b) -> (q ~> a) -> (q ~> b) -> q ~> p Source Github #

(CategoryOf j, CategoryOf k) => HasTerminalObject (FINITARY j k) Source Github # 
Instance details

Associated Types

type TerminalObject 
Instance details

Defined in Proarrow.Category.Enriched.Finitary.Topos

Methods

terminate :: forall (a :: FINITARY j k). Ob a => a ~> (TerminalObject :: FINITARY j k) Source Github #

(FiniteCat j, FiniteCat k) => Finitary (Sub (Prof :: (j +-> k) -> (j +-> k) -> Type) :: SUBCAT (Finitary :: (j +-> k) -> Constraint) -> SUBCAT (Finitary :: (j +-> k) -> Constraint) -> Type) Source Github #

FINITARY j k is locally finite: its own hom-profunctor is finitary, by natTransformations. So the numbering above is not just a testing device, it is the skeleton of each hom-set, and the Finitary laws apply to it like to any other. (It is not a FiniteCat -- there are unboundedly many finitary profunctors -- which is exactly the difference between finite and locally finite.)

Instance details

Methods

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

toIndex :: forall (a :: FINITARY j k) (b :: FINITARY j k). (Ob a, Ob b) => Sub (Prof :: (j +-> k) -> (j +-> k) -> Type) a b -> Natural Source Github #

fromIndex :: forall (a :: FINITARY j k) (b :: FINITARY j k). (Ob a, Ob b) => Natural -> Sub (Prof :: (j +-> k) -> (j +-> k) -> Type) a b Source Github #

elements :: forall (a :: FINITARY j k) (b :: FINITARY j k). (Ob a, Ob b) => [Sub (Prof :: (j +-> k) -> (j +-> k) -> Type) a b] Source Github #