| License | BSD-style (see the file LICENSE) |
|---|---|
| Maintainer | sjoerd@w3future.com |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
Data.Square
Description
Synopsis
- emptySquare :: Square '[] '[] '[] '[]
- proId :: Profunctor p => Square '[p] '[p] '[] '[]
- funId :: Functor f => Square '[] '[] '[f] '[f]
- funNat :: (Functor f, Functor g) => (f ~> g) -> Square '[] '[] '[f] '[g]
- proNat :: (Profunctor p, Profunctor q) => (p :-> q) -> Square '[p] '[q] '[] '[]
- newtype SquareNT p q f g = Square {
- unSquare :: forall a b. p a b -> q (f a) (g b)
- type Square ps qs fs gs = SquareNT (PList ps) (PList qs) (FList fs) (FList gs)
- mkSquare :: (IsPList ps, IsPList qs, IsFList fs, IsFList gs, Profunctor (PList qs)) => (forall a b. PlainP ps a b -> PlainP qs (PlainF fs a) (PlainF gs b)) -> Square ps qs fs gs
- runSquare :: (IsPList ps, IsPList qs, IsFList fs, IsFList gs, Profunctor (PList qs)) => Square ps qs fs gs -> PlainP ps a b -> PlainP qs (PlainF fs a) (PlainF gs b)
- (|||) :: (Profunctor (PList rs), IsFList fs, IsFList gs, Functor (FList hs), Functor (FList is)) => Square ps qs fs gs -> Square qs rs hs is -> Square ps rs (fs ++ hs) (gs ++ is)
- (===) :: (IsPList ps, IsPList qs, Profunctor (PList qs), Profunctor (PList ss)) => Square ps qs fs gs -> Square rs ss gs hs -> Square (ps ++ rs) (qs ++ ss) fs hs
- toRight :: Functor f => Square '[] '[Star f] '[f] '[]
- toLeft :: Square '[Costar f] '[] '[f] '[]
- fromRight :: Functor f => Square '[] '[Costar f] '[] '[f]
- fromLeft :: Square '[Star f] '[] '[] '[f]
- uLeft :: Functor f => Square '[Star f, Costar f] '[] '[] '[]
- uRight :: Functor f => Square '[] '[Costar f, Star f] '[] '[]
- toRight2 :: (Functor f, Functor g) => Square '[] '[Star g, Star f] '[f, g] '[]
- toLeft2 :: (Functor f, Functor g) => Square '[Costar f, Costar g] '[] '[f, g] '[]
- fromRight2 :: (Functor f, Functor g) => Square '[] '[Costar f, Costar g] '[] '[f, g]
- fromLeft2 :: (Functor f, Functor g) => Square '[Star g, Star f] '[] '[] '[f, g]
- spiderLemma :: (Profunctor p, Profunctor q, Functor f1, Functor f2, Functor f3, Functor g1, Functor g2, Functor g3) => Square '[p] '[q] '[f1, f2, f3] '[g1, g2, g3] -> Square '[Star f1, p, Costar g1] '[Costar f3, q, Star g3] '[f2] '[g2]
- spiderLemma' :: (Profunctor p, Profunctor q, Functor f1, Functor f2, Functor f3, Functor g1, Functor g2, Functor g3) => Square '[Star f1, p, Costar g1] '[Costar f3, q, Star g3] '[f2] '[g2] -> Square '[p] '[q] '[f1, f2, f3] '[g1, g2, g3]
- type Square21 ps1 ps2 qs f g = SquareNT (PList ps1 :**: PList ps2) (PList qs) (UncurryF f) (UncurryF g)
- data (p1 :**: p2) a b where
- data UncurryF f a where
- type Square01 qs a b = SquareNT Unit (PList qs) (ValueF a) (ValueF b)
- data Unit a b where
- data ValueF x u where
Double category
There is a double category of Haskell functors and profunctors.
The squares in this double category are natural transformations.
emptySquare :: Square '[] '[] '[] '[] Source #
+-----+ | | | | | | +-----+
forall a b. (a -> b) -> (a -> b)
The empty square is the identity transformation.
proId :: Profunctor p => Square '[p] '[p] '[] '[] Source #
+-----+ | | p-----p | | +-----+
forall a b. p a b -> p a b
Profunctors are drawn as horizontal lines.
Note that emptySquare is proId for the profunctor (->).
We don't draw a line for (->) because it is the identity for profunctor composition.
funId :: Functor f => Square '[] '[] '[f] '[f] Source #
+--f--+ | | | | v | | | | +--f--+
forall a b. (a -> b) -> (f a -> f b)
Functors are drawn with vertical lines with arrow heads.
You will recognize the above type as fmap!
We don't draw lines for the identity functor, because it is the identity for functor composition.
funNat :: (Functor f, Functor g) => (f ~> g) -> Square '[] '[] '[f] '[g] Source #
+--f--+ | | | | @ | | | | +--g--+
forall a b. (a -> b) -> (f a -> g b)
Non-identity transformations are drawn with an @ in the middle.
Natural transformations between haskell functors are usualy given the type
forall a. f a -> g a. The type above you get when fmapping before or after.
(It doesn't matter which, because of naturality!)
proNat :: (Profunctor p, Profunctor q) => (p :-> q) -> Square '[p] '[q] '[] '[] Source #
+-----+ | | p--@--q | | +-----+
forall a b. p a b -> q a b
Natural transformations between profunctors.
newtype SquareNT p q f g Source #
+--f--+ | v | p--@--q | v | +--g--+
forall a b. p a b -> q (f a) (g b)
The complete definition of a square is a combination of natural transformations between functors and natural transformations between profunctors.
To make type inferencing easier the above type is wrapped by a newtype.
type Square ps qs fs gs = SquareNT (PList ps) (PList qs) (FList fs) (FList gs) Source #
To make composing squares associative, this library uses squares with lists of functors and profunctors, which are composed together.
FList '[] a ~ a FList '[f, g, h] a ~ h (g (f a)) PList '[] a b ~ a -> b PList '[p, q, r] a b ~ (p a x, q x y, r y b)
mkSquare :: (IsPList ps, IsPList qs, IsFList fs, IsFList gs, Profunctor (PList qs)) => (forall a b. PlainP ps a b -> PlainP qs (PlainF fs a) (PlainF gs b)) -> Square ps qs fs gs Source #
runSquare :: (IsPList ps, IsPList qs, IsFList fs, IsFList gs, Profunctor (PList qs)) => Square ps qs fs gs -> PlainP ps a b -> PlainP qs (PlainF fs a) (PlainF gs b) Source #
(|||) :: (Profunctor (PList rs), IsFList fs, IsFList gs, Functor (FList hs), Functor (FList is)) => Square ps qs fs gs -> Square qs rs hs is -> Square ps rs (fs ++ hs) (gs ++ is) infixl 6 Source #
(===) :: (IsPList ps, IsPList qs, Profunctor (PList qs), Profunctor (PList ss)) => Square ps qs fs gs -> Square rs ss gs hs -> Square (ps ++ rs) (qs ++ ss) fs hs infixl 5 Source #
Proarrow equipment
The double category of haskell functors and profunctors is a proarrow equipment. Which means that we can "bend" functors to become profunctors.
toRight :: Functor f => Square '[] '[Star f] '[f] '[] Source #
+--f--+ | v | | \->f | | +-----+
A functor f can be bent to the right to become the profunctor .Star f
toLeft :: Square '[Costar f] '[] '[f] '[] Source #
+--f--+ | v | f<-/ | | | +-----+
A functor f can be bent to the left to become the profunctor .Costar f
fromRight :: Functor f => Square '[] '[Costar f] '[] '[f] Source #
+-----+ | | | /-<f | v | +--f--+
The profunctor can be bent down to become the functor Costar ff again.
fromLeft :: Square '[Star f] '[] '[] '[f] Source #
+-----+ | | f>-\ | | v | +--f--+
The profunctor can be bent down to become the functor Star ff again.
toRight2 :: (Functor f, Functor g) => Square '[] '[Star g, Star f] '[f, g] '[] Source #
+-f-g-+ | v \>g funId ||| toRight | | | === | \-->f toRight +-----+
toLeft2 :: (Functor f, Functor g) => Square '[Costar f, Costar g] '[] '[f, g] '[] Source #
+-f-g-+ f</ v | toLeft ||| funId | | | === g<--/ | toLeft +-----+
fromRight2 :: (Functor f, Functor g) => Square '[] '[Costar f, Costar g] '[] '[f, g] Source #
+-----+ | /--<f fromRight | | | === | v /<g funId ||| fromRight +-f-g-+
fromLeft2 :: (Functor f, Functor g) => Square '[Star g, Star f] '[] '[] '[f, g] Source #
+-----+ g>--\ | fromLeft | | | === f>\ | | fromLeft ||| funId +-f-g-+
spiderLemma :: (Profunctor p, Profunctor q, Functor f1, Functor f2, Functor f3, Functor g1, Functor g2, Functor g3) => Square '[p] '[q] '[f1, f2, f3] '[g1, g2, g3] -> Square '[Star f1, p, Costar g1] '[Costar f3, q, Star g3] '[f2] '[g2] Source #
+f-f-f+ +--f--+ spiderLemma n = |v v v| f> v <f fromLeft ||| funId ||| fromRight | \|/ | | \|/ | === p--@--q ==> p--@--q n | /|\ | | /|\ | === |v v v| g< v >g toLeft ||| funId ||| toRight +g-g-g+ +--g--+
The spider lemma is an example how bending wires can also be seen as sliding functors around corners.
spiderLemma' :: (Profunctor p, Profunctor q, Functor f1, Functor f2, Functor f3, Functor g1, Functor g2, Functor g3) => Square '[Star f1, p, Costar g1] '[Costar f3, q, Star g3] '[f2] '[g2] -> Square '[p] '[q] '[f1, f2, f3] '[g1, g2, g3] Source #
spiderLemma' n = (toRight === proId === fromRight) ||| n ||| (toLeft === proId === fromLeft)
The spider lemma in the other direction.
In other categories than Hask
A--f--C | v | p--@--q | v | B--g--D
Squares can be generalized further by choosing a different category for each quadrant.
To use this, SquareNT has been made kind polymorphic:
type SquareNT :: (a -> b -> Type) -> (c -> d -> Type) -> (a -> c) -> (b -> d) -> Type
This library is mostly about staying in Hask, but it is interesting to use f.e. the
product category Hask × Hask or the unit category.
type Square21 ps1 ps2 qs f g = SquareNT (PList ps1 :**: PList ps2) (PList qs) (UncurryF f) (UncurryF g) Source #
H²-f--H | v | p--@--q H = Hask, H² = Hask x Hask | v | H²-g--H
data (p1 :**: p2) a b where Source #
Combine two profunctors from Hask to a profunctor from Hask x Hask
data UncurryF f a where Source #
Uncurry the kind of a bifunctor.
type UncurryF :: (a -> b -> Type) -> (a, b) -> Type
type Square01 qs a b = SquareNT Unit (PList qs) (ValueF a) (ValueF b) Source #
1--a--H | v | U--@--q 1 = Hask^0 = (), H = Hask | v | 1--b--H
The boring profunctor from and to the unit category.