@@ -26,7 +26,19 @@ data CoyonedaF f a i = CoyonedaF (i -> a) (f i)
26
26
-- | The `Coyoneda` `Functor`.
27
27
-- |
28
28
-- | `Coyoneda f` is a `Functor` for any type constructor `f`. In fact,
29
- -- | it is the _free_ `Functor` for `f`.
29
+ -- | it is the _free_ `Functor` for `f`, i.e. any natural transformation
30
+ -- | `nat :: f ~> g`, can be factor through `liftCoyoneda`. The natural
31
+ -- | transformation from `Coyoneda f ~> g` is given by `lowerCoyoneda <<<
32
+ -- | hoistCoyoneda nat`:
33
+ -- | ```purescript
34
+ -- | lowerCoyoneda <<< hoistCoyoneda nat <<< liftCoyoneda $ fi
35
+ -- | = lowerCoyoneda (hoistCoyoneda nat (Coyoneda $ mkExists $ CoyonedaF id fi)) (by definition of liftCoyoneda)
36
+ -- | = lowerCoyoneda (coyoneda id (nat fi)) (by definition of hoistCoyoneda)
37
+ -- | = unCoyoneda map (coyoneda id (nat fi)) (by definition of lowerCoyoneda)
38
+ -- | = unCoyoneda map (Coyoneda $ mkExists $ CoyonedaF id (nat fi)) (by definition of coyoneda)
39
+ -- | = map id (nat fi) (by definition of unCoyoneda)
40
+ -- | = nat fi (since g is a Functor)
41
+ -- | ```
30
42
newtype Coyoneda f a = Coyoneda (Exists (CoyonedaF f a ))
31
43
32
44
instance eqCoyoneda :: (Functor f , Eq1 f , Eq a ) => Eq (Coyoneda f a ) where
@@ -55,6 +67,12 @@ instance bindCoyoneda :: Bind f => Bind (Coyoneda f) where
55
67
liftCoyoneda $
56
68
runExists (\(CoyonedaF k fi) -> lowerCoyoneda <<< f <<< k =<< fi) e
57
69
70
+ -- | When `f` is a Monad then it is a functor as well. In this case
71
+ -- | `liftCoyoneda` is not only a functor isomorphism but also a monad
72
+ -- | isomorphism, i.e. the following law holds
73
+ -- | ```purescript
74
+ -- | liftCoyoneda fa >>= liftCoyoneda <<< g = liftCoyoneda $ fa >>= g
75
+ -- | ```
58
76
instance monadCoyoneda :: Monad f => Monad (Coyoneda f )
59
77
60
78
instance monadTransCoyoneda :: MonadTrans Coyoneda where
@@ -64,6 +82,12 @@ instance extendCoyoneda :: Extend w => Extend (Coyoneda w) where
64
82
extend f (Coyoneda e) =
65
83
runExists (\(CoyonedaF k fi) -> liftCoyoneda $ f <<< coyoneda k <<= fi) e
66
84
85
+ -- | As in the monad case: if `w` is a comonad, then it is a functor, thus
86
+ -- | `liftCoyoneda` is an iso of functors, but moreover it is an iso of
87
+ -- | comonads, i.e. the following law holds:
88
+ -- | ```purescript
89
+ -- | g <<= liftCoyoneda w = liftCoyoneda $ g <<< liftCoyoneda <<= w
90
+ -- | ```
67
91
instance comonadCoyoneda :: Comonad w => Comonad (Coyoneda w ) where
68
92
extract (Coyoneda e) = runExists (\(CoyonedaF k fi) -> k $ extract fi) e
69
93
@@ -78,6 +102,21 @@ unCoyoneda :: forall f g a. (forall b. (b -> a) -> f b -> g a) -> Coyoneda f a -
78
102
unCoyoneda f (Coyoneda e) = runExists (\(CoyonedaF k fi) -> f k fi) e
79
103
80
104
-- | Lift a value described by the type constructor `f` to `Coyoneda f`.
105
+ -- |
106
+ -- | Note that for any functor `f` `liftCoyoneda` has a right inverse
107
+ -- | `lowerCoyoneda`:
108
+ -- | ```purescript
109
+ -- | liftCoyoneda <<< lowerCoyoneda $ (Coyoneda e)
110
+ -- | = liftCoyoneda <<< unCoyoneda map $ (Coyoneda e)
111
+ -- | = liftCoyonead (runExists (\(CoyonedaF k fi) -> map k fi) e)
112
+ -- | = liftCoyonead (Coyoneda e)
113
+ -- | = coyoneda id (Coyoneda e)
114
+ -- | = Coyoneda e
115
+ -- | ```
116
+ -- | Moreover if `f` is a `Functor` then `liftCoyoneda` is an isomorphism of
117
+ -- | functors with inverse `lowerCoyoneda`: we already showed that
118
+ -- | `lowerCoyoneda <<< hoistCoyoneda id = lowerCoyoneda` is its left inverse
119
+ -- | whenever `f` is a functor.
81
120
liftCoyoneda :: forall f . f ~> Coyoneda f
82
121
liftCoyoneda = coyoneda id
83
122
0 commit comments