这不会进行类型检查,因为该类Adjunction
仅表示附加的一小部分,其中两个函子都是Hask上的endofunctors。
事实证明,附属条件并非如此(<-:) r -| (<-:) r
。这里有两个细微不同的函子:
f = (<-:) r
,从Hask到Op(Hask)的函子(与Hask相反的类别,有时也称为Hask ^ op)
g = (<-:) r
,从Op(Hask)到Hask的函子
尤其counit
应在Op(Hask)类别中进行自然转换,该类别会围绕以下箭头翻转:
unit :: a -> g (f a)
counit :: f (g a) <-: a
其实counit
与unit
此附件相同。
为了正确地捕捉到这一点,我们需要对Functor
and Adjunction
类进行泛化,以便可以对不同类别之间的附加语进行建模:
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
然后,我们再次得到Compose
一个单子(如果翻转该附加,则是一个单子):
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
并且Cont
仅仅是其中的一种特殊情况:
type Cont r = Compose ((<-:) r) ((<-:) r)
另请参阅此要点以获取更多详细信息:https : //gist.github.com/Lysxia/beb6f9df9777bbf56fe5b42de04e6c64
我读过,给定一对伴随物,它们会形成一个独特的Monad&Comonad,但给定一个Monad,它可以分解为多个因数。有这个例子吗?
分解通常不是唯一的。一旦如上所述M
对附加词进行了概括,那么至少可以将任何monad 视为其Kleisli类别与其基本类别(在本例中为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 (=<<)
我不知道延续单子是否对应于Hask上endofunctors之间的附加词。
另请参阅有关monad的nCatLab文章:https ://ncatlab.org/nlab/show/monad#RelationToAdjunctionsAndMonadicity
与附加条件和专制性的关系
每个附加语(L⊣R)都会产生一个单子R∘L和一个共性L∘R。通常,有不止一个附加词以这种方式产生给定的单子,实际上,给定单子有一类附加词。该类别中的初始对象是单子的Kleisli类别的附加物,而末端对象是代数的Eilenberg-Moore类别的附加物。(例如Borceux,第2卷,第4.2.2节)后者称为单子附加。