简体   繁体   English

究竟什么是类别?

[英]What exactly is a category?

I am reading Category Theory for Programmers , and I cannot figure out what exactly a category is. 我正在为程序员阅读分类理论 ,我无法弄清楚究竟是什么类别。

Let's consider the Bool type. 让我们考虑一下Bool类型。 Is Bool a category and True or False are objects (inhabitants)? Bool是一个类别, TrueFalse是对象(居民)?

One reason you're getting a lot of potentially confusing answers is that your question is a little like asking: "Let's consider a soccer ball. Is the soccer ball a 'game' with the black and white polygons its 'pieces'?" 你得到很多可能令人困惑的答案的一个原因是你的问题有点像问:“让我们考虑一个足球。足球是一个'游戏',黑色和白色多边形是'棋子'吗?”

The answer might be @arrowd's answer: "No, you've confused the game of soccer ( Hask ) with its ball ( Bool ), and the polygons ( True and False ) don't matter." 答案可能是@ arrowd的回答:“不,你糊涂足球(游戏Hask其球() Bool ),以及多边形( TrueFalse )并不重要。” Or, it might be @freestyle's answer: "Yes, we could certainly create a game using the soccer ball and assign one player to the black polygons and the other player the white polygons, but what would the rules be?" 或者,它可能是@ freestyle的答案:“是的,我们当然可以使用足球创建一个游戏并将一个玩家分配给黑色多边形而另一个玩家分配白色多边形,但规则是什么?” Or, it might be @Yuval Itzchakov's answer: "Formally, a 'game' is a collection of one or more players, zero or more pieces, and a set of rules such that, etc., etc." 或者,它可能是@Yuval Itzchakov的答案:“正式地,'游戏'是一个或多个玩家的集合,零件或多件,以及一套规则,等等等。”

So, let me add to the confusion with one more (very long) answer, but maybe it will answer your question a little more directly. 所以,让我再加上一个(非常长的)答案的混乱,但也许它会更直接地回答你的问题。

Yes, but it's a boring category 是的,但这是一个无聊的类别

Instead of talking about the Haskell type Bool , let's just talk about the abstract concept of boolean logic and the boolean values true and false. 我们不是谈论Haskell类型的Bool ,而是谈谈布尔逻辑的抽象概念和布尔值true和false。 Can we form a category with the abstract values "true" and "false" as the objects? 我们可以用抽象值“true”和“false”作为对象形成一个类别吗?

The answer is definitely yes. 答案肯定是肯定的。 In fact, we can form (infinitely) many such categories. 事实上,我们可以(无限地)形成许多这样的类别。 All we need to do is explain what the "objects" are, what the "arrows" (sometimes called morphisms) are, and make sure that they obey the formal mathematical rules for categories. 我们需要做的就是解释“对象”是什么,“箭头”(有时称为态射)是什么,并确保它们遵守类别的正式数学规则。

Here is one category: Let the "objects" be "true" and "false", and let there be two "arrows": 这是一个类别:让“对象”为“真”和“假”,并让两个“箭头”:

true -> true
false -> false

Note: Don't confuse this -> notation with Haskell functions. 注意:不要将此->表示法与Haskell函数混淆。 These arrows don't "mean" anything yet, they are just abstract connections between objects. 这些箭头并不“意味着”任何东西,它们只是对象之间的抽象连接。

Now, I know this is a category because it includes both identity arrows (from an object to itself), and it satisfies the composition property which basically says that if I can follow two arrows from a -> b -> c , then there must be a direct arrow a -> c representing their "composition". 现在,我知道这是一个类别,因为它包含两个标识箭头(从一个对象到它自身),它满足组合属性,基本上说如果我可以从a -> b -> c跟随两个箭头,那么必须是一个直接的箭头a -> c代表他们的“组成”。 ( Again , when I write a -> b -> c , I'm not talking about a function type here -- these are abstract arrows connecting a to b and then b to c .) Anyway, I don't have enough arrows to worry too much about composition for this category because I don't have any "paths" between different objects. 同样 ,当我写a -> b -> c ,我不是在这里谈论一个函数类型-这是连接抽象的箭头ab ,然后bc )。无论如何,我没有足够的箭过分担心这个类别的构图,因为我在不同的对象之间没有任何“路径”。 I will call this the "Discrete Boolean" category. 我将其称为“离散布尔”类别。 I agree that it is mostly useless, just like a game based on the polygons of a soccer ball would be pretty stupid. 我同意它几乎没用,就像基于足球多边形的游戏一样非常愚蠢。

Yes, but it has nothing to do with boolean values 是的,但它与布尔值无关

Here's a slightly more interesting category. 这是一个稍微有趣的类别。 Let the objects be "true" and "false", and let the arrows be the two identity arrows above plus: 让对象为“true”和“false”,并让箭头为上面的两个标识箭头加上:

false -> true

This is a category, too. 这也是一个类别。 It has all the identity arrows, and it satisfies composition because, ignoring the identity arrows, the only interesting "path" I can follow is from "false" to "true", and there's nowhere else to go, so I still don't really have enough arrows to worry about the composition rule. 它具有所有的身份箭头,并且它满足构图,因为忽略身份箭头,我可以遵循的唯一有趣的“路径”是从“假”到“真”,并且没有其他地方可去,所以我仍然没有真的有足够的箭头来担心构图规则。

There are a couple more categories you could write down here. 您可以在这里写下几个类别。 See if you can find one. 看看你能找到一个。

Unfortunately, these last two categories don't really have anything to do with the properties of boolean logic. 不幸的是,最后两个类别与布尔逻辑的属性没有任何关系。 It's true that false -> true looks a little like a not operation, but then how could we explain false -> false or true -> true , and why isn't true -> false there, too? 这是真的, false -> true看起来有点像not操作,但那么我们怎么能解释false -> falsetrue -> true ,为什么不是true -> false那也是true -> false

Ultimately, we could just as easily have called these objects "foo" and "bar" or "A" and "B" or not even bothered to name them, and the categories would be just as valid. 最终,我们可以很容易地将这些对象称为“foo”和“bar”或“A”和“B”,甚至不打算给它们命名,这些类别也同样有效。 So, while technically these are categories with "true" and "false" as objects, they don't capture anything interesting about boolean logic. 因此,虽然从技术上讲这些是具有“true”和“false”作为对象的类别,但它们并没有捕获有关布尔逻辑的任何有趣内容。

Quick aside: multiple arrows 快速旁边:多个箭头

Something I haven't mentioned yet is that categories can contain multiple, distinct arrows between two objects, so there could be two arrows from a to b . 我还没有提到的是类别可以在两个对象之间包含多个不同的箭头,因此从ab可能有两个箭头。 To differentiate them, I might give them names, like: 为了区分它们,我可能会给它们命名,例如:

u : a -> b
v : a -> b

I could even have an arrow separate from the identity from b to itself: 我甚至可以从b到自身的标识分开一个箭头:

w : b -> b      -- some non-identity arrow

The composition rule would have to be satisfied by all the different paths. 组合规则必须由所有不同的路径满足。 So, because there's a path u : a -> b and a path w : b -> b (even though it doesn't "go" anywhere else), there would have to be an arrow representing the composition of u followed by w from a -> b . 所以,因为有一个路径u : a -> b和路径w : b -> b (即使它没有“走出去”其他地方),就必须代表组成的箭头u其次是w来自a -> b Its value might be equal to "u" again, or it might be "v", or it might be some other arrow from a -> b . 它的值可能再次等于“u”,或者它可能是“v”,或者它可能是来自a -> b其他箭头。 Part of describing a category is explaining how all the arrows compose and demonstrating that they obey the category laws (the unit law and the associative law, but let's not worry about those laws here). 描述一个类别的部分原因在于解释所有箭头如何构成并证明它们遵守类别法(单位法和联想法,但我们不要在这里担心这些法律)。

Armed with this knowledge, you can create an infinite number of boolean categories just by adding more arrows wherever you want and inventing any rules you'd like about how they should compose, subject to the category laws. 有了这些知识,您可以创建无限数量的布尔类别,只需在任何地方添加更多箭头,并根据类别法则发明您应该如何编写的任何规则。

Sort of, if you use more complicated objects 如果您使用更复杂的对象,则排序

Here's a more interesting category that captures some of the "meaning" of boolean logic. 这是一个更有趣的类别,它捕获了布尔逻辑的一些“含义”。 It's kind of complicated to explain, so bear with me. 解释起来有点复杂,所以请耐心等待。

Let the objects be boolean expressions with zero or more boolean variables: 让对象成为具有零个或多个布尔变量的布尔表达式:

true
false
not x
x and y
(not (y or false)) and x

We'll consider expressions that are "always the same" to be the same object, so y or false and y are the same object, since no matter what the value of y is, they have the same boolean value. 我们将“始终相同”的表达式视为同一个对象,因此y or falsey是同一个对象,因为无论y的值是什么,它们都具有相同的布尔值。 That means that the last expression above could have been written (not y) and x instead. 这意味着上面的最后一个表达式可能已写入(not y) and x

Let the arrows represent the act of setting zero or more boolean variables to specific values. 让箭头表示将零个或多个布尔变量设置为特定值的行为。 We'll label these arrows with little annotations, so that the arrow {x=false,y=true} represents the act of setting two variables as indicated. 我们将使用少量注释标记这些箭头,以便箭头{x=false,y=true}表示设置两个变量的行为。 We'll assume that the settings are applied in order, so the arrow {x=false,x=true} would have the same effect on an expression as {x=false} , even though they're different arrows. 我们假设设置按顺序应用,因此箭头{x=false,x=true}对表达式的影响与{x=false} ,即使它们是不同的箭头。 That means that we have arrows like: 这意味着我们有箭头:

{x=false} : not x -> true
{x=true,y=true} : x and y -> true

We also have: 我们还有:

{x=false} : x and y -> false and y  -- or just "false", the same thing

Technically, the two arrows labelled {x=false} are different arrows. 从技术上讲,标有{x=false}的两个箭头是不同的箭头。 (They can't be the same arrow because they're arrows between different objects.) It's very common in category theory to use the same name for different arrows like this if they have the same "meaning" or "interpretation", like these ones do. (它们不能是相同的箭头,因为它们是不同对象之间的箭头。)在类别理论中,如果它们具有相同的“含义”或“解释”,就像这样使用相同的名称,这是非常常见的,就像这些那些。

We'll define composition of arrows to be the act of applying the sequence of settings in the first arrow and then applying the settings from the second arrow, so the composition of: 我们将箭头的组合定义为在第一个箭头中应用设置序列然后应用第二个箭头的设置的行为,因此组成:

{x=false}: x or y -> y     and    {y=true} : y -> true

is the arrow: 是箭头:

{x=false,y=true}: x or y -> true

This is a category. 这是一个类别。 It has identity arrows for every expression, consisting of not setting any variables: 它为每个表达式都有标识箭头,包括不设置任何变量:

{} : true -> true
{} : not (x or y) and (u or v) -> not (x or y) and (u or v)

It defines composition for every pair of arrows, and the compositions obey the unit and associative laws (again, let's not worry about that detail here). 它为每对箭头定义了构图,并且构图遵循单位和关联定律(再次,我们不要在此担心这个细节)。

And, it represents a particular aspect of boolean logic, specifically the act of calculating the value of a boolean expression by substituting boolean values into variables. 并且,它代表布尔逻辑的一个特定方面,特别是通过将布尔值替换为变量来计算布尔表达式的值的行为。

Hey, look! 你看! A Functor! 一个函子!

It also has a somewhat interesting functor which we might call "Negate". 它也有一个有趣的函子,我们称之为“否定”。 I won't explain what a functor is here. 我不会解释这里的仿函数是什么。 I'll just say that Negate maps this category to itself by: 我只想说Negate通过以下方式将此类别映射到自身:

  • taking each object (boolean expression) to its logical negation 将每个对象(布尔表达式)取为逻辑否定
  • taking each arrow to a new arrow representing the same variable substitutions 将每个箭头移动到表示相同变量替换的新箭头

So, the arrow: 那么,箭头:

{a=false} : (not a) and b -> b

gets mapped by the Negate functor to: 由Negate仿函数映射到:

{a=false} : not ((not a) and b) -> not b

or more simply, using the rules of boolean logic: 或者更简单地说,使用布尔逻辑的规则:

{a=false} : a or (not b) -> not b

which is a valid arrow in the original category. 这是原始类别中的有效箭头。

This functor captures the idea that "negating a boolean expression" is equivalent to "negating its final result", or maybe more generally that the process of substituting variables in a negated expression has the same structure as doing it to the original expression. 该仿函数捕获了“否定布尔表达式”等同于“否定其最终结果”的想法,或者更一般地说,在否定表达式中替换变量的过程具有与对原始表达式相同的结构。 Maybe that's not too exciting, but this is just a long Stack Overflow answer, not a 500-page textbook on Category Theory, right? 也许这不是太令人兴奋,但这只是一个很长的Stack Overflow答案,而不是一本500页的分类理论教科书,对吗?

Bool as part of the Hask category BoolHask类别的一部分

Now, let's switch from talking about abstract boolean categories to your specific question, whether the Bool Haskell type is a category with objects True and False . 现在,让我们从谈论抽象布尔类别转到您的特定问题, Bool Haskell 类型是否是具有对象TrueFalse的类别。

The answers above still apply, to the extent that this Haskell type can be used as a model of boolean logic. 上面的答案仍然适用,只要这个Haskell类型可以用作布尔逻辑的模型。

However, when people talk about categories in Haskell, they are usually talking about a specific category Hask where: 但是,当人们在Haskell中讨论类别时,他们通常会讨论特定类别Hask ,其中:

  • the objects are types (like Bool , Int , etc.) 对象是类型(如BoolInt等)
  • the arrows are Haskell functions (like f :: Int -> Double ). 箭头是Haskell函数(如f :: Int -> Double )。 Finally , the Haskell syntax and our abstract category syntax coincide -- the Haskell function f can be thought of as an arrow from the object Int to the object Double ). 最后 ,Haskell语法和我们的抽象类别语法重合 - Haskell函数f可以被认为是从对象Int到对象Double的箭头。
  • composition is regular function composition 成分是规律的功能成分

If we are talking about this category, then the answer to your question is: no, in the Hask category, Bool is one of the objects, and the arrows are Haskell functions like: 如果我们在讨论这个类别,那么你的问题的答案是:不,在Hask类别中, Bool是其中一个对象,而箭头是Haskell函数,如:

id :: Bool -> Bool
not :: Bool -> Bool
(==0) :: Int -> Bool

foo :: Bool -> Int
foo b = if b then 10 else 15

To make things more complicated, the objects also include types of functions, so Bool -> Bool is one of the objects. 为了使事情变得更复杂,对象包括函数类型,因此Bool -> Bool是其中一个对象。 One example of an arrow that uses this object is: 使用此对象的箭头的一个示例是:

and :: Bool -> (Bool -> Bool)

which is an arrow from the object Bool to the object Bool -> Bool . 这是从Bool对象到Bool -> Bool对象的箭头Bool -> Bool

In this scenario, True and False aren't part of the category. 在这种情况下, TrueFalse不属于该类别。 Haskell values for function types, like sqrt or length are part of the category because they're arrows, but True and False are non-function types, so we just leave them out of the definition. 函数类型的Haskell值(如sqrtlength是类别的一部分,因为它们是箭头,但TrueFalse是非函数类型,因此我们将它们排除在定义之外。

Category Theory 分类理论

Note that this last category, like the first categories we looked at, has absolutely nothing to do with boolean logic, even though Bool is one of the objects. 请注意,最后一个类别,就像我们查看的第一个类别一样,与布尔逻辑完全无关,即使Bool是其中一个对象。 In fact, in this category, Bool and Int look about the same -- they're just two types that can have arrows leaving or entering them, and you'd never know that Bool was about true and false or that Int represented integers, if you were just looking at the Hask category. 事实上,在这个类别中, BoolInt看起来大致相同 - 它们只是两种类型,可以有箭头离开或进入它们,你永远不会知道Bool是关于真和假,或者Int表示整数,如果你只是看看Hask类别。

This is a fundamental aspect of category theory. 这是范畴理论的一个基本方面。 You use a specific category to study a specific aspect of some system. 您使用特定类别来研究某个系统的特定方面。 Whether or not Bool is a category or a part of category is sort of a vague question. Bool是一个类别还是类别的一部分是一个模糊的问题。 The better question would be, "is this particular aspect of Bool that I'm interest in something that can be represented as a useful category?" 更好的问题是,“ Bool这个特殊方面是我对可以表现为有用类别的东西感兴趣吗?”

The categories I gave above roughly correspond to these potentially interesting aspects of Bool : 我上面给出的类别大致对应于Bool这些可能有趣的方面:

  • The "Discrete Boolean" category represents Bool as a plain mathematical set of two objects, "true" and "false", with no additional interesting features. “离散布尔”类别将Bool表示为两个对象的简单数学集合,“true”和“false”,没有其他有趣的特征。
  • The "false -> true" category represents an ordering of boolean values, false < true , where each arrow represents the operator '<='. “false - > true”类别表示布尔值的排序, false < true ,其中每个箭头表示运算符“<=”。
  • The boolean expression category represents an evaluation model for simple boolean expressions. 布尔表达式类别表示简单布尔表达式的评估模型。
  • Hask represents the composition of functions whose input and output types may be a boolean type or a functional type involving boolean and other types. Hask表示函数的组合,其输入和输出类型可以是布尔类型或涉及布尔和其他类型的函数类型。

If you are talking about Hask category, then no. 如果你在谈论Hask类别,那么没有。 Hask is the category and the objects are Haskell types. Hask是类别,对象是Haskell类型。 That is, Bool is an object, and True / False aren't even talked about here. 也就是说, Bool是一个对象,在这里甚至没有谈到True / False The description of Hask can be found on Haskell wiki . Hask的描述可以在Haskell wiki上找到。 There are also talks, that Hask isn't even a proper category, read this . 还有会谈, Hask甚至不是一个合适的类别, 请阅读此内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM