2023-03-07 22:15:08 -05:00
|
|
|
||| This module defines profunctor strength with respect to a particular
|
|
|
|
||| monoidal structure.
|
|
|
|
|||
|
|
|
|
||| Unlike Haskell's profunctors library, `Strong` and `Choice` are here
|
|
|
|
||| special cases of the interface `GenStrong`, which defines strength with
|
|
|
|
||| respect to an arbitrary tensor product. When writing implementations for
|
|
|
|
||| a profunctor, `GenStrong Pair` and `GenStrong Either` should be used instead
|
|
|
|
||| of `Strong` and `Choice` respectively.
|
2023-03-05 17:06:27 -05:00
|
|
|
module Data.Profunctor.Strong
|
|
|
|
|
2023-03-06 11:31:00 -05:00
|
|
|
import Data.Morphisms
|
2023-03-06 10:50:30 -05:00
|
|
|
import Data.Tensor
|
2023-03-05 17:06:27 -05:00
|
|
|
import Data.Profunctor.Functor
|
|
|
|
import Data.Profunctor.Types
|
|
|
|
|
|
|
|
%default total
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Strength interface
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
||| Profunctor strength with respect to a tensor product.
|
|
|
|
||| A strong profunctor preserves the monoidal structure of a category.
|
|
|
|
|||
|
|
|
|
||| These constraints are not required by the interface, but the tensor product
|
|
|
|
||| `ten` is generally expected to implement `(Tensor ten i, Symmetric ten)`.
|
|
|
|
|||
|
|
|
|
||| Laws:
|
2023-03-07 22:28:38 -05:00
|
|
|
||| * `strongl = dimap swap' swap' . strongr`
|
2023-03-07 22:15:08 -05:00
|
|
|
||| * `dimap unitr.rightToLeft unitr.leftToRight . strongl = id`
|
|
|
|
||| * `lmap (mapSnd f) . strongl = rmap (mapSnd f) . strongl`
|
2023-03-07 22:21:54 -05:00
|
|
|
||| * `strongr . strongr = dimap assocr assocl . strongr`
|
2023-03-07 22:15:08 -05:00
|
|
|
|||
|
|
|
|
||| @ ten The tensor product of the monoidal structure
|
2023-03-05 17:06:27 -05:00
|
|
|
public export
|
|
|
|
interface Profunctor p => GenStrong (0 ten : Type -> Type -> Type) p where
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The left action of a strong profunctor.
|
2023-03-05 17:06:27 -05:00
|
|
|
strongl : p a b -> p (a `ten` c) (b `ten` c)
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The right action of a strong profunctor.
|
2023-03-05 17:06:27 -05:00
|
|
|
strongr : p a b -> p (c `ten` a) (c `ten` b)
|
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| Profunctor strength with respect to the product (`Pair`).
|
2023-03-05 17:06:27 -05:00
|
|
|
public export
|
|
|
|
Strong : (p : Type -> Type -> Type) -> Type
|
|
|
|
Strong = GenStrong Pair
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| A special case of `strongl` with constraint `Strong`.
|
|
|
|
||| This is useful if the typechecker has trouble inferring the tensor product.
|
|
|
|
%inline
|
2023-03-05 17:06:27 -05:00
|
|
|
public export
|
|
|
|
first : Strong p => p a b -> p (a, c) (b, c)
|
|
|
|
first = strongl {ten=Pair}
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| A special case of `strongr` with constraint `Strong`.
|
|
|
|
||| This is useful if the typechecker has trouble inferring the tensor product.
|
|
|
|
%inline
|
2023-03-05 17:06:27 -05:00
|
|
|
public export
|
|
|
|
second : Strong p => p a b -> p (c, a) (c, b)
|
|
|
|
second = strongr {ten=Pair}
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| Profunctor strength with respect to the coproduct (`Either`).
|
2023-03-06 10:51:23 -05:00
|
|
|
public export
|
|
|
|
Choice : (p : Type -> Type -> Type) -> Type
|
|
|
|
Choice = GenStrong Either
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| A special case of `strongl` with constraint `Choice`.
|
|
|
|
||| This is useful if the typechecker has trouble inferring the tensor product to use.
|
|
|
|
%inline
|
2023-03-06 10:51:23 -05:00
|
|
|
public export
|
|
|
|
left : Choice p => p a b -> p (Either a c) (Either b c)
|
|
|
|
left = strongl {ten=Either}
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| A special case of `strongr` with constraint `Choice`.
|
|
|
|
||| This is useful if the typechecker has trouble inferring the tensor product to use.
|
|
|
|
%inline
|
2023-03-06 10:51:23 -05:00
|
|
|
public export
|
|
|
|
right : Choice p => p a b -> p (Either c a) (Either c b)
|
|
|
|
right = strongr {ten=Either}
|
|
|
|
|
2023-03-05 17:06:27 -05:00
|
|
|
|
|
|
|
export
|
|
|
|
uncurry' : Strong p => p a (b -> c) -> p (a, b) c
|
|
|
|
uncurry' = rmap (uncurry id) . first
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
export
|
|
|
|
strong : Strong p => (a -> b -> c) -> p a b -> p a c
|
|
|
|
strong f = dimap dup (uncurry $ flip f) . first
|
|
|
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Implementations for existing types
|
|
|
|
------------------------------------------------------------------------------
|
2023-03-05 17:06:27 -05:00
|
|
|
|
2023-03-06 11:31:00 -05:00
|
|
|
|
|
|
|
export
|
|
|
|
Bifunctor ten => GenStrong ten Morphism where
|
|
|
|
strongl (Mor f) = Mor (mapFst f)
|
|
|
|
strongr (Mor f) = Mor (mapSnd f)
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| A named implementation of `GenStrong` for function types.
|
|
|
|
||| Use this to avoid having to use a type wrapper like `Morphism`.
|
2023-03-06 11:31:00 -05:00
|
|
|
export
|
|
|
|
[Function] Bifunctor ten => GenStrong ten (\a,b => a -> b)
|
|
|
|
using Profunctor.Function where
|
|
|
|
strongl = mapFst
|
|
|
|
strongr = mapSnd
|
|
|
|
|
|
|
|
export
|
|
|
|
Functor f => GenStrong Pair (Kleislimorphism f) where
|
|
|
|
strongl (Kleisli f) = Kleisli $ \(a,c) => (,c) <$> f a
|
|
|
|
strongr (Kleisli f) = Kleisli $ \(c,a) => (c,) <$> f a
|
|
|
|
|
|
|
|
export
|
|
|
|
Applicative f => GenStrong Either (Kleislimorphism f) where
|
|
|
|
strongl (Kleisli f) = Kleisli $ either (map Left . f) (pure . Right)
|
|
|
|
strongr (Kleisli f) = Kleisli $ either (pure . Left) (map Right . f)
|
|
|
|
|
|
|
|
export
|
|
|
|
Functor f => GenStrong Pair (Star f) where
|
|
|
|
strongl (MkStar f) = MkStar $ \(a,c) => (,c) <$> f a
|
|
|
|
strongr (MkStar f) = MkStar $ \(c,a) => (c,) <$> f a
|
|
|
|
|
|
|
|
export
|
|
|
|
Applicative f => GenStrong Either (Star f) where
|
|
|
|
strongl (MkStar f) = MkStar $ either (map Left . f) (pure . Right)
|
|
|
|
strongr (MkStar f) = MkStar $ either (pure . Left) (map Right . f)
|
|
|
|
|
|
|
|
export
|
|
|
|
GenStrong Either Tagged where
|
|
|
|
strongl (Tag x) = Tag (Left x)
|
|
|
|
strongr (Tag x) = Tag (Right x)
|
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
------------------------------------------------------------------------------
|
2023-03-05 17:06:27 -05:00
|
|
|
-- Tambara
|
2023-03-07 22:15:08 -05:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
2023-03-05 17:06:27 -05:00
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The comonad generated by the reflective subcategory of profunctors that
|
|
|
|
||| implement `GenStrong ten`.
|
2023-03-05 17:06:27 -05:00
|
|
|
public export
|
2023-03-06 10:50:30 -05:00
|
|
|
record GenTambara (ten, p : Type -> Type -> Type) a b where
|
2023-03-05 17:06:27 -05:00
|
|
|
constructor MkTambara
|
2023-03-06 16:44:26 -05:00
|
|
|
runTambara : forall c. p (a `ten` c) (b `ten` c)
|
2023-03-05 17:06:27 -05:00
|
|
|
|
2023-03-06 10:50:30 -05:00
|
|
|
export
|
|
|
|
Bifunctor ten => Profunctor p => Profunctor (GenTambara ten p) where
|
|
|
|
dimap f g (MkTambara p) = MkTambara $ dimap (mapFst f) (mapFst g) p
|
|
|
|
|
|
|
|
export
|
|
|
|
ProfunctorFunctor (GenTambara ten) where
|
|
|
|
promap f (MkTambara p) = MkTambara (f p)
|
|
|
|
|
|
|
|
export
|
|
|
|
Tensor ten i => ProfunctorComonad (GenTambara ten) where
|
2023-03-06 16:53:56 -05:00
|
|
|
proextract (MkTambara p) = dimap unitr.rightToLeft unitr.leftToRight p
|
2023-03-07 22:21:54 -05:00
|
|
|
produplicate (MkTambara p) = MkTambara $ MkTambara $ dimap assocr assocl p
|
2023-03-06 10:50:30 -05:00
|
|
|
|
|
|
|
export
|
|
|
|
Associative ten => Symmetric ten => Profunctor p => GenStrong ten (GenTambara ten p) where
|
2023-03-07 22:21:54 -05:00
|
|
|
strongl (MkTambara p) = MkTambara $ dimap assocr assocl p
|
2023-03-07 22:28:38 -05:00
|
|
|
strongr (MkTambara p) = MkTambara $ dimap (assocr . mapFst swap')
|
|
|
|
(mapFst swap' . assocl) p
|
2023-03-06 10:50:30 -05:00
|
|
|
|
|
|
|
export
|
|
|
|
Bifunctor ten => Profunctor p => Functor (GenTambara ten p a) where
|
|
|
|
map = rmap
|
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The comonad generated by the reflective subcategory of profunctors that
|
|
|
|
||| implement `Strong`.
|
|
|
|
|||
|
|
|
|
||| This is a special case of `GenTambara`.
|
2023-03-05 17:06:27 -05:00
|
|
|
public export
|
2023-03-06 11:01:17 -05:00
|
|
|
Tambara : (p : Type -> Type -> Type) -> Type -> Type -> Type
|
2023-03-05 17:06:27 -05:00
|
|
|
Tambara = GenTambara Pair
|
2023-03-06 10:51:03 -05:00
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The comonad generated by the reflective subcategory of profunctors that
|
|
|
|
||| implement `Choice`.
|
|
|
|
|||
|
|
|
|
||| This is a special case of `GenTambara`.
|
2023-03-06 11:01:17 -05:00
|
|
|
public export
|
|
|
|
TambaraSum : (p : Type -> Type -> Type) -> Type -> Type -> Type
|
|
|
|
TambaraSum = GenTambara Either
|
|
|
|
|
2023-03-07 14:16:55 -05:00
|
|
|
|
2023-03-06 11:01:17 -05:00
|
|
|
export
|
2023-03-07 14:16:55 -05:00
|
|
|
tambara : GenStrong ten p => p :-> q -> p :-> GenTambara ten q
|
|
|
|
tambara @{gs} f x = MkTambara $ f $ strongl @{gs} x
|
2023-03-06 11:01:17 -05:00
|
|
|
|
|
|
|
export
|
2023-03-07 14:16:55 -05:00
|
|
|
untambara : Tensor ten i => Profunctor q => p :-> GenTambara ten q -> p :-> q
|
|
|
|
untambara f x = dimap unitr.rightToLeft unitr.leftToRight $ runTambara $ f x
|
2023-03-06 11:01:17 -05:00
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
------------------------------------------------------------------------------
|
2023-03-06 10:51:03 -05:00
|
|
|
-- Pastro
|
2023-03-07 22:15:08 -05:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
2023-03-06 10:51:03 -05:00
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The monad generated by the reflective subcategory of profunctors that
|
|
|
|
||| implement `GenStrong ten`.
|
2023-03-06 10:51:03 -05:00
|
|
|
public export
|
|
|
|
data GenPastro : (ten, p : Type -> Type -> Type) -> Type -> Type -> Type where
|
|
|
|
MkPastro : (y `ten` z -> b) -> p x y -> (a -> x `ten` z) -> GenPastro ten p a b
|
|
|
|
|
|
|
|
|
|
|
|
export
|
|
|
|
Profunctor (GenPastro ten p) where
|
|
|
|
dimap f g (MkPastro l m r) = MkPastro (g . l) m (r . f)
|
|
|
|
lmap f (MkPastro l m r) = MkPastro l m (r . f)
|
|
|
|
rmap g (MkPastro l m r) = MkPastro (g . l) m r
|
|
|
|
|
|
|
|
export
|
|
|
|
ProfunctorFunctor (GenPastro ten) where
|
|
|
|
promap f (MkPastro l m r) = MkPastro l (f m) r
|
|
|
|
|
|
|
|
export
|
|
|
|
(Tensor ten i, Symmetric ten) => ProfunctorMonad (GenPastro ten) where
|
2023-03-06 16:53:56 -05:00
|
|
|
propure x = MkPastro unitr.leftToRight x unitr.rightToLeft
|
2023-03-06 10:51:03 -05:00
|
|
|
projoin (MkPastro {x=x',y=y',z=z'} l' (MkPastro {x,y,z} l m r) r') = MkPastro ll m rr
|
|
|
|
where
|
|
|
|
ll : y `ten` (z' `ten` z) -> b
|
2023-03-07 22:28:38 -05:00
|
|
|
ll = l' . mapFst l . assocl . mapSnd swap'
|
2023-03-06 10:51:03 -05:00
|
|
|
|
|
|
|
rr : a -> x `ten` (z' `ten` z)
|
2023-03-07 22:28:38 -05:00
|
|
|
rr = mapSnd swap' . assocr . mapFst r . r'
|
2023-03-06 10:51:03 -05:00
|
|
|
|
|
|
|
export
|
|
|
|
ProfunctorAdjunction (GenPastro ten) (GenTambara ten) where
|
|
|
|
prounit x = MkTambara (MkPastro id x id)
|
|
|
|
procounit (MkPastro l (MkTambara x) r) = dimap r l x
|
|
|
|
|
|
|
|
export
|
|
|
|
(Associative ten, Symmetric ten) => GenStrong ten (GenPastro ten p) where
|
|
|
|
strongl (MkPastro {x,y,z} l m r) = MkPastro l' m r'
|
|
|
|
where
|
|
|
|
l' : y `ten` (z `ten` c) -> b `ten` c
|
2023-03-07 22:21:54 -05:00
|
|
|
l' = mapFst l . assocl
|
2023-03-06 10:51:03 -05:00
|
|
|
r' : a `ten` c -> x `ten` (z `ten` c)
|
2023-03-07 22:21:54 -05:00
|
|
|
r' = assocr . mapFst r
|
2023-03-06 10:51:03 -05:00
|
|
|
strongr (MkPastro {x,y,z} l m r) = MkPastro l' m r'
|
|
|
|
where
|
|
|
|
l' : y `ten` (c `ten` z) -> c `ten` b
|
2023-03-07 22:28:38 -05:00
|
|
|
l' = swap' . mapFst l . assocl . mapSnd swap'
|
2023-03-06 10:51:03 -05:00
|
|
|
r' : c `ten` a -> x `ten` (c `ten` z)
|
2023-03-07 22:28:38 -05:00
|
|
|
r' = mapSnd swap' . assocr . mapFst r . swap'
|
2023-03-06 10:51:03 -05:00
|
|
|
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The monad generated by the reflective subcategory of profunctors that
|
|
|
|
||| implement `Strong`.
|
|
|
|
|||
|
|
|
|
||| This is a special case of `GenPastro`.
|
2023-03-06 11:01:17 -05:00
|
|
|
public export
|
|
|
|
Pastro : (p : Type -> Type -> Type) -> Type -> Type -> Type
|
|
|
|
Pastro = GenPastro Pair
|
|
|
|
|
2023-03-07 22:15:08 -05:00
|
|
|
||| The monad generated by the reflective subcategory of profunctors that
|
|
|
|
||| implement `Choice`.
|
|
|
|
|||
|
|
|
|
||| This is a special case of `GenPastro`.
|
2023-03-06 11:01:17 -05:00
|
|
|
public export
|
|
|
|
PastroSum : (p : Type -> Type -> Type) -> Type -> Type -> Type
|
|
|
|
PastroSum = GenPastro Either
|
|
|
|
|
2023-03-07 14:16:55 -05:00
|
|
|
|
2023-03-06 11:01:17 -05:00
|
|
|
export
|
2023-03-07 14:16:55 -05:00
|
|
|
pastro : GenStrong ten q => p :-> q -> GenPastro ten p :-> q
|
|
|
|
pastro @{gs} f (MkPastro l m r) = dimap r l (strongl @{gs} (f m))
|
2023-03-06 11:01:17 -05:00
|
|
|
|
|
|
|
export
|
2023-03-07 14:16:55 -05:00
|
|
|
unpastro : Tensor ten i => GenPastro ten p :-> q -> p :-> q
|
|
|
|
unpastro f x = f (MkPastro unitr.leftToRight x unitr.rightToLeft)
|
|
|
|
|