我正在阅读Haskell/Category theory,这是该文章中的definition of monad:
monad是一种特殊类型的仿函数,从一个类别到另一个类别 类别,支持一些额外的结构。所以,到了 定义。 monad是一个仿函数 M:C-> C ,还有两个 每个对象X在C 中的态射:
单位:X - > M(X)
加入:M(M(X)) - > M(X)
据我了解,在Haskell中return
相当于unit
。但是return
我可以写:
x :: [Int] -- x is a member of Lst category
x = return 5
这是Haskell中的有效代码。
现在,正如您所看到的,5
此处不是Lst
的成员,但return
适用于此。
所以,我认为Lst
不是С来自 M:C-> C 。但是谁呢?
也许正确答案是Hask
,但我不确定“仿函数从一个类别到其子类别”与“仿函数从一个类别到同一类别“。
答案 0 :(得分:7)
这是一个常见的混淆点,你已经清楚地问了这个问题,以便它可以回答。
我不确定" 仿函数从类别到它的子类别"与" 仿函数相同,从类别到同一类别"。
它不一样。仿函数由四个数据组成:源类别C,目标类别D,C对象到D对象的映射,以及C的态射映射到D的态射,满足某些条件。如果更改D,则更改仿函数。
然而,当我们定义一个仿函数时,我们经常在类别D中有一些选择。我从你的问题中推断Lst
是Hask
的子类别,其对象是{{1}的类型虽然我不确定[a]
的态射应该是什么。我们可以定义这两种形状之一的仿函数Lst
:
[]
:[]
- > Hask
(即Lst
的目标类别为[]
)
Lst
:[]
- > Hask
(即Hask
的目标类别为[]
)
这些是技术上不同的仿函数,我们必须做出选择。在这种情况下,正确的选择是选择2.我们需要源和目标类别相同,因为我们需要在Hask
中将[]
应用于[]
的输出。所以 C = join
和 M = Hask
。
一般来说,考虑像[]
这样被定义为某种类型构造函数的图像的类别很少有用。我不确定这个(非常常见的)想法来自哪里。我建议你不要理会"类别Lst
"。现在只有一个类别就足够了!
对于类比,考虑对实数f(x)= x ^ 2求平方的函数。我们可以将其视为函数f:R - > R从实数到实数,即使碰巧f(x)只取非负实数。 f的目标不必等于f的图像(f对其输入值实际获得的值)。
答案 1 :(得分:0)
根据定义,monad是一个endofunctor。类型类Functor
实际上代表了endofunctors,因为Functor
的实例是为类型构造函数定义的,类型构造函数是类型级函数,它接受一个类型并返回一个新类型(也就是说,它们有类型{{ 1}})。
* -> *
,因此return :: Monad m => a -> m a
可以获取return
类型的值并返回Int
类型的值就不足为奇了。