| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Proarrow.Category.Enriched.Thin.Composition
Description
Composition of thin profunctors. In general the arrows of a composite p are an
existential over the objects of the middle category, which a :.: qConstraint cannot express. This
module dispatches on the shape of the legs, so that the single ThinProfunctor instance for
:.: never overlaps with anything: a representable leg pins the middle object down, and
otherwise the middle category is searched (Search), which needs it to be Enumerable and both
legs to be DecidableProfunctors. Composites are themselves decidable, so searches nest.
Synopsis
- data ThinComp
- type family ThinCompStrategy (p :: j +-> k) (q :: i +-> j) :: ThinComp where ...
- class (ThinProfunctor p, ThinProfunctor q) => ComposeThin (s :: ThinComp) (p :: j +-> k) (q :: i +-> j) where
- type HasArrowComp (s :: ThinComp) (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i)
- arrComp :: forall (a :: k) (c :: i). (Ob a, Ob c, HasArrowComp s p q a c) => (p :.: q) a c
- withArrComp :: forall (a :: k) (c :: i) r. (p :.: q) a c -> ((HasArrowComp s p q a c, Ob a, Ob c) => r) -> r
- type family MatVec v (bs :: [j]) (ws :: [v]) (p :: j +-> k) (a :: k) :: v where ...
- type family MatCol v (bs :: [j]) (q :: i +-> j) (c :: i) :: [v] where ...
- type MatMul v (bs :: [j]) (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i) = MatVec v bs (MatCol v bs q c) p a
- type Search (bs :: [j]) (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i) = MatMul BOOL bs p q a c
- search :: forall {i} {j} {k} (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i) (bs :: [j]). (DecidableProfunctor p, DecidableProfunctor q, Enumerable j, Ob a, Ob c) => IndexedList bs -> Decision (p :.: q) a c (Search bs p q a c)
- found :: forall {i} {j} {k} p q (a :: k) (b :: j) (c :: i) r. (DecidableProfunctor p, DecidableProfunctor q, Enumerable j) => p a b -> q b c -> ((Search (Objects j) p q a c ~ 'TRU, Ob a, Ob c) => r) -> r
- class ComposeThin s p q => DecideComp (s :: ThinComp) (p :: j +-> k) (q :: i +-> j) where
- data Walk (n :: Nat) (p :: k +-> k) (a :: k) (b :: k) where
- type family Walks v (n :: Nat) (p :: k +-> k) (a :: k) (b :: k) :: v where ...
- type family WalkRow v (n :: Nat) (p :: k +-> k) (b :: k) :: [v] where ...
- type family NextRow v (as :: [k]) (row :: [v]) (p :: k +-> k) (b :: k) :: [v] where ...
- type Closure (p :: k +-> k) = Walk (Length (Objects k)) p
- type Closing v (n :: Nat) (p :: k +-> k) = (SNatI n, Quantale v, EnrichedProfunctor v p, Enriched v k, Enumerable k)
- data GradedWalk v (n :: Nat) (p :: k +-> k) (d :: v) (a :: k) (b :: k) where
- DoneAt :: forall {k} v (n :: Nat) (p :: k +-> k) (d :: v) (a :: k) (b :: k). (Ob a, Ob b) => (d ~> HomObj v a b) -> GradedWalk v n p d a b
- StepAt :: forall {k} v (n1 :: Nat) (p :: k +-> k) (a :: k) (c :: k) (b :: k) (e :: v) (d1 :: v). (Ob a, Ob b, Ob c, Ob e, Ob d1) => (e ~> ProObj v p a c) -> GradedWalk v n1 p d1 c b -> GradedWalk v ('S n1) p (e ** d1) a b
- data Row v (n :: Nat) (p :: k +-> k) (b :: k) (as :: [k]) (ws :: [v]) where
- row :: forall {k} v (n :: Nat) (p :: k +-> k) (b :: k). (Closing v n p, Ob b) => Row v n p b (Objects k) (WalkRow v n p b)
- withObRow :: forall {k} (a :: k) v (n :: Nat) (p :: k +-> k) (b :: k) (cs :: [k]) (ws :: [v]) r. Member a cs -> Row v n p b cs ws -> (Ob (Walks v n p a b) => r) -> r
- withObWalks :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (b :: k) r. (Closing v n p, Ob a, Ob b) => (Ob (Walks v n p a b) => r) -> r
- withObStep :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (c :: k) (b :: k) r. (Closing v n p, Ob a, Ob c, Ob (Walks v n p c b)) => ((Ob (ProObj v p a c), Ob (ProObj v p a c ** Walks v n p c b)) => r) -> r
- withObMatVec :: forall {k} (a :: k) v (n :: Nat) (p :: k +-> k) (b :: k) (cs :: [k]) (ws :: [v]) r. (Closing v n p, Ob a) => Row v n p b cs ws -> (Ob (MatVec v cs ws p a) => r) -> r
- underlyingAt :: forall {k} v (n :: Nat) (p :: k +-> k) (d :: v) (a :: k) (b :: k). Closing v n p => GradedWalk v n p d a b -> d ~> Walks v n p a b
- stepAt :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (c :: k) (b :: k) (e :: v) (d :: v). (Closing v n p, Ob a, Ob b, Ob c) => (e ~> ProObj v p a c) -> (d ~> Walks v n p c b) -> (e ** d) ~> Walks v ('S n) p a b
- inject :: forall {k} (a :: k) v (n :: Nat) (p :: k +-> k) (b :: k) (c :: k) (cs :: [k]) (ws :: [v]). (Closing v n p, Ob a, Ob c, Ob (Walks v n p c b)) => Row v n p b cs ws -> Member c cs -> (ProObj v p a c ** Walks v n p c b) ~> MatVec v cs ws p a
- underlyingWalk :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (b :: k). Closing v n p => Walk n p a b -> (Unit :: v) ~> Walks v n p a b
- shortest :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (b :: k). (Closing v n p, Ob a, Ob b) => GradedWalk v n p (Walks v n p a b) a b
- best :: forall {k} (a :: k) v (n :: Nat) (p :: k +-> k) (b :: k) (cs :: [k]) (ws :: [v]). (Closing v n p, Ob a, Ob b) => Row v n p b cs ws -> GradedWalk v ('S n) p (MatVec v cs ws p a) a b
- walkAt :: forall {k} v (n :: Nat) (p :: k +-> k) (d :: v) (a :: k) (b :: k). Closing v n p => ((Unit :: v) ~> d) -> GradedWalk v n p d a b -> Walk n p a b
- checkedWalk :: forall {k} v (n :: Nat) (p :: k +-> k) (x :: k) (y :: k) (a :: k) (b :: k) (c :: k) (d :: k). (Closing v n p, Ob x, Ob y, Ob a, Ob b, Ob c, Ob d) => (HomObj v x y ** Walks v n p a b) ~> Walks v n p c d
Documentation
How a composite p of thin profunctors decides its arrows. In general
:.: q is an existential over the objects HasArrow (p :.: q) a cb of the middle category
(the join ⋁_b p(a,b) ∧ q(b,c) in the enriching Bool), which a Constraint cannot express.
But when the left leg is corepresented (f a ≤ b, a companion) or the right leg represented
(b ≤ g c, a conjoint) the middle object is determined and the existential collapses to a
substitution: q (f a) c, respectively p a (g c). The strategy is chosen by the closed
family ThinCompStrategy from the shape of the legs, so that the one ThinProfunctor
instance for :.: never overlaps with anything; a composite of two non-representable legs
falls back to BySearch, which enumerates the middle category and decides both legs at each
object (Search). (Star and
Costar have the same two shapes, but functors between thin
kinds are written as FunctorForReps here, so Rep/Corep cover them.)
type family ThinCompStrategy (p :: j +-> k) (q :: i +-> j) :: ThinComp where ... Source Github #
Equations
| ThinCompStrategy (RepCostar p :: k -> j -> Type) (q :: i +-> j) = 'ByLeft | |
| ThinCompStrategy (Corep f :: k -> j -> Type) (q :: i +-> j) = 'ByLeft | |
| ThinCompStrategy (p :: j +-> k) (Rep g :: j -> i -> Type) = 'ByRight | |
| ThinCompStrategy (p :: j +-> k) (CorepStar q :: j -> i -> Type) = 'ByRight | |
| ThinCompStrategy (p :: j +-> k) (q :: i +-> j) = 'BySearch |
class (ThinProfunctor p, ThinProfunctor q) => ComposeThin (s :: ThinComp) (p :: j +-> k) (q :: i +-> j) where Source Github #
Associated Types
type HasArrowComp (s :: ThinComp) (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i) Source Github #
Methods
arrComp :: forall (a :: k) (c :: i). (Ob a, Ob c, HasArrowComp s p q a c) => (p :.: q) a c Source Github #
withArrComp :: forall (a :: k) (c :: i) r. (p :.: q) a c -> ((HasArrowComp s p q a c, Ob a, Ob c) => r) -> r Source Github #
Instances
type family MatVec v (bs :: [j]) (ws :: [v]) (p :: j +-> k) (a :: k) :: v where ... Source Github #
The join ⋁_b p(a,b) ⊗ w_b of an edge out of a with whatever the vector holds for where
that edge lands: one row of the matrix of p against a vector, over the given middle objects.
The objects and the vector are walked in step, so ws is always the vector cut down to bs.
This is the module's one join. Composing two profunctors multiplies by a column read off the
right-hand one (MatMul); the closure multiplies by the previous iterate (Walks), which is
what lets that iterate be computed once instead of once per pair.
type family MatCol v (bs :: [j]) (q :: i +-> j) (c :: i) :: [v] where ... Source Github #
One column of the matrix of an enriched profunctor: its hom-objects into c, over the given
objects.
type MatMul v (bs :: [j]) (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i) = MatVec v bs (MatCol v bs q c) p a Source Github #
Matrix multiplication over a list of middle objects, ⋁_b p(a,b) ⊗ q(b,c): the hom-object of
the composite of two enriched profunctors when the middle category is enumerable. The type-level
twin of Proarrow.Category.Instance.FinRel.
type Search (bs :: [j]) (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i) = MatMul BOOL bs p q a c Source Github #
search :: forall {i} {j} {k} (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i) (bs :: [j]). (DecidableProfunctor p, DecidableProfunctor q, Enumerable j, Ob a, Ob c) => IndexedList bs -> Decision (p :.: q) a c (Search bs p q a c) Source Github #
Walk the object list deciding both legs at each object; a hit is the composite, and a miss reduces the search to the tail of the list.
found :: forall {i} {j} {k} p q (a :: k) (b :: j) (c :: i) r. (DecidableProfunctor p, DecidableProfunctor q, Enumerable j) => p a b -> q b c -> ((Search (Objects j) p q a c ~ 'TRU, Ob a, Ob c) => r) -> r Source Github #
An actual composite proves the search succeeds: locate its middle object in the list, then at
that position both legs hold and the disjunction is TRU whatever the rest of the list says.
class ComposeThin s p q => DecideComp (s :: ThinComp) (p :: j +-> k) (q :: i +-> j) where Source Github #
Whether a composite decides its arrows, by the same strategy as ComposeThin: a representable
leg is substituted away and the other leg decided, a search is decided by running it. This is
what makes composites decidable in turn, so that searches can nest.
Associated Types
type HoldsComp (s :: ThinComp) (p :: j +-> k) (q :: i +-> j) (a :: k) (c :: i) :: BOOL Source Github #
Methods
decideComp :: forall (a :: k) (c :: i). (Ob a, Ob c) => Decision (p :.: q) a c (HoldsComp s p q a c) Source Github #
toHoldsComp :: forall (a :: k) (c :: i) r. (p :.: q) a c -> ((HoldsComp s p q a c ~ 'TRU, Ob a, Ob c) => r) -> r Source Github #
Instances
Closure: walks along a graph, in any enriching category
data Walk (n :: Nat) (p :: k +-> k) (a :: k) (b :: k) where Source Github #
A walk of at most n steps along p, finished by an arrow of the base category. Its
hom-object in any enriching category is Walks: at BOOL the truth of the walk, decided with
the path as witness; at COST the shortest distance.
Constructors
| Done :: forall {k} (n :: Nat) (p :: k +-> k) (a :: k) (b :: k). (a ~> b) -> Walk n p a b | |
| Step :: forall {k} (n1 :: Nat) (p :: k +-> k) (a :: k) (c :: k) (b :: k). p a c -> Walk n1 p c b -> Walk ('S n1) p a b |
Instances
| (SNatI n, EnrichedProfunctor COST p, Enriched COST k, Enumerable k) => EnrichedProfunctor COST (Walk n p :: k -> k -> Type) Source Github # | Walks along a |
Defined in Proarrow.Category.Enriched.Thin.Composition Methods withProObj :: forall (a :: k) (b :: k) r. (Ob a, Ob b) => (Ob (ProObj COST (Walk n p) a b) => r) -> r Source Github # underlying :: forall (a :: k) (b :: k). Walk n p a b -> (Unit :: COST) ~> ProObj COST (Walk n p) a b Source Github # enriched :: forall (a :: k) (b :: k). (Ob a, Ob b) => ((Unit :: COST) ~> ProObj COST (Walk n p) a b) -> Walk n p a b Source Github # rmap :: forall (a :: k) (b :: k) (c :: k). (Ob a, Ob b, Ob c) => (HomObj COST b c ** ProObj COST (Walk n p) a b) ~> ProObj COST (Walk n p) a c Source Github # lmap :: forall (a :: k) (b :: k) (c :: k). (Ob a, Ob b, Ob c) => (HomObj COST c a ** ProObj COST (Walk n p) a b) ~> ProObj COST (Walk n p) c b Source Github # | |
| (SNatI n, DecidableProfunctor p, Decidable k, Enumerable k) => DecidableProfunctor (Walk n p :: k -> k -> Type) Source Github # | Reachability: the truth of a walk is its hom-object in |
Defined in Proarrow.Category.Enriched.Thin.Composition | |
| (SNatI n, DecidableProfunctor p, Decidable k, Enumerable k) => ThinProfunctor (Walk n p :: k -> k -> Type) Source Github # | |
| Profunctor p => Profunctor (Walk n p :: j -> j -> Type) Source Github # | |
Defined in Proarrow.Category.Enriched.Thin.Composition Methods dimap :: forall (c :: j) (a :: j) (b :: j) (d :: j). (c ~> a) -> (b ~> d) -> Walk n p a b -> Walk n p c d Source Github # lmap :: forall (c :: j) (a :: j) (b :: j). (c ~> a) -> Walk n p a b -> Walk n p c b Source Github # rmap :: forall (b :: j) (d :: j) (a :: j). (b ~> d) -> Walk n p a b -> Walk n p a d Source Github # (\\) :: forall (a :: j) (b :: j) r. ((Ob a, Ob b) => r) -> Walk n p a b -> r Source Github # | |
| type ProObj COST (Walk n p :: k -> k -> Type) (a :: k) (b :: k) Source Github # | |
| type HasArrow (Walk n p :: k -> k -> Type) (a :: k) (b :: k) Source Github # | |
| type Holds (Walk n p :: k -> k -> Type) (a :: k) (b :: k) Source Github # | |
type family Walks v (n :: Nat) (p :: k +-> k) (a :: k) (b :: k) :: v where ... Source Github #
The hom-object of a walk of at most n steps, in any enriching category v: an arrow of the
base, or an edge followed by one entry of the previous iterate (WalkRow). Naming the whole
iterate rather than a shorter walk per pair is what keeps this affordable. At BOOL it is the
truth of Walk, at COST the shortest distance, computed by GHC at the type level and by row
at the value level.
type family WalkRow v (n :: Nat) (p :: k +-> k) (b :: k) :: [v] where ... Source Github #
The n-th iterate of the fixed point for a fixed target b: the hom-object of the walks of at
most n steps into b, one entry per object, in the order of Objects. It starts as the column
of the base hom-objects, there being no step to take yet, and grows by NextRow.
Each iterate is written in terms of the whole previous one, so it is computed once and read by every object. That sharing is what makes the fixed point affordable: the work is the number of steps times the square of the number of objects, where a recursion per pair of objects would instead cost the number of objects to the power of the number of steps.
type family NextRow v (as :: [k]) (row :: [v]) (p :: k +-> k) (b :: k) :: [v] where ... Source Github #
One more step, taken for every object at once: an arrow of the base, or an edge into the
previous iterate (MatVec).
type Closure (p :: k +-> k) = Walk (Length (Objects k)) p Source Github #
The Kleene closure of p: walks of at most as many steps as there are objects, which is all
of them, since a shortest walk never revisits an object. It is the free category on the graph
p in whatever p is enriched in: at BOOL the reflexive-transitive closure of a relation, with
the path as witness (decide); at COST the free Lawvere metric space, with the shortest
distances (withProObj) and the shortest paths (shortest).
Graded walks
type Closing v (n :: Nat) (p :: k +-> k) = (SNatI n, Quantale v, EnrichedProfunctor v p, Enriched v k, Enumerable k) Source Github #
What the closure needs of its ingredients: a quantale to compute in, an enriched graph over an enumerable enriched base, and a known number of steps.
data GradedWalk v (n :: Nat) (p :: k +-> k) (d :: v) (a :: k) (b :: k) where Source Github #
A walk graded by its cost: each piece comes with a budget, an arrow of v into the piece's
hom-object, and the grade of the walk is the tensor of the budgets. A walk at grade d is a
generalised element of the closure, d ~> (Walks v n p a bunderlyingAt), and shortest
produces one at grade exactly the hom-object.
Constructors
| DoneAt :: forall {k} v (n :: Nat) (p :: k +-> k) (d :: v) (a :: k) (b :: k). (Ob a, Ob b) => (d ~> HomObj v a b) -> GradedWalk v n p d a b | |
| StepAt :: forall {k} v (n1 :: Nat) (p :: k +-> k) (a :: k) (c :: k) (b :: k) (e :: v) (d1 :: v). (Ob a, Ob b, Ob c, Ob e, Ob d1) => (e ~> ProObj v p a c) -> GradedWalk v n1 p d1 c b -> GradedWalk v ('S n1) p (e ** d1) a b |
data Row v (n :: Nat) (p :: k +-> k) (b :: k) (as :: [k]) (ws :: [v]) where Source Github #
The n-th iterate reflected to the value level: every object paired with its own entry, which
is exactly the hom-object of the walks from it. row builds one and everything that needs a
shorter walk reads it, so the value level shares its work the same way the type level does.
Constructors
| RNil :: forall {k} v (n :: Nat) (p :: k +-> k) (b :: k). Row v n p b ('[] :: [k]) ('[] :: [v]) | |
| RCons :: forall {k} (a :: k) (as1 :: [k]) v (ws1 :: [v]) (n :: Nat) (p :: k +-> k) (b :: k). (Ob a, Ob (Walks v n p a b)) => Row v n p b as1 ws1 -> Row v n p b (a ': as1) (Walks v n p a b ': ws1) |
row :: forall {k} v (n :: Nat) (p :: k +-> k) (b :: k). (Closing v n p, Ob b) => Row v n p b (Objects k) (WalkRow v n p b) Source Github #
The n-th iterate: the base hom-objects, then one more step for every object at a time.
withObRow :: forall {k} (a :: k) v (n :: Nat) (p :: k +-> k) (b :: k) (cs :: [k]) (ws :: [v]) r. Member a cs -> Row v n p b cs ws -> (Ob (Walks v n p a b) => r) -> r Source Github #
Object evidence for the hom-object of a walk: read the object's own entry out of an iterate.
withObWalks :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (b :: k) r. (Closing v n p, Ob a, Ob b) => (Ob (Walks v n p a b) => r) -> r Source Github #
The same, for a caller that is not already holding the iterate.
withObStep :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (c :: k) (b :: k) r. (Closing v n p, Ob a, Ob c, Ob (Walks v n p c b)) => ((Ob (ProObj v p a c), Ob (ProObj v p a c ** Walks v n p c b)) => r) -> r Source Github #
Object evidence for one summand of MatVec: an edge and its tensor with the entry after it.
withObMatVec :: forall {k} (a :: k) v (n :: Nat) (p :: k +-> k) (b :: k) (cs :: [k]) (ws :: [v]) r. (Closing v n p, Ob a) => Row v n p b cs ws -> (Ob (MatVec v cs ws p a) => r) -> r Source Github #
Object evidence for the join over the given middle objects.
underlyingAt :: forall {k} v (n :: Nat) (p :: k +-> k) (d :: v) (a :: k) (b :: k). Closing v n p => GradedWalk v n p d a b -> d ~> Walks v n p a b Source Github #
A graded walk is a generalised element of the closure: inject it into the join at its middle object.
stepAt :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (c :: k) (b :: k) (e :: v) (d :: v). (Closing v n p, Ob a, Ob b, Ob c) => (e ~> ProObj v p a c) -> (d ~> Walks v n p c b) -> (e ** d) ~> Walks v ('S n) p a b Source Github #
An edge with a budget, followed by a generalised element of the shorter walks.
inject :: forall {k} (a :: k) v (n :: Nat) (p :: k +-> k) (b :: k) (c :: k) (cs :: [k]) (ws :: [v]). (Closing v n p, Ob a, Ob c, Ob (Walks v n p c b)) => Row v n p b cs ws -> Member c cs -> (ProObj v p a c ** Walks v n p c b) ~> MatVec v cs ws p a Source Github #
The injection of one summand into the join over the middle objects.
underlyingWalk :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (b :: k). Closing v n p => Walk n p a b -> (Unit :: v) ~> Walks v n p a b Source Github #
A walk of pieces at the unit, as a generalised element at the unit.
shortest :: forall {k} v (n :: Nat) (p :: k +-> k) (a :: k) (b :: k). (Closing v n p, Ob a, Ob b) => GradedWalk v n p (Walks v n p a b) a b Source Github #
The best walk between two points, graded by exactly their hom-object: a shortest path at
COST, a path or the absence of one at BOOL. At every join it keeps the summand the join is
(minIs); a pair no walk connects gets the empty walk at InitialObject.
best :: forall {k} (a :: k) v (n :: Nat) (p :: k +-> k) (b :: k) (cs :: [k]) (ws :: [v]). (Closing v n p, Ob a, Ob b) => Row v n p b cs ws -> GradedWalk v ('S n) p (MatVec v cs ws p a) a b Source Github #
The best walk through one of the given middle objects.
walkAt :: forall {k} v (n :: Nat) (p :: k +-> k) (d :: v) (a :: k) (b :: k). Closing v n p => ((Unit :: v) ~> d) -> GradedWalk v n p d a b -> Walk n p a b Source Github #
Reachability and shortest paths
checkedWalk :: forall {k} v (n :: Nat) (p :: k +-> k) (x :: k) (y :: k) (a :: k) (b :: k) (c :: k) (d :: k). (Closing v n p, Ob x, Ob y, Ob a, Ob b, Ob c, Ob d) => (HomObj v x y ** Walks v n p a b) ~> Walks v n p c d Source Github #
The action of the base on a closure: the triangle inequality. It holds for the best walks but
is not derived structurally, so it is a checkedArrow.
Orphan instances
| DecideComp (ThinCompStrategy p q) p q => DecidableProfunctor (p :.: q :: k -> j2 -> Type) Source Github # | |
| ComposeThin (ThinCompStrategy p q) p q => ThinProfunctor (p :.: q :: k -> j2 -> Type) Source Github # | |