Questo non viene verificato perché la classe Adjunction
rappresenta solo un piccolo sottoinsieme di aggiunte, in cui entrambi i funzioni sono endofunctor su Hask .
A quanto pare, questo non è il caso dell'adeguamento (<-:) r -| (<-:) r
. Ci sono due funzioni sottilmente differenti:
f = (<-:) r
, il funzione da Hask a Op (Hask) (la categoria opposta di Hask, talvolta indicata anche come Hask ^ op)
g = (<-:) r
, il funzione da Op (Hask) a Hask
In particolare, counit
dovrebbe essere una trasformazione naturale nella categoria Op (Hask), che gira le frecce attorno:
unit :: a -> g (f a)
counit :: f (g a) <-: a
In effetti, counit
coincide con unit
in questa modifica.
Per catturarlo correttamente, dobbiamo generalizzare le classi Functor
e in Adjunction
modo da poter modellare le aggiunte tra le diverse categorie:
class Exofunctor c d f where
exomap :: c a b -> d (f a) (f b)
class
(Exofunctor d c f, Exofunctor c d g) =>
Adjunction
(c :: k -> k -> Type)
(d :: h -> h -> Type)
(f :: h -> k)
(g :: k -> h) where
unit :: d a (g (f a))
counit :: c (f (g a)) a
Quindi otteniamo di nuovo che Compose
è una monade (e un comonad se capovolgiamo l'aggiunta):
newtype Compose f g a = Compose { unCompose :: f (g a) }
adjReturn :: forall c f g a. Adjunction c (->) f g => a -> Compose g f a
adjReturn = Compose . unit @_ @_ @c @(->)
adjJoin :: forall c f g a. Adjunction c (->) f g => Compose g f (Compose g f a) -> Compose g f a
adjJoin = Compose . exomap (counit @_ @_ @c @(->)) . (exomap . exomap @(->) @c) unCompose . unCompose
ed Cont
è semplicemente un caso speciale di ciò:
type Cont r = Compose ((<-:) r) ((<-:) r)
Vedi anche questa sintesi per maggiori dettagli: https://gist.github.com/Lysxia/beb6f9df9777bbf56fe5b42de04e6c64
Ho letto che dati un paio di aggiunte formano un'unica Monade e Comonade ma una Monade può essere scomposta in più Fattori. C'è qualche esempio di questo?
La fattorizzazione non è generalmente unica. Dopo aver generalizzato le aggiunte come sopra, puoi almeno considerare ogni monade M
come un'aggiunta tra la sua categoria Kleisli e la sua categoria base (in questo caso, Hask).
Every monad M defines an adjunction
F -| G
where
F : (->) -> Kleisli M
: Type -> Type -- Types are the objects of both categories (->) and Kleisli m.
-- The left adjoint F maps each object to itself.
: (a -> b) -> (a -> M b) -- The morphism mapping uses return.
G : Kleisli M -> (->)
: Type -> Type -- The right adjoint G maps each object a to m a
: (a -> M b) -> (M a -> M b) -- This is (=<<)
Non so se la monade di continuazione corrisponda a un aggiustamento tra endofunctor su Hask.
Vedi anche l'articolo nCatLab sulle monadi: https://ncatlab.org/nlab/show/monad#RelationToAdjunctionsAndMonadicity
Relazione con aggiunte e monadicità
Ogni aggiunta (L ⊣ R) induce una monade R∘L e una comonad L∘R. Vi è in generale più di una aggiunta che dà origine a una data monade in questo modo, infatti esiste una categoria di aggiunte per una data monade. L'oggetto iniziale in quella categoria è l'aggiustamento sulla categoria Kleisli della monade e l'oggetto terminale è quello sulla categoria di algebre di Eilenberg-Moore. (es. Borceux, vol. 2, prop. 4.2.2) Quest'ultima è chiamata regolazione monadica.