<p><a href="https://en.wikipedia.org/wiki/Algebraic_data_type" rel="noreferrer">Algebraic data types</a> include two concepts with names that feel like they imply something clever, but that I can't for the life of me understand:</p>
<ul>
<li>Sum type: This refers to tagged unions, like Rust's enums</li>
<li>Product type: This refers to collection types like tuples and structs</li>
</ul>
<p>Why are these referred to using mathematical language? What makes the former more addition-like and the latter more product-like? It feels like these imply some sort of relationship and symmetry that's present in algebra, but I can't figure out what that would be.</p>

<terminology><algebraic-data-types>
What is implied by the names "sum type" and "product type"?
CC BY-SA 4.0
2023-05-19T16:02:28.647Z
Could someone please spell out what makes this question off-topic? The [help center](https://languagedesign.stackexchange.com/help) does not yet include a definition of the scope of programming-language design and implementation.
Ben Kovitz
CC BY-SA 4.0
2023-05-19T16:24:38.867Z
@BenKovitz Perhaps because it could've been answered by a simple Google search. It's already been [asked](https://stackoverflow.com/questions/5911267/what-are-sums-and-products-data-structures) on Stack Overflow. However, it's probably useful to have a question like this on PLDI too, I don't get the downvotes
user
CC BY-SA 4.0
2023-05-19T19:23:27.830Z
There is a similar question on another site: https://proofassistants.stackexchange.com/q/879/32
ice1000
CC BY-SA 4.0
2023-05-19T19:25:48.880Z
One more funnily and unexplainedly downvoted question :)
ice1000
CC BY-SA 4.0
2023-05-22T09:10:44.410Z
[Related code golf challenge](https://codegolf.stackexchange.com/q/236249/9288).
alephalpha
<h1>Category Theory</h1>
<p>Those terms have meaning in category theory.</p>
<p>The <em>direct product</em> of two objects <code>A</code> and <code>B</code> in a category is an object <code>P</code> together with a pair of morphisms <code>π₁ : P -&gt; A</code> and <code>π₂ : P -&gt; B</code> called <em>projections</em> such that it is, in some sense, the smallest such object.</p>
<p><a href="https://mermaid.live/edit#pako:eNqrVkrOT0lVslIqLkksSXXJTEwvSszVLTOKyVMAggAFXV07BUcrhfMNj5oakcWcIGJNSjpKualFuYmZKUAzqkEqYpRKMlJzU2OUrIDMlNS0xNKckhilmLxaoNLE0pL84Mq8ZCWrkqLSVB2l0oIUhK1KVmmJOcWptQDKcjEV" rel="noreferrer"><img src="https://mermaid.ink/img/pako:eNqrVkrOT0lVslIqLkksSXXJTEwvSszVLTOKyVMAggAFXV07BUcrhfMNj5oakcWcIGJNSjpKualFuYmZKUAzqkEqYpRKMlJzU2OUrIDMlNS0xNKckhilmLxaoNLE0pL84Mq8ZCWrkqLSVB2l0oIUhK1KVmmJOcWptQDKcjEV?type=png" alt="" /></a></p>
<p>Precisely, the requirement is that if we have another candidate <code>P'</code> and morphisms <code>π'₁ : P' -&gt; A</code> and <code>π'₂ : P' -&gt; B</code>, then there must be a unique map <code>f : P' -&gt; P</code> such that the following diagram commutes.</p>
<p><a href="https://mermaid.live/edit#pako:eNqrVkrOT0lVslIqLkksSXXJTEwvSszVLTOKyVMAggB1BV1dOwVHK4XzDeqPmhpRRJ2gok0oogFWCmlQAYRehFaETqBGJR2l3NSi3MTMFKADqkEqYpRKMlJzU2OUrIDMlNS0xNKckhilmLxaoNLE0pL84Mq8ZCWrkqLSVB2l0oIUhJOVrNISc4pTawHk5EHe" rel="noreferrer"><img src="https://mermaid.ink/img/pako:eNqrVkrOT0lVslIqLkksSXXJTEwvSszVLTOKyVMAggB1BV1dOwVHK4XzDeqPmhpRRJ2gok0oogFWCmlQAYRehFaETqBGJR2l3NSi3MTMFKADqkEqYpRKMlJzU2OUrIDMlNS0xNKckhilmLxaoNLE0pL84Mq8ZCWrkqLSVB2l0oIUhJOVrNISc4pTawHk5EHe?type=png" alt="" /></a></p>
<p>&quot;Commutes&quot; is just a fancy category theory term for &quot;if there are multiple paths that go from one point to another, they must be equal&quot;. In this diagram, that means <code>π₁∘f = π'₁</code> and <code>π₂∘f = π'₂</code>. That is, <code>P</code> is the &quot;best&quot; product in the sense that any other product is necessarily just &quot;<code>P</code> with some extra&quot;.</p>
<p>In the category of types in a particular programming language, the categorical product of <code>A</code> and <code>B</code> is the type of tuples containing an <code>A</code> and a <code>B</code>, and the projection maps extract an <code>A</code> and a <code>B</code> from it respectively. Any other type which contains an <code>A</code> and a <code>B</code> must necessarily be isomorphic to &quot;a tuple plus some extra&quot;.</p>
<p>Note that this representation is only unique up to isomorphism (up to a unique isomorphism, which is more powerful but in ways that aren't relevant here). <code>(A, B)</code> is a valid direct product of <code>A</code> and <code>B</code>. So is <code>(B, A)</code>. And so is the structure</p>
<pre><code>struct HelloThere {
  a: A,
  b: B,
}
</code></pre>
<p>All of these are distinct types but are isomorphic, and they are all valid products of the two input types.</p>
<p>Likewise, the <em>direct sum</em> or coproduct is the dual of the product, which means it's the above diagrams with all the arrows reversed. More precisely, the direct sum is an object <code>I</code> together with a pair of morphisms <code>i₁ : A -&gt; I</code> and <code>i₂ : B -&gt; I</code>.</p>
<p><a href="https://mermaid.live/edit#pako:eNqrVkrOT0lVslIqLkksSXXJTEwvSszVLTOKyVMAAkcFXV07BU8rhcxHTY0QISckoSYlHaXc1KLcxMwUoAnVIAUxSiUZqbmpMUpWQGZKalpiaU5JjFJMXi1QaWJpSX5wZV6yklVJUWmqjlJpQQrCTiWrtMSc4tRaAPggLzs" rel="noreferrer"><img src="https://mermaid.ink/img/pako:eNqrVkrOT0lVslIqLkksSXXJTEwvSszVLTOKyVMAAkcFXV07BU8rhcxHTY0QISckoSYlHaXc1KLcxMwUoAnVIAUxSiUZqbmpMUpWQGZKalpiaU5JjFJMXi1QaWJpSX5wZV6yklVJUWmqjlJpQQrCTiWrtMSc4tRaAPggLzs?type=png" alt="" /></a></p>
<p>Note that we've reversed the directions of our arrows. Instead of projections out of our type <code>P</code>, we have <em>injections</em> into <code>I</code>.</p>
<p>Again, we get a universal property, stating that <code>I</code> must be the <em>best</em> sum. So given <code>I'</code>, <code>i'₁ : A -&gt; I'</code>, and <code>i'₂ : B -&gt; I'</code>, we must get an <code>f : I -&gt; I'</code> with the following commutative diagram.</p>
<p><a href="https://mermaid.live/edit#pako:eNqrVkrOT0lVslIqLkksSXXJTEwvSszVLTOKyVMAAkcFXV07BU91K4VM9UdNjRBBJxTBJoigJ1wwDUUrUBG6RrBQk5KOUm5qUW5iZgrQ8mqQghilkozU3NQYJSsgMyU1LbE0pyRGKSavFqg0sbQkP7gyL1nJqqSoNFVHqbQgBeFcJau0xJzi1FoArgk-HA" rel="noreferrer"><img src="https://mermaid.ink/img/pako:eNqrVkrOT0lVslIqLkksSXXJTEwvSszVLTOKyVMAAkcFXV07BU91K4VM9UdNjRBBJxTBJoigJ1wwDUUrUBG6RrBQk5KOUm5qUW5iZgrQ8mqQghilkozU3NQYJSsgMyU1LbE0pyRGKSavFqg0sbQkP7gyL1nJqqSoNFVHqbQgBeFcJau0xJzi1FoArgk-HA?type=png" alt="" /></a></p>
<p>i.e., <code>f∘i₁ = i'₁</code> and <code>f∘i₂ = i'₂</code>. It so happens that, in the category of types, this direct sum object manifests as the disjoint, or tagged, union (which Haskell calls <code>Either</code>).</p>
<p>You'll also sometimes hear function types called <em>exponential types</em>, which as a similar categorical relationship to the <em>exponential object</em>. I'll sometimes write <code>A -&gt; B</code> and <code>B^A</code> (Note: The result type is the <em>base</em> of the exponent) interchangeably in what follows, when it makes sense for the explanation.</p>
<p>But why did we choose these names in category theory? Lots of reasons, actually!</p>
<p>First, we can make a cardinality argument. I'll borrow notation from set theory and write <code>|A|</code> to denote the cardinality of the set underlying our type. If you don't know what cardinality is, just think of it as &quot;the number of possible distinct elements in your type&quot;. We have the following, for all types <code>A</code> and <code>B</code>.</p>
<ul>
<li><code>|A + B| = |A| + |B|</code>. The number of elements in the disjoint union is equal to the sum of the sizes of each type.</li>
<li><code>|A × B| = |A| × |B|</code>. The number of elements in the tuple type is equal to the product of the sizes of each type.</li>
<li><code>|A ^ B| = |A| ^ |B|</code>. The number of functions from <code>B</code> to <code>A</code> is equal to the size of <code>A</code> raised to the power of that of <code>B</code>.</li>
</ul>
<p>So if all we care about is counting, then these operations match precisely our intuitive notions in ordinary arithmetic.</p>
<p>But there's more! These categorical objects behave a lot like ordinary arithmetic ones in more ways than just counting.</p>
<p>They're commutative.</p>
<ul>
<li><code>A × B ≅ B × A</code></li>
<li><code>A + B ≅ B + A</code></li>
</ul>
<p>They're associative.</p>
<ul>
<li><code>(A × B) × C ≅ A × (B × C)</code></li>
<li><code>(A + B) + C ≅ A + (B + C)</code></li>
</ul>
<p>and they even distribute.</p>
<ul>
<li><code>(A + B) × C ≅ A × C + B × C</code></li>
<li><code>A × (B + C) ≅ A × C + A × C</code></li>
</ul>
<p>The exponential (function) types are well behaved too. Take a moment to think about what these mean, as types, as these can be a bit less trivial to immediately see.</p>
<ul>
<li><code>(A × B) ^ C ≅ A ^ C × B ^ C</code></li>
<li><code>A ^ (B + C) ≅ A ^ B × A ^ C</code></li>
<li><code>(A ^ B) ^ C ≅ A ^ (B × C)</code></li>
</ul>
<p>We can go one step further. In category theory, we often denote the <em>initial object</em> of a category as <code>0</code> and the <em>terminal object</em> as <code>1</code>. Under those definitions, in the category of types in our hypothetical language, the initial object <code>0</code> is <code>Void</code>, the empty type, and the terminal object <code>1</code> is <code>Unit</code>, the type having one value. These numbers also behave neatly in this model.</p>
<ul>
<li><code>A + 0 ≅ 0 + A ≅ A</code></li>
<li><code>A × 1 ≅ 1 × A ≅ A</code></li>
<li><code>A × 0 ≅ 0 × A ≅ 0</code></li>
<li><code>A ^ 0 ≅ 1</code></li>
<li><code>0 ^ A ≅ 0</code> (if <code>A</code> is nonempty)</li>
<li><code>1 ^ A ≅ 1</code></li>
<li><code>A ^ 1 ≅ A</code></li>
</ul>
<p>In summary, we call these types sums, products, exponentials, <code>0</code>, and <code>1</code>, because when we actually write down all of the nice arithmetic properties of addition, multiplication, powers, zero, and one, it turns out that these are the types that satisfy those properties.</p>
<hr />
<p>Side note: You'll notice I switched from using <code>=</code> to <code>≅</code> halfway through. I use <code>≅</code> to denote <em>isomorphism</em>. It's true that <code>(A × B) × C</code> is not actually <em>equal</em> to <code>A × (B × C)</code>, since the first looks like <code>((a, b), c)</code> and the second looks like <code>(a, (b, c))</code>, but they store the same information. The notion of isomorphism makes that rigorous. In fact, all of the above isomorphisms are <em>natural</em> in their arguments, which means that the types are related in a uniform way that doesn't depend on the specific structure of the arguments.</p>

CC BY-SA 4.0
2023-05-19T19:35:20.883Z
2023-05-19T19:35:20.883Z
Silvio Mayolo
CC BY-SA 4.0
2023-05-20T22:11:50.700Z
While presenting the category theory model is interesting, it makes the concepts look more complicated than they are. The vocabulary of category theory comes from set theory and the set theory model is rather easier to understand.
Gilles 'SO- stop being evil'
<h1>You count the number of distinct elements.</h1>
<p>Let's forget about types with infinite many elements and only look at finite ones.</p>
<p>Suppose <code>A</code> have 5 instances, and <code>B</code> have 6 instances. The sum of <code>A</code> and <code>B</code>, which you know the definition of, has 11 instances in total. The product of <code>A</code> and <code>B</code> have 30 instances in total. Hence the names.</p>
<p>These are not the essential reasons, but this is an intuitive explanation I believe.</p>

CC BY-SA 4.0
2023-05-19T19:25:32.693Z
2023-05-19T19:25:32.693Z
ice1000
<p>For this example, we'll consider 2 datatypes: letters L <code>abcdef</code> and numbers <code>123456</code> N.</p>
<h2>A sum type contains all elements in A or B</h2>
<p>So L+N would be <code>abcdef123456</code></p>
<p>This is a &quot;Sum&quot; because the number of items in the resulting type is the sum of the number of items in each subtype.</p>
<p>The sum of 0 types creates a never type, a type with no elements.</p>
<h2>The union type</h2>
<p>You didn't ask about the union type, but let me explain anyway. The union type, in typescript <code>|</code> or a untagged union, is like sum but duplicate items are counted only once. So <code>L+L</code> has 12 elements, each letter twice with a different tag, while <code>L|L</code> has only 6 elements: The letters themselves.</p>
<h2>A product type contains all combinations of elements in A and B</h2>
<p>The product of A*B would be <code>[('a', '1'), ('a', '2'), ('a', '3'), ('a', '4'), ('a', '5'), ('a', '6'), ('b', '1'), ('b', '2'), ('b', '3'), ('b', '4'), ('b', '5'), ('b', '6'), ('c', '1'), ('c', '2'), ('c', '3'), ('c', '4'), ('c', '5'), ('c', '6'), ('d', '1'), ('d', '2'), ('d', '3'), ('d', '4'), ('d', '5'), ('d', '6'), ('e', '1'), ('e', '2'), ('e', '3'), ('e', '4'), ('e', '5'), ('e', '6'), ('f', '1'), ('f', '2'), ('f', '3'), ('f', '4'), ('f', '5'), ('f', '6')]</code>.</p>
<p>This is called a product, or Cartesian product, because its length is the product of the lengths of each of the types. Things get a bit more complex when types have infinite lengths.</p>
<p>The product of nothing is often defined to have one element, the unit type, as \$0^0\ = 1$. This allows you to construct types from nothing by then summing unit types.</p>

CC BY-SA 4.0
2023-05-19T15:05:44.060Z
2024-08-18T19:11:25.630Z
2024-08-18T19:11:25.630Z
mousetail 'he-him'
CC BY-SA 4.0
2024-08-25T13:01:08.350Z
Minor nit: the sum of `L` and `N` (unlike the union of the two) has values *created* from the values of `L` and `N`, not the values from `L` and `N` themselves.
chepner
CC BY-SA 4.0
2023-05-19T15:12:02.627Z
Is the unit type considered to be bottom? I've always thought those were two veeeeery different things, at least in the Haskell world.
Unrelated String
CC BY-SA 4.0
2023-05-19T15:33:59.807Z
“0^0 = 1” — \[citation needed\]
Bbrk24
CC BY-SA 4.0
2023-05-19T15:38:37.323Z
@Bbrk24 In type theory yes
mousetail 'he-him'
CC BY-SA 4.0
2023-05-19T16:26:28.877Z
@UnrelatedString mousetail isn't saying unit is bottom, they're saying the product of nothing and nothing is unit. The unit type has one inhabitant, while the bottom type has none
user
CC BY-SA 4.0
2023-05-19T16:26:47.527Z
I think TypeScript’s union is `|`, not `&`— `&` gets the intersection of two types (what they share) while `|` gets the elements of each, ignoring duplicates
Jacob
CC BY-SA 4.0
2023-05-19T16:28:19.607Z
I agree with what Jacob said. I'm pretty sure `|` = union and `&` = intersection is standard terminology in other languages too. `|` is `+`
user
CC BY-SA 4.0
2023-05-19T16:43:49.567Z
@mousetail Thanks for the edit but it's still wrong: `|` is a proper sum type, it doesn't care about duplicates. `&` is the one that only counts them once (you were right about that before).
user
CC BY-SA 4.0
2023-05-19T20:33:46.400Z
@user the product of nothing and nothing is nothing, not unit.
ice1000
CC BY-SA 4.0
2023-05-19T20:52:08.400Z
The product of no types is unit, the product of never and never is never
mousetail 'he-him'
CC BY-SA 4.0
2023-05-19T22:00:54.197Z
@ice1000 Oh right, you can't make a tuple of nothings
user
CC BY-SA 4.0
2023-05-19T22:01:09.110Z
@mousetail What does "the product of no types" mean, then?
user
CC BY-SA 4.0
2023-05-20T06:35:42.033Z
@user Well consider `(a,b)` is a tuple of 2 types, then `()` is a tuple containing no types. It has 1 element: The unit type
mousetail 'he-him'
# What is implied by the names "sum type" and "product type"?
Posted by: username_0 on 2023-05-19
[Algebraic data types](https://en.wikipedia.org/wiki/Algebraic_data_type) include two concepts with names that feel like they imply something clever, but that I can't for the life of me understand:

* Sum type: This refers to tagged unions, like Rust's enums
* Product type: This refers to collection types like tuples and structs

Why are these referred to using mathematical language? What makes the former more addition-like and the latter more product-like? It feels like these imply some sort of relationship and symmetry that's present in algebra, but I can't figure out what that would be.
**Tags:** terminology algebraic-data-types
> **Comments:**
> **username_1**: Could someone please spell out what makes this question off-topic? The [help center](https://languagedesign.stackexchange.com/help) does not yet include a definition of the scope of programming-language design and implementation.  
> **username_2**: @BenKovitz Perhaps because it could've been answered by a simple Google search. It's already been [asked](https://stackoverflow.com/questions/5911267/what-are-sums-and-products-data-structures) on Stack Overflow. However, it's probably useful to have a question like this on PLDI too, I don't get the downvotes  
> **username_3**: There is a similar question on another site: https://proofassistants.stackexchange.com/q/879/32  
> **username_3**: One more funnily and unexplainedly downvoted question :)  
> **username_4**: [Related code golf challenge](https://codegolf.stackexchange.com/q/236249/9288).  
---
## 3 answers
### Answer by username_3 on 2023-05-19. Score: 18
# You count the number of distinct elements.

Let's forget about types with infinite many elements and only look at finite ones.

Suppose `A` have 5 instances, and `B` have 6 instances. The sum of `A` and `B`, which you know the definition of, has 11 instances in total. The product of `A` and `B` have 30 instances in total. Hence the names.

These are not the essential reasons, but this is an intuitive explanation I believe.
---
### Answer by username_7 on 2023-05-19. Score: 15
For this example, we'll consider 2 datatypes: letters L `abcdef` and numbers `123456` N.

## A sum type contains all elements in A or B

So L+N would be `abcdef123456`

This is a "Sum" because the number of items in the resulting type is the sum of the number of items in each subtype.

The sum of 0 types creates a never type, a type with no elements.

## The union type

You didn't ask about the union type, but let me explain anyway. The union type, in typescript `|` or a untagged union, is like sum but duplicate items are counted only once. So `L+L` has 12 elements, each letter twice with a different tag, while `L|L` has only 6 elements: The letters themselves.

## A product type contains all combinations of elements in A and B

The product of A\*B would be `[('a', '1'), ('a', '2'), ('a', '3'), ('a', '4'), ('a', '5'), ('a', '6'), ('b', '1'), ('b', '2'), ('b', '3'), ('b', '4'), ('b', '5'), ('b', '6'), ('c', '1'), ('c', '2'), ('c', '3'), ('c', '4'), ('c', '5'), ('c', '6'), ('d', '1'), ('d', '2'), ('d', '3'), ('d', '4'), ('d', '5'), ('d', '6'), ('e', '1'), ('e', '2'), ('e', '3'), ('e', '4'), ('e', '5'), ('e', '6'), ('f', '1'), ('f', '2'), ('f', '3'), ('f', '4'), ('f', '5'), ('f', '6')]`.

This is called a product, or Cartesian product, because its length is the product of the lengths of each of the types. Things get a bit more complex when types have infinite lengths.

The product of nothing is often defined to have one element, the unit type, as \$0^0\ = 1$. This allows you to construct types from nothing by then summing unit types.
> **Comments:**
> **username_9** (2023-05-19): Is the unit type considered to be bottom? I've always thought those were two veeeeery different things, at least in the Haskell world.  
> **username_10** (2023-05-19): “0^0 = 1” — \[citation needed\]  
> **username_7** (2023-05-19): @Bbrk24 In type theory yes  
> **username_2** (2023-05-19): @UnrelatedString mousetail isn't saying unit is bottom, they're saying the product of nothing and nothing is unit. The unit type has one inhabitant, while the bottom type has none  
> **username_11** (2023-05-19): I think TypeScript’s union is `|`, not `&`— `&` gets the intersection of two types (what they share) while `|` gets the elements of each, ignoring duplicates  
> **username_2** (2023-05-19): I agree with what Jacob said. I'm pretty sure `|` = union and `&` = intersection is standard terminology in other languages too. `|` is `+`  
> **username_2** (2023-05-19): @mousetail Thanks for the edit but it's still wrong: `|` is a proper sum type, it doesn't care about duplicates. `&` is the one that only counts them once (you were right about that before).  
> **username_3** (2023-05-19): @user the product of nothing and nothing is nothing, not unit.  
> **username_7** (2023-05-19): The product of no types is unit, the product of never and never is never  
> **username_2** (2023-05-19): @ice1000 Oh right, you can't make a tuple of nothings  
> **username_2** (2023-05-19): @mousetail What does "the product of no types" mean, then?  
> **username_7** (2023-05-20): @user Well consider `(a,b)` is a tuple of 2 types, then `()` is a tuple containing no types. It has 1 element: The unit type  
> **username_8** (2024-08-25): Minor nit: the sum of `L` and `N` (unlike the union of the two) has values *created* from the values of `L` and `N`, not the values from `L` and `N` themselves.  
---
### Answer by username_5 on 2023-05-19. Score: 12
Category Theory
Those terms have meaning in category theory.
The direct product of two objects A and B in a category is an object P together with a pair of morphisms π₁ : P -> A and π₂ : P -> B called projections such that it is, in some sense, the smallest such object.

Precisely, the requirement is that if we have another candidate P' and morphisms π'₁ : P' -> A and π'₂ : P' -> B, then there must be a unique map f : P' -> P such that the following diagram commutes.

"Commutes" is just a fancy category theory term for "if there are multiple paths that go from one point to another, they must be equal". In this diagram, that means π₁∘f = π'₁ and π₂∘f = π'₂. That is, P is the "best" product in the sense that any other product is necessarily just "P with some extra".
In the category of types in a particular programming language, the categorical product of A and B is the type of tuples containing an A and a B, and the projection maps extract an A and a B from it respectively. Any other type which contains an A and a B must necessarily be isomorphic to "a tuple plus some extra".
Note that this representation is only unique up to isomorphism (up to a unique isomorphism, which is more powerful but in ways that aren't relevant here). (A, B) is a valid direct product of A and B. So is (B, A). And so is the structure
struct HelloThere {
  a: A,
  b: B,
}

All of these are distinct types but are isomorphic, and they are all valid products of the two input types.
Likewise, the direct sum or coproduct is the dual of the product, which means it's the above diagrams with all the arrows reversed. More precisely, the direct sum is an object I together with a pair of morphisms i₁ : A -> I and i₂ : B -> I.

Note that we've reversed the directions of our arrows. Instead of projections out of our type P, we have injections into I.
Again, we get a universal property, stating that I must be the best sum. So given I', i'₁ : A -> I', and i'₂ : B -> I', we must get an f : I -> I' with the following commutative diagram.

i.e., f∘i₁ = i'₁ and f∘i₂ = i'₂. It so happens that, in the category of types, this direct sum object manifests as the disjoint, or tagged, union (which Haskell calls Either).
You'll also sometimes hear function types called exponential types, which as a similar categorical relationship to the exponential object. I'll sometimes write A -> B and B^A (Note: The result type is the base of the exponent) interchangeably in what follows, when it makes sense for the explanation.
But why did we choose these names in category theory? Lots of reasons, actually!
First, we can make a cardinality argument. I'll borrow notation from set theory and write |A| to denote the cardinality of the set underlying our type. If you don't know what cardinality is, just think of it as "the number of possible distinct elements in your type". We have the following, for all types A and B.

|A + B| = |A| + |B|. The number of elements in the disjoint union is equal to the sum of the sizes of each type.
|A × B| = |A| × |B|. The number of elements in the tuple type is equal to the product of the sizes of each type.
|A ^ B| = |A| ^ |B|. The number of functions from B to A is equal to the size of A raised to the power of that of B.

So if all we care about is counting, then these operations match precisely our intuitive notions in ordinary arithmetic.
But there's more! These categorical objects behave a lot like ordinary arithmetic ones in more ways than just counting.
They're commutative.

A × B ≅ B × A
A + B ≅ B + A

They're associative.

(A × B) × C ≅ A × (B × C)
(A + B) + C ≅ A + (B + C)

and they even distribute.

(A + B) × C ≅ A × C + B × C
A × (B + C) ≅ A × C + A × C

The exponential (function) types are well behaved too. Take a moment to think about what these mean, as types, as these can be a bit less trivial to immediately see.

(A × B) ^ C ≅ A ^ C × B ^ C
A ^ (B + C) ≅ A ^ B × A ^ C
(A ^ B) ^ C ≅ A ^ (B × C)

We can go one step further. In category theory, we often denote the initial object of a category as 0 and the terminal object as 1. Under those definitions, in the category of types in our hypothetical language, the initial object 0 is Void, the empty type, and the terminal object 1 is Unit, the type having one value. These numbers also behave neatly in this model.

A + 0 ≅ 0 + A ≅ A
A × 1 ≅ 1 × A ≅ A
A × 0 ≅ 0 × A ≅ 0
A ^ 0 ≅ 1
0 ^ A ≅ 0 (if A is nonempty)
1 ^ A ≅ 1
A ^ 1 ≅ A

In summary, we call these types sums, products, exponentials, 0, and 1, because when we actually write down all of the nice arithmetic properties of addition, multiplication, powers, zero, and one, it turns out that these are the types that satisfy those properties.

Side note: You'll notice I switched from using = to ≅ halfway through. I use ≅ to denote isomorphism. It's true that (A × B) × C is not actually equal to A × (B × C), since the first looks like ((a, b), c) and the second looks like (a, (b, c)), but they store the same information. The notion of isomorphism makes that rigorous. In fact, all of the above isomorphisms are natural in their arguments, which means that the types are related in a uniform way that doesn't depend on the specific structure of the arguments.
> **Comments:**
> **username_6** (2023-05-20): While presenting the category theory model is interesting, it makes the concepts look more complicated than they are. The vocabulary of category theory comes from set theory and the set theory model is rather easier to understand.  
---
