7

我试图将 Monad 的分类定义与我在其他一些教程/书籍中看到的其他一般表示/定义相协调。

下面,我(也许是强行)试图使这两个定义接近,请指出错误并在需要时提供更正

所以从 Monad 的定义开始

单子只是内函子类别中的幺半群。

并且对 endofunctors 有一点了解,我假设 Monad 可以写成

((a->b)->Ma->Mb)->((b->c)->Mb->Mc) 

TypeLHS(左侧)的 ' ' 是Mb, RHS 的类型是Mc,所以我想我可以这样写

Mb-> (b->c)-> Mc, **which is how we define bind**

这就是我如何看待内引子类别中的 Monads(它们本身在CategoryC 中,带有 ' types' as objects

单子视觉.

这有什么意义吗?

4

3 回答 3

9

Well um, I think you're a bit off. A monad is an endofunctor, which in Hask (The category of Haskell types) is something with the kind F :: * -> * with some function that knows how to inject morphisms (functions) into the subcategory of Hask with functions upon Fs as morphisms and Fs as objects, fmap. What you have there appears to be a natural transformation in Hask.

Examples: Maybe, Either a, (,) a, etc..

Now a monad also must have 2 natural transformations (Functor F, Functor g => F a -> G a in hask).

n : Identity -> M
u : M^2 -> M

Or in haskell code

n :: Identity a -> M a -- Identity a == a
u :: M (M a) -> M a

which correspond to return and join respectively.

Now we have to get to >>=. What you had as bind was actually just fmap, what we actually want is m a -> (a -> m b) -> m b. This is easily defined as

 m >>= f = join $ f `fmap` m

Tada! We have monads. Now for this monoid of endofunctors.

A monoid over endofunctors would have a functors as objects and natural transformations as morphisms. The interesting thing is that the product of two endofunctors is their composition. Here's the Haskell code for our new monoid

type (f <+> g) a = f (g a)
class Functor m => Monoid' m where
    midentity' :: Identity a -> m a
    mappend' :: (m <+> m) a -> m a

This desugars to

 midentity' :: a -> m a
 mappend' :: m (m a) -> m a

Look familiar?

于 2013-09-21T03:07:56.370 回答
5

定义“Monads 只是 endofunctors 类别中的幺半群。”,虽然这是一个糟糕的起点。它来自一篇博文,主要是为了开个玩笑。但是,如果您对通信感兴趣,可以在 Haskell 中进行演示:

范畴的外行描述是对象和对象之间态射的抽象集合。类别之间的映射称为函子,将对象映射到对象,将态射映射到态射关联并保留身份。内子是从一个范畴到它自身的函子。

{-# LANGUAGE MultiParamTypeClasses, 
             ConstraintKinds,
             FlexibleInstances,
             FlexibleContexts #-}

class Category c where
  id  :: c x x
  (.) :: c y z -> c x y -> c x z

class (Category c, Category d) => Functor c d t where
  fmap :: c a b -> d (t a) (t b)

type Endofunctor c f = Functor c c f

满足所谓自然性条件的函子之间的映射称为自然变换。在 Haskell 中,这些是类型的多态函数:(Functor f, Functor g) => forall a. f a -> g a.

一个范畴上的单子C是三样东西(T,η,μ)T是内函子和1恒等函子C。Mu 和 eta 是满足三角形恒等式和结合恒等式的两个自然变换,定义为:

  • η : 1 → T
  • μ : T^2 → T

在 Haskellμ中是join并且ηreturn

  • return :: Monad m => a -> m a
  • join :: Monad m => m (m a) -> m a

Haskell 中 Monad 的分类定义可以写成:

class (Endofunctor c t) => Monad c t where
  eta :: c a (t a)
  mu :: c (t (t a)) (t a)

绑定运算符可以从这些派生。

(>>=) :: (Monad c t) => c a (t b) -> c (t a) (t b)
(>>=) f = mu . fmap f

这是一个完整的定义,但等效地,您也可以证明 Monad 定律可以表示为具有函子类别的 Monoid 定律。我们可以构造这个函子范畴,它是以对象为函子(即范畴之间的映射)和自然变换(即函子之间的映射)为态射的范畴。在一个内函子类别中,所有函子都是同一类别之间的函子。

newtype CatFunctor c t a b = CatFunctor (c (t a) (t b))

我们可以证明这产生了一个以函子组合作为态射组合的范畴:

-- Note needs UndecidableInstances to typecheck
instance (Endofunctor c t) => Category (CatFunctor c t) where
  id = CatFunctor id
  (CatFunctor g) . (CatFunctor f) = CatFunctor (g . f)

幺半群具有通常的定义:

class Monoid m where
  unit :: m
  mult :: m -> m -> m

一类函子上的幺半群具有作为恒等式 a 的自然变换和结合自然变换的乘法运算。可以定义 Kleisli 组合以满足乘法定律。

(<=<) :: (Monad c t) => c y (t z) -> c x (t y) -> c x (t z)
f <=< g = mu . fmap f . g 

所以你有它“Monads 只是 endofunctors 类别中的幺半群”,这只是 endofunctors 和 (mu, eta) 的 monads 正常定义的“无点”版本。

instance (Monad c t) => Monoid (c a (t a)) where
  unit = eta
  mult = (<=<)

通过一些替换,我们可以证明(<=<)Are 的等价语句的 monoidal 属性和单子自然变换的关联图。

f <=< unit == f
unit <=< f == f

f <=< (g <=< h) == (f <=< g) <=< h

如果您对图表表示感兴趣,我已经写了一些关于用字符串图表示它们的内容。

于 2013-09-21T06:29:40.863 回答
2

在我看来,您忽略了重要的事情:

  • 定义中有“monoid”一词。您在帖子中没有考虑到它。
  • 为了准确起见,最好将其替换为“monoid object”。幺半群存在于抽象代数中,幺半群对象存在于范畴论中。不同的物种。
    • Monoids 是某个类别中的幺半群对象,但这在这里不相关。
  • 一个幺半群对象只能在一个幺半群类别中定义。

因此,理解该定义的途径如下。

  • 您在 Haskell 类型和函数Hask的类别上考虑一个 endofunctors 类别(我们称之为E ) 。它的对象是Hask上的函子,其中从 F 到 G 的态射是 F a -> G a 类型的多态函数,具有某些属性。
  • 你考虑E上的一个结构,它把它变成一个幺半群,即函子和恒等函子的组合。
  • 您考虑定义一个幺半群对象,例如来自 Wikipedia。
  • 您考虑它在您的特定类别E中的含义。这意味着M是一个内函子,μ和“join”的类型相同,η和“return”的类型相同。
  • “(>>=)”是通过“join”定义的。

一个建议。不要试图用 Haskell 表达一切。它是为编写程序而不是数学而设计的。数学符号在这里更方便,因为您可以将函子的组合写为“∘”,而不会遇到类型检查器的麻烦。

于 2013-09-29T15:04:53.607 回答