| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Proarrow.Path
Description
A profunctor-specific counterpart of Proarrow.Bicategory.Strictified, hardcoded to
:.:/Id instead of an arbitrary Bicategory. A Path is a
type-level list of profunctors; Fold collapses one down to the single profunctor its
elements compose to. Unlike the general (strictified) version, we don't need to track
identity 2-cells through the induction -- since our 2-cells are just plain Haskell
functions (:~>), the identity of any composite is always definitionally \x -> x.
The only real work is concatFold/splitFold, which do the actual
associator/unitor reshuffling once, by induction, so that Proarrow.Squares never has
to.
Synopsis
- idN :: forall {k} {k1} p (a :: k) (b :: k1). p a b -> p a b
- leftUnitor :: forall {k1} {k} (p :: k1 +-> k). Profunctor p => ((Id :: k -> k -> Type) :.: p) :~> p
- leftUnitorInv :: forall {i} {j} (p :: i +-> j). Profunctor p => p :~> ((Id :: j -> j -> Type) :.: p)
- rightUnitor :: forall {k1} {k} (p :: k1 +-> k). Profunctor p => (p :.: (Id :: k1 -> k1 -> Type)) :~> p
- rightUnitorInv :: forall {i} {k} (p :: i +-> k). Profunctor p => p :~> (p :.: (Id :: i -> i -> Type))
- associator :: forall {k1} {k2} {j} {i} (p :: k1 +-> k2) (q :: j +-> k1) (r :: i +-> j) (a :: k2) (b :: i). ((p :.: q) :.: r) a b -> (p :.: (q :.: r)) a b
- associatorInv :: forall {j1} {k} {j2} {i} (p :: j1 +-> k) (q :: j2 +-> j1) (r :: i +-> j2) (a :: k) (b :: i). (p :.: (q :.: r)) a b -> ((p :.: q) :.: r) a b
- data Path j k where
- type family (ps :: Path a b) +++ (qs :: Path b c) :: Path a c
- class ((as +++ bs) +++ cs) ~ (as +++ (bs +++ cs)) => Assoc (as :: Path a a1) (bs :: Path a1 b) (cs :: Path b c)
- type family Fold (ps :: Path j k) :: j +-> k
- data Tag
- type family Sat (t :: Tag) (p :: i +-> j)
- data SPath (t :: Tag) (ps :: Path a b) where
- class ((ps +++ ('Nil :: Path k k)) ~ ps, forall b c (qs :: Path k b) (rs :: Path b c). Assoc ps qs rs) => IsOb (t :: Tag) (ps :: Path j k) where
- appendPath :: forall {a} {b1} {b2} (t :: Tag) (ps :: Path a b1) (qs :: Path b1 b2). SPath t ps -> SPath t qs -> SPath t (ps +++ qs)
- withAssoc :: forall {a1} {a2} {b} {c} (ps :: Path a1 a2) (qs :: Path a2 b) (rs :: Path b c) (t :: Tag) r. IsOb t ps => (Assoc ps qs rs => r) -> r
- type IsPath = IsOb 'Prof :: Path j k -> Constraint
- type IsTight = IsOb 'Tight :: Path j k -> Constraint
- weakenTight :: forall {a} {b} (ps :: Path a b). SPath 'Tight ps -> SPath 'Prof ps
- withObAppend :: forall {j} {b} {k} (t :: Tag) (ps :: Path j b) (qs :: Path b k) r. IsOb t qs => SPath t ps -> (IsOb t (ps +++ qs) => r) -> r
- withFoldOb :: forall {j} {k} (ps :: Path j k) r. SPath 'Prof ps -> (Profunctor (Fold ps) => r) -> r
- withFoldRep :: forall {j} {k} (ps :: Path j k) r. SPath 'Tight ps -> (Representable (Fold ps) => r) -> r
- concatFold :: forall {j} {b} {k} (as :: Path j b) (bs :: Path b k). SPath 'Prof as -> SPath 'Prof bs -> (Fold bs :.: Fold as) :~> Fold (as +++ bs)
- splitFold :: forall {i} {k1} {k2} (as :: Path i k1) (bs :: Path k1 k2). SPath 'Prof as -> SPath 'Prof bs -> Fold (as +++ bs) :~> (Fold bs :.: Fold as)
- whiskerL :: forall {j} {b} {k} (xs :: Path j b) (ys :: Path b k) (zs :: Path b k). SPath 'Prof xs -> SPath 'Prof ys -> SPath 'Prof zs -> (Fold ys :~> Fold zs) -> Fold (xs +++ ys) :~> Fold (xs +++ zs)
- whiskerR :: forall {j} {b} {k} (xs :: Path j b) (ys :: Path j b) (zs :: Path b k). SPath 'Prof xs -> SPath 'Prof ys -> SPath 'Prof zs -> (Fold xs :~> Fold ys) -> Fold (xs +++ zs) :~> Fold (ys +++ zs)
Documentation
idN :: forall {k} {k1} p (a :: k) (b :: k1). p a b -> p a b Source Github #
Identity natural transformation, used as a 2-cell between profunctors that happen to be syntactically equal.
leftUnitor :: forall {k1} {k} (p :: k1 +-> k). Profunctor p => ((Id :: k -> k -> Type) :.: p) :~> p Source Github #
leftUnitorInv :: forall {i} {j} (p :: i +-> j). Profunctor p => p :~> ((Id :: j -> j -> Type) :.: p) Source Github #
rightUnitor :: forall {k1} {k} (p :: k1 +-> k). Profunctor p => (p :.: (Id :: k1 -> k1 -> Type)) :~> p Source Github #
rightUnitorInv :: forall {i} {k} (p :: i +-> k). Profunctor p => p :~> (p :.: (Id :: i -> i -> Type)) Source Github #
associator :: forall {k1} {k2} {j} {i} (p :: k1 +-> k2) (q :: j +-> k1) (r :: i +-> j) (a :: k2) (b :: i). ((p :.: q) :.: r) a b -> (p :.: (q :.: r)) a b Source Github #
associatorInv :: forall {j1} {k} {j2} {i} (p :: j1 +-> k) (q :: j2 +-> j1) (r :: i +-> j2) (a :: k) (b :: i). (p :.: (q :.: r)) a b -> ((p :.: q) :.: r) a b Source Github #
class ((as +++ bs) +++ cs) ~ (as +++ (bs +++ cs)) => Assoc (as :: Path a a1) (bs :: Path a1 b) (cs :: Path b c) Source Github #
(as +++ bs) +++ cs and as +++ (bs +++ cs) are the same Path. Proved once, up
front, by (mutual) induction with IsOb's superclasses -- see there for how the
induction actually goes through -- so that every other associativity fact needed
anywhere in Proarrow.Squares is a free ~ coercion instead of a function call.
type family Fold (ps :: Path j k) :: j +-> k Source Github #
Fold a Path down to the single profunctor its elements compose to.
Which per-element property a SPath witnesses. Tight plays the role of the tight
(vertical, Representable) legs of the Prof equipment; a later Cotight would do
the same for Corepresentable legs.
type family Sat (t :: Tag) (p :: i +-> j) Source Github #
The per-element constraint a Tag stands for. c is applied homogeneously at every
element of a path, each of a (potentially) different i +-> j kind -- a genuinely
impredicative use GHC's kind system can't express with c itself as the parameter, so
Tag is the (monomorphic, first-order) proxy for it instead. Mirrors
Proarrow.Bicategory.Sub's IsOb/SUBCAT tag mechanism.
data SPath (t :: Tag) (ps :: Path a b) where Source Github #
Runtime witness that every element of a Path satisfies . Replaces having a
separate witness type per tag (what used to be Sat tSPath/TPath), so
(|||)/(===) only need one append lemma
(withObAppend), not one per kind of leg.
class ((ps +++ ('Nil :: Path k k)) ~ ps, forall b c (qs :: Path k b) (rs :: Path b c). Assoc ps qs rs) => IsOb (t :: Tag) (ps :: Path j k) where Source Github #
ps is a path all of whose elements satisfy . Only two cases (Sat tNil/Cons)
are needed: the head p stays concrete at each step of withObAppend's recursion, so
GHC's own instance resolution reattaches it to the recursively-derived
for free -- it never needs to reduce IsOb t (ps +++ qs)ps +++ qs itself, just
match the ( shape.:::)
Instances
appendPath :: forall {a} {b1} {b2} (t :: Tag) (ps :: Path a b1) (qs :: Path b1 b2). SPath t ps -> SPath t qs -> SPath t (ps +++ qs) Source Github #
Concatenate two witnesses. Plain recursion, no constraint solving -- unlike
withObAppend, which additionally proves .IsOb t (ps +++ qs)
withAssoc :: forall {a1} {a2} {b} {c} (ps :: Path a1 a2) (qs :: Path a2 b) (rs :: Path b c) (t :: Tag) r. IsOb t ps => (Assoc ps qs rs => r) -> r Source Github #
Bring a specific instantiation of 's quantified IsOb t ps
superclass into scope. Needed explicitly: GHC won't search the superclasses of an
arbitrary given constraint to solve an unrelated Assoc ps qs rs~ goal, so uses of associativity
(e.g. in (|||)/(===)) have to ask for it by name
at the specific ps/qs/rs in play, even though the fact itself is free once
asked for.
type IsPath = IsOb 'Prof :: Path j k -> Constraint Source Github #
A well-formed (horizontal) path: every element is a plain Profunctor.
type IsTight = IsOb 'Tight :: Path j k -> Constraint Source Github #
A tight (vertical) path: every element is Representable.
weakenTight :: forall {a} {b} (ps :: Path a b). SPath 'Tight ps -> SPath 'Prof ps Source Github #
A tight path is, in particular, a well-formed path (Representable implies
Profunctor). Needed explicitly because different Tags don't otherwise know
anything about each other.
withObAppend :: forall {j} {b} {k} (t :: Tag) (ps :: Path j b) (qs :: Path b k) r. IsOb t qs => SPath t ps -> (IsOb t (ps +++ qs) => r) -> r Source Github #
ps,qs both satisfy pointwise ⟹ so does Sat tps +++ qs.
withFoldOb :: forall {j} {k} (ps :: Path j k) r. SPath 'Prof ps -> (Profunctor (Fold ps) => r) -> r Source Github #
Extract Profunctor evidence for from a runtime witness.Fold ps
withFoldRep :: forall {j} {k} (ps :: Path j k) r. SPath 'Tight ps -> (Representable (Fold ps) => r) -> r Source Github #
Extract Representable evidence for from a runtime witness. The body is
identical to Fold pswithFoldOb's -- both just extract , which needs the
same single-vs-multi-element case split Sat t (Fold ps)Fold itself has -- but there's no polymorphic
t anywhere that would let one definition serve both: every call site already knows
its tag concretely, so there's nothing to be generic over.
concatFold :: forall {j} {b} {k} (as :: Path j b) (bs :: Path b k). SPath 'Prof as -> SPath 'Prof bs -> (Fold bs :.: Fold as) :~> Fold (as +++ bs) Source Github #
Combine the composites of two adjacent paths into the composite of their concatenation.
splitFold :: forall {i} {k1} {k2} (as :: Path i k1) (bs :: Path k1 k2). SPath 'Prof as -> SPath 'Prof bs -> Fold (as +++ bs) :~> (Fold bs :.: Fold as) Source Github #
The inverse of concatFold.