From time to time I encounter questions in mathematics, which in some sense can be called "grammatically incorrect."
Example. "Interval [ 0 , 1 ] is closed or open? " Example. "Does it \ {1, 2, 3 \}\ {1, 2, 3 \} group? " Example. "What is the Fourier series for s i n x + s i n p i x ?
More stupid examples. ')
Example. "Is the rectangle simple?" Example. " 17 i n 3 ? " Example. "What is the Fourier series for the empty set?"
All these examples are united by the fact that they are typing errors : these are attempts to apply a certain mathematical process to a mathematical object that can in no way be input data for it. If to answer these questions you try to write a program in some highly mathematical programming language, then it (I hope!) Will not compile.
Mathematical objects are usually not perceived explicitly as having types in the same sense as objects in programming languages with a type system . It is assumed that ordinary mathematics should be formalized in the Zermelo – Fraenkel system (ZF), possibly with the axiom of choice, and in ZF each mathematical object is constructed as a set. In this sense, all these objects are of the same type. (In particular, the question " 17 i n 3 "It is quite logical in ZF! And this is one of the reasons why it’s worth not to love ZF as a basis for mathematics.) However, it seems to me that in practice mathematical objects are implicitly perceived as having types, and this way of thinking is learned by mathematics, but not often discussed. Instead of reasoning from the point of view of set theory, it is worthwhile to consider mathematical objects as having types, which will allow us to import various useful concepts into mathematics, such as the concepts of type safety , typeconversion , subtyping and overload , which will allow us to more specifically define “grammatical fallacy »Mathematical sentences. For the remainder of the post, I will relaxly discuss how these and other types of concepts apply to mathematics in general. The article will contain many categorical concepts, but for the sake of simplicity of understanding, I will limit myself to making them notes in brackets.
Informal description of mathematical types
Informally, it can be said that a type of mathematical object describes a kind of this object.
Example. An object 2 has a type t e x t t t N a t (natural number). Example. An object - 2 has a type t e x t t t i n t (whole). Example. An object f r a c 1 2 has a type t e x t t t R a t (rational number). Example. An object ( 2 , 3 ) has a type textttNattimestextttNat (a pair of positive integers). Example. An object 30circ has a type textttdeg (degree). Example. An object xmapstox2 has a type textttNattotextttNat (function is displayed from natural numbers to natural numbers). Example. An object texttttrue has a type textttBool ( Boolean ).
But less simple examples:
Example. An object mathbbZ has a type textttGrp (Group). Example. An object S2 has a type textttTop (topological space). Example. An object XmapstoH1(X) has a type textttToptotextttGrp (the function is mapped from topological spaces to groups).
Types help us understand what actions we can perform with a set of mathematical objects.
Example. You can take two objects of type textttNat and add or multiply them. In other words, there are functions +,times:textttNattimestextttNattotextttNat . Example. You can take two objects of type textttint in addition to addition and multiplication subtract them. In other words, there are functions +,times,−:textttInttimestextttInttotextttInt . Example. You can take an object like textttdeg and apply trigonometric functions to it. In other words, there are functions textttsin,textttcos:textttDegtotextttReal . Example. If a textttA,textttB are types, then we can take an object of type textttA and another object of type textttAtotextttB to apply the latter to the first. In other words, there is a function texttteval:textttAtimes(textttAtotextttB)totextttB .
Type of textttBool occupies a special place in this theory. There are only two objects of this type, namely texttttrue and textttfalse , and functions, giving output values textBool , can be used to check if the property is true.
Example. You can take a natural number and ask if it is simple. In other words, there is a function textttisPrime:textttNattotextttBool . Example. If a textttA is a type, then we can take two objects of type textttA and ask if they are equal. In other words, there is a function
which we can also write using the equal sign = . Example. You can take two integers and ask whether the first is greater than or equal to the second. In other words, there is a function
ge:textttInttimestextttInttotextttBool
As follows from these examples, there are many ways to combine types to create new types; they are called type constructors . Example. An object having a work typetextttAtimestextttB , is a pair of objects of type textttA and textttB . Example. An object of type sumtextttA+textttB is or object of type textttA or object type textttB . Example.Functional object textttAtotextttB , also sometimes written as textttBtextttA Is a function that receives objects of type at the input textttA and returning objects of type on output textttB .
(These constructions may seem familiar to lovers of category theory: they all are just products, coproducts and exponentials. In other words, the categories of types are bidecarte closed categories.)
Using the above simple type constructors, we can create more complex type constructors. For example, having type textttA we can create a type listtexttt[A] which is the type of (finite) lists of elements of type textttA :
(Where texttt1 - this is a special type called unit type ; its defining characteristic is that there is only one object of type-unit, which we will call a point ). Heuristic type-list can be written as a "geometric series" fractexttt1texttt1−textttA .
Notation system
Above we used the record textttf:textttAtotextttB to indicate that textttf was an object of type textttAtotextttB . It would be logical to generalize this entry to arbitrary types so that texttta:textttA meant that a is an object of type textttA . This will be a type declaration .
Type safety and typing errors
In addition to helping us understand what we can do with a set of mathematical objects, types also help us understand what we cannot do. Let's look at the examples presented at the beginning of the post, taking into account this idea.
Example. "Does it \ {1, 2, 3 \} group? " Example. "What is the Fourier series for sinx+sinpix ?
Example. "Interval [0,1] is closed or open? "Functions textttisClosed and textttisOpen they cannot receive at the entrance a multitude or even a topographic space; they get in pairs (X,S) where X Is a topological space, and S - subspace X (and give out on output is whether S closed or open subset X ). In other words, they are of type not textttToptotextttBool and type textttPairstotextttBool . Question is whether [0,1] open or closed, depends on whether it is considered as a subset of itself or, say, mathbbR .
Example. "Does it \ {1, 2, 3 \} group? "function textttisGroup does not get a lot at the entrance; she gets inlet couples (X,cdot) where X - this is a lot, but cdot - binary operation on X ( magma ). In other words, she has type not textttSettotextttBool and type textttMagmatotextttBool .
Example. "What is the Fourier series for sinx+sinpix ? "Function textttFourierSeries does not receive the input function on mathbbR ; it receives at the input a periodic function on mathbbR for example with a period 2pi or, similarly, the function on sinx+sinpix is not periodic with any period. In other words, textttFourierSeries has no type (textttRealtotextttComplex)to(textttInttotextttComplex) and type (textttCircletotextttComplex)to(textttInttotextttComplex) .
More stupid examples can be analyzed similarly.
Finding typing errors, or type checking, helps in debugging mathematical calculations in the same way that a compiler looks for typing errors for debugging code. For example, when we see an expression in the form a=b then before checking its truth, you can check whether it makes sense at all by making sure that a and b have one type. This is a very generalized version of dimension analysis .
Type checking is also a way of understanding new mathematical topics. If you still can not yet pronounce correctly typed sentences on the desired topic (which can be determined by other people who know the subject), then you have not yet figured out the types of basic objects or functions of this area. For example, if you say "fundamental group ...", then you need to end the sentence with either the phrase "point topological space" or "linearly connected topological space". Otherwise, you do not understand the important aspect of defining the fundamental group, namely the role of base points.
Type casting, subtype creation and overloading
Type checking for a nontrivial task can be done by the fact that most mathematical objects are naturally considered to be of several types. For example, the above we said that the number 2 has a type textttNat but it is also obvious that it has type textttInt,textttRat,textttReal and even textttComplex . One way to describe this situation is in the cast functions .
which transform objects into different types. If there is a cast operator textttAtotextttB , then we can use objects of type textttA as input to functions waiting for objects of type textttB if we first cast the type.
Another way to describe this situation is that some types are subtypes of other types; in other words, instead of a set of cast functions, the above situation describes a chain of inclusions of subtypes. The creation of subtypes allows objects to have several types at the same time, and not to be of a certain type at a certain point of any calculations.
Subtypes have an interesting relationship with functional types. If a textttB′ is a subtype textttB then functional type textttAtotextttB′ is a subtype textttAtotextttB , but if textttA′ is a subtype textttA (a function that outputs objects of type textttB′ , also produces output type textttB ), then the functional type textttA′totextttB is not a subtype, but a supertype textttAtotextttB (a function that receives objects of the type textttA can also receive objects of type textttA′ ). In other words, the creation of functional types is covariant in output types, but contravariant in input types with respect to subtypes.
(And this should also be familiar to lovers of category theory: this phenomenon reflects the fact that the creation of exponential objects is covariantly functorial in final objects, but contravariantly functorial in the original objects.)
The third way to describe this situation is that the functions in mathematics are overloaded , and this description is probably closest to mathematical practice. Overloading is the practice of defining functions that have the same name but receive different types of input data. For example, the addition symbol + refers not to one, but to several functions that have the same name, i.e.
+:textttNattimestextttNattotextttNat
+:textttInttimestextttInttotextttInt
+:textttRattimestextttRattotextttRat
+:textttRealtimestextttRealtotextttReal
+:textttComplextimestextttComplextotextttComplex
and so on. More generally we can use + for the operation of addition on any ring, and even more generally for the operation of grouping in any Abelian group. We even used it above to designate types of sums!
With indicative record ab business is much worse. It can refer to functions of any of the following types:
or even more generally, a can be a member of a group, but b may be whole or a may be e , but b may be an element and we even used an indicative notation to denote functional types! See also this question in math.se.
It seems that overloading students is confusing, and I think part of the reason is that mathematicians rarely explicitly talk about it when they use it. Overloading is not so bad as long as all its different instances are at least logically connected with each other, but sometimes mathematical concepts are overloaded for no reason other than historical ones, for example, the words “normal” and “correct”. It confuses students even more: sometimes one word is used in two different contexts because of a logical connection, for example, “normal expansion” and “normal subgroups”, but sometimes it simply does not exist. See also this question on MO .
Recursive types
In type theory, some types can be defined recursively , relative to themselves, and not directly relative to other types. In this way, surprisingly many important types of mathematical objects can be defined.
Example. Type of textttNat natural numbers can be recursively defined as
textttNat=texttt1+textttNat
that is, a natural number is either a point (namely 1 ), or another natural number (namely, its previous).
Example. More generally, type list texttt[A] can be recursively defined as
that is, the list of elements of type textttA is either a point or an element of type textttA (namely the beginning of the list) along with the list of elements of the type textttA (i.e. the remaining part of the list). In particular, textttNat - it's just a type texttt[1] list of points. It is worth noting that this is exactly the ratio that must be satisfied by the "geometric series" fractexttt1texttt1−textttA .
Example. Type of textttTree (fully binary) trees (with root) can be recursively defined as
that is, a game is a pair of game functions that we can call textttL and textttR . Strictly speaking, the combinatorial game actually needs to be called the position of the game, since it describes a specific moment of the game (for example, the beginning of a game of chess), and not what we usually call a game (for example, chess). We perceive games as something in which two people play, left and right, and in any position of the game the left has possible options for the positions of the game into which he can move it, namely, such positions for which textttL returns true, and the right one also has some possible positions of the game to which it can move, namely, such positions for which textttR returns true.
Conway noted that combinatorial games resemble a generalization of both ordinal numbers (which can be described relative to the set of ordinal numbers) and Dedekind sections (which can be described by a pair of sets of rational numbers). He used this connection to determine a large class of numbers using games; see more in On Numbers and Games .
The type we defined earlier textttSet=(textttSettotextttBool) , can also be perceived as a type of impartial games , that is, games in which possible moves do not depend on which player is playing.
(For lovers of category theory: recursive types are initial algebras with respect to the corresponding endofunctor of the category of types.)
Functions that receive a recursive type as an input can also be defined recursively. Examples with natural numbers should already be familiar to you; Here are some other examples.
Example. The length of the list can be defined recursively as follows: dot length is 0 . If the list is not a point, then it consists of an element and a sublist, and then the list length is one more than the length of the sublist. (I could write it with pseudocode, but I don’t know a clear way to display pseudo code on a WordPress site.)
Example. More generally, for any two types textttA,textttB there is a function
called map , the input function textttf:textttAtotextttB , and the output returns function textttmap(f):texttt[A]totexttt[B] , recursively defined as follows: if the input list is empty, then the output list is the same. Otherwise, the input list consists of an object of type textttA and sublists, and textttmap(f) applies textttf to the object and then textttmap(f) to sub-list, and all of them together make the output list. The length of the function list is obtained using textttmap to unique function textttAtotexttt1 .
(Fans of category theory will see that, in fact, in this entry, the list constructor is a functor. There are even programming languages like Haskell that recognize this fact and use it.)
Example.The height of the tree can be recursively defined as follows: the height of a point is equal to 0 . If a tree is not a point, then it has two subtrees, and then the tree height is one more than the maximum height of its subtrees.
Example. Games with guaranteed completion can be organized into four non-overlapping classes: the game is
positive if the left one wins regardless of who goes first,
negative if the right one wins regardless of who goes first,
, , ,
, , .
Here, “victory” means victories in a normal game, when the first player who cannot make a move loses. The above classes correspond to the four functions.
which can be recursively defined through each other as follows:
A game is positive if and only if at least one of the variants of the left is positive or zero, and all the variants of the right are positive or fuzzy.
A game is negative if and only if all variants of the left are negative or indistinct, and at least one of the variants of the right is negative or zero.
A game is zero if and only if none of the variants of the left are positive or non-zero, and none of the variants of the right are negative or non-zero.
A game is fuzzy if and only if at least one of the variants of the left is positive or zero and at least one of the variants of the right is negative or zero.
(For lovers of category theory: recursively defined functions are the application of the universal property of initial algebras.)
Recursive types are another reason to assume that mathematics has a type system: they allow much more recursion to be recorded than it is usually explicitly mentioned in mathematics, where write it using induction (recursion overNat ) or sometimestransfinite induction (recursion over alteredSet ).Recursive types, on the contrary, provide a general record of structural induction . Often we can reduce the cases of structural induction we need to ordinary induction (for example, if we want to perform structural induction for trees, then we can perform ordinary induction for their vertices), but conceptually structural induction is clearer (for example, we can perform structural induction for trees without highlighting a specific vertex function).
Conclusion
Although theoretically mathematics is not often described as having a type system, in practice it turns out to be both more useful and more accurate to describe mathematics as having such a system. This gives us a language to understand certain types of mathematical errors (typing errors), as well as to understand certain implied mathematical actions (overloads). In addition, types have an interesting mathematical structure and provide a richer language for defining and working with recursively defined mathematical objects than traditional methods.