Haskell中的所有Monad实例是否都有不同的方式从Hask映射到Hask?

时间:2017-01-12 12:11:00

标签: haskell monads category-theory

我正在阅读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,但我不确定“仿函数从一个类别到其子类别”与“仿函数从一个类别到同一类别“。

2 个答案:

答案 0 :(得分:7)

这是一个常见的混淆点,你已经清楚地问了这个问题,以便它可以回答。

  

我不确定" 仿函数从类别到它的子类别"与" 仿函数相同,从类别到同一类别"。

它不一样。仿函数由四个数据组成:源类别C,目标类别D,C对象到D对象的映射,以及C的态射映射到D的态射,满足某些条件。如果更改D,则更改仿函数。

然而,当我们定义一个仿函数时,我们经常在类别D中有一些选择。我从你的问题中推断LstHask的子类别,其对象是{{1}的类型虽然我不确定[a]的态射应该是什么。我们可以定义这两种形状之一的仿函数Lst

  1. [][] - > Hask(即Lst的目标类别为[]

  2. Lst[] - > Hask(即Hask的目标类别为[]

  3. 这些是技术上不同的仿函数,我们必须做出选择。在这种情况下,正确的选择是选择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类型的值就不足为奇了。