Haskell中的所有类型类都有类别理论模拟吗?

时间:2016-05-21 19:55:46

标签: haskell category-theory

考虑一个类型为* -> *的类型类。例如:Functor类型类。众所周知,在Haskell中,这种类型类与其数学(即类别理论)类似物之间存在对应关系。泛化:

问题1: Haskell中每个成员都属于* -> *类型的每个类型对应于类别之间的某些函数吗?

现在考虑一个类型为*的类型类。例如,可以想象一个类型类Group,它对应于组的类别(从技术上讲,Group将是Hask的子类别,其对象包含所有Haskell的类型)。泛化:

问题2: Haskell中其成员属于*的每个类型类都与某些类别相对应(技术上:Hask的某个子类别)?

由此可以提出下一个一般性问题:

问题3:类似等于或高于* -> * -> *的类型对应于某种类别的理论概念吗?

实际上,整个问题可归纳如下:

一般问题:每个Haskell类型类都对应一些类别理论概念吗?

编辑:至少,您似乎可以说,因为每个类型类都包含一些Haskell类型作为其成员,您可以将每个类型类视为 some Hask的子类别(在.下关闭,并使用id)。

3 个答案:

答案 0 :(得分:15)

当充分迂腐地解释时,所有这些问题的答案都是"是",但是出于无意义的微不足道的原因。

每个类别C都限制为离散的子类别| C |与C相同的对象,但只有身份态射(因此没有有趣的结构)。至少,Haskell类型的操作可以被解释为离散类别|*|上的操作。最近的角色"故事相当于(但不是旋转)试图承认态射是重要的,而不仅仅是物体。 "名义上"类型的角色相当于|*|而不是*

(注意,我不喜欢使用&#34; Hask&#34;作为&#34; Haskell类型和函数类别的名称&#34;:我担心将一个类别标记为 < / H> Haskell类别具有令人遗憾的副作用,使我们对Haskell编程中其他分类结构的丰富性感到盲目。它是一个陷阱。)

作为一种不同的迂腐,我注意到你可以把任何旧的废话作为任何旧类型的类型组合,没有任何有趣的结构(但是具有微不足道的结构仍然可以断言,如果必须的话)。但是,您在库中找到的类通常是结构丰富的。超过* -> *的类通常是Functor的子类,除了fmap之外,还需要存在某些自然变换。

对于问题2.是的,当然,*以上的课程提供了*的子类别。从一个类别中删除对象没有问题,因为存在身份和复合的分类要求需要态射存在,给定对象,但不要求哪些对象< / em>存在。事实上它很有可能使它成为一个无聊的事实。但是,*之上的许多Haskell类型类比*的子类别产生的更有趣的类别。例如,Monoid类为我们提供了一个类别,其中对象是Monoid的实例,箭头是 monoid homomorphisms :不只是一个旧函数f Monoid到另一个,但保留结构:f mempty = memptyf (mappend x y) = mappend (f x) (f y)

对于问题3,好吧,因为到处都是潜伏着大量的分类结构,当然还有很多类别的分类结构(可能但不一定)。我特别喜欢索引族集之间的仿函数。

type (s :: k -> *) :-> (t :: k -> *) = forall x. s x -> t x

class FunctorIx (f :: (i -> *) -> (j -> *)) where
  mapIx :: (s :-> t) -> (f s :-> f t)

ij重合时,询问这样的f何时是monad是明智的。通常的分类定义就足够了,即使我们已经离开了* -> *

消息是这样的:没有任何关于成为类型类的内容会诱导有趣的分类结构;有很多有趣的分类结构,可以通过各种类型的类型类来有效地呈现。从*(集合和函数)到* -> *(函子和自然变换),肯定有一些有趣的函子。不要粗心地谈论&#34; Hask&#34;哈斯克尔的分类结构的丰富性。

答案 1 :(得分:6)

这里的一个问题是,类别理论,即一般的抽象废话,是一种可以用来谈论数学中几乎任何事物的理论。因此,我们所谈论的所有内容都可以使用类别理论的语言来表达,但我们可能不会产生任何有趣的结果。

  

Haskell中每个成员类型* -> *的每个类型类都对应于类别之间的某个函数吗?

否。此问题包含类型错误!函数映射设置为集,但类别不是集。 (换句话说,函数是类别Set中的态射。)类别是使用类来制定的,通常是适当的类,因此您无法将类别提供给函数。

我们会在Haskell类型的类别中调用* -> *态射中的对象。此类别的子类别是Haskell类型之间的仿函数类别,称为Functor

  

Haskell中其成员属于*的每个类型类是否对应于某个类别(技术上:Hask的某个子类别)?

是的。这是事实,但并不是非常有趣。只需从Hask中删除不在类型类中的每个对象,并删除Hask中不消耗的任何态射并从类型类中生成元素,并留下Hask的子类别。此类别应至少包含一个对象和至少一个态射id

  

等于或高于* -> * -> *的类型对应于某种类别的理论概念吗?

是的。再次,这不会很有趣。我们来看一个类型为X的类型* -> * -> *

X是一个具有相同种类的类型类中的对象吗?嗯,是。但是这个类别并不是很有趣,因为很难想象任何非平凡的态射。

X是某种类别的态射?不,因为它无法组成。

X是一个算子,它将Hask中类型的子类别映射到Hask中类型的态射的子类别吗?当然,但在我们允许态射进入Hask类型的起始子类别之前,我们必须有一些特殊的知识,X Y a bX Z a b允许同一a b

在我看来,这并不会产生任何有用的见解,这并不奇怪,因为我们对X一无所知。

结论

类别理论是一种非常容易过度思考和过度使用的工具之一。如果您对类别理论本身并不感兴趣,我的建议是找到使用它的具体动机。特定的类型类(仿函数,透镜,monad,comonads等)有时会为您提供足够的结构或“原始数学材料”,您可以从中构建类别理论中的有趣证明。但是对类型类的研究总的来说可能比它有用更抽象。

答案 2 :(得分:3)

可以想象不保留其分类结构的类别之间的映射。但它们并不有趣。在类别理论中,我们希望使用结构保留映射,这些称为仿函数。

*->*类型的裸型构造函数没有提供映射态射的规定。所以,正如@pigworker所解释的那样,你能做的最好的事情就是将它们解释为来自| C |的函子到C,只是因为| C |没有非平凡的态射被映射。

Haskell Functor是一个endofunctor,只要它满足仿函数法则(不能在Haskell中强制执行)。 endofunctor不是它映射的类别中的对象,因此不是类型。但是对于态射也是如此 - 它们不是物体。但是,如果类别支持指数,则有一种方法可以将态射表示为对象。 Haskell的类型类型是笛卡尔闭合的,因此它支持指数。

那么它是否也提供了代表endofunctors的对象(类型)?据我所知,它没有。因此,仿函数不是Hask的成员(或者我们称之为的任何东西)。

顺便提一下,*->*->*种类的映射可以作为一个非平凡的分类解释作为bifunctor - 从产品类别CxC到C的结构保留仿函数。请参阅Haskell中Bifunctor的定义。