Bottom type

Last updated

In type theory, a theory within mathematical logic, the bottom type of a type system is the type that is a subtype of all other types. [1]

Contents

Where such a type exists, it is often represented with the up tack (⊥) symbol.

Relation with the empty type

When the bottom type is uninhabited, a function whose return type is bottom cannot return any value, not even the lone value of a unit type. In such a language, the bottom type may therefore be known as the zero, never or empty type which, in the Curry–Howard correspondence, corresponds to falsity.

However, when the bottom type is inhabited, it is then different from the empty type.

Computer science applications

In subtyping systems, the bottom type is a subtype of all types. [1] It is dual to the top type, which spans all possible values in a system.

If a type system is sound, the bottom type is uninhabited and a term of bottom type represents a logical contradiction. In such systems, typically no distinction is drawn between the bottom type and the empty type, and the terms may be used interchangeably.

If the bottom type is inhabited, its term(s) typically correspond to error conditions such as undefined behavior, infinite recursion, or unrecoverable errors.

In Bounded Quantification with Bottom, [1] Pierce says that "Bot" has many uses:

  1. In a language with exceptions, a natural type for the raise construct is raise  exception -> Bot, and similarly for other control structures. Intuitively, Bot here is the type of computations that do not return an answer.
  2. Bot is useful in typing the "leaf nodes" of polymorphic data structures. For example, List(Bot) is a good type for nil.
  3. Bot is a natural type for the "null pointer" value (a pointer which does not point to any object) of languages like Java: in Java, the null type is the universal subtype of reference types. null is the only value of the null type; and it can be cast to any reference type. [2] However, the null type is not a bottom type as described above, it is not a subtype of int and other primitive types.
  4. A type system including both Top and Bot seems to be a natural target for type inference, allowing the constraints on an omitted type parameter to be captured by a pair of bounds: we write S<:X<:T to mean "the value of X must lie somewhere between S and T." In such a scheme, a completely unconstrained parameter is bounded below by Bot and above by Top.

In programming languages

Most commonly used languages don't have a way to denote the bottom type. There are a few notable exceptions.

In Haskell, the bottom type is called Void. [3]

In Common Lisp the type NIL, contains no values and is a subtype of every type. [4] The type named NIL is sometimes confused with the type named NULL, which has one value, namely the symbol NIL itself.

In Scala, the bottom type is denoted as Nothing. Besides its use for functions that just throw exceptions or otherwise don't return normally, it's also used for covariant parameterized types. For example, Scala's List is a covariant type constructor, so List[Nothing] is a subtype of List[A] for all types A. So Scala's Nil, the object for marking the end of a list of any type, belongs to the type List[Nothing].

In Rust, the bottom type is called the never type and is denoted by !. It is present in the type signature of functions guaranteed to never return, for example by calling panic!() or looping forever. It is also the type of certain control-flow keywords, such as break and return, which do not produce a value but are nonetheless usable as expressions. [5]

In Ceylon, the bottom type is Nothing. [6] It is comparable to Nothing in Scala and represents the intersection of all other types as well as an empty set.

In Julia, the bottom type is Union{}. [7]

In TypeScript, the bottom type is never. [8] [9]

In JavaScript with Closure Compiler annotations, the bottom type is !Null (literally, a non-null member of the Null unit type).

In PHP, the bottom type is never.

In Python's optional static type annotations, the general bottom type is typing.Never (introduced in version 3.11), [10] while typing.NoReturn (introduced in version 3.5) can be used as the return type of non-returning functions specifically (and doubled as the general bottom type prior to the introduction of Never). [11]

In Kotlin, the bottom type is Nothing. [12]

In D, the bottom type is noreturn [13]

In Dart, since version 2.12 with the sound null safety update, the Never type was introduced as the bottom type. Before that, the bottom type used to be Null. [14] [15]

See also

Related Research Articles

<span class="mw-page-title-main">Design by contract</span> Approach for designing software

Design by contract (DbC), also known as contract programming, programming by contract and design-by-contract programming, is an approach for designing software.

In computer science, an associative array, map, symbol table, or dictionary is an abstract data type that stores a collection of pairs, such that each possible key appears at most once in the collection. In mathematical terms, an associative array is a function with finite domain. It supports 'lookup', 'remove', and 'insert' operations.

In computer programming, a type system is a logical system comprising a set of rules that assigns a property called a type to every term. Usually the terms are various language constructs of a computer program, such as variables, expressions, functions, or modules. A type system dictates the operations that can be performed on a term. For variables, the type system determines the allowed values of that term. Type systems formalize and enforce the otherwise implicit categories the programmer uses for algebraic data types, data structures, or other components.

In computer science, primitive data types are a set of basic data types from which all other data types are constructed. Specifically it often refers to the limited set of data representations in use by a particular processor, which all compiled programs must use. Most processors support a similar set of primitive data types, although the specific representations vary. More generally, "primitive data types" may refer to the standard data types built into a programming language. Data types which are not primitive are referred to as derived or composite.

In some programming languages, eval, short for the English evaluate, is a function which evaluates a string as though it were an expression in the language, and returns a result; in others, it executes multiple lines of code as though they had been included instead of the line including the eval. The input to eval is not necessarily a string; it may be structured representation of code, such as an abstract syntax tree, or of special type such as code. The analog for a statement is exec, which executes a string as if it were a statement; in some languages, such as Python, both are present, while in other languages only one of either eval or exec is.

Many programming language type systems support subtyping. For instance, if the type Cat is a subtype of Animal, then an expression of type Cat should be substitutable wherever an expression of type Animal is used.

In computer science, the Boolean is a data type that has one of two possible values which is intended to represent the two truth values of logic and Boolean algebra. It is named after George Boole, who first defined an algebraic system of logic in the mid 19th century. The Boolean data type is primarily associated with conditional statements, which allow different actions by changing control flow depending on whether a programmer-specified Boolean condition evaluates to true or false. It is a special case of a more general logical data type—logic does not always need to be Boolean.

In computing, a null pointer or null reference is a value saved for indicating that the pointer or reference does not refer to a valid object. Programs routinely use null pointers to represent conditions such as the end of a list of unknown length or the failure to perform some action; this use of null pointers can be compared to nullable types and to the Nothing value in an option type.

In computer science, future, promise, delay, and deferred refer to constructs used for synchronizing program execution in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is not yet complete.

<span class="mw-page-title-main">Scala (programming language)</span> General-purpose programming language

Scala is a strong statically typed high-level general-purpose programming language that supports both object-oriented programming and functional programming. Designed to be concise, many of Scala's design decisions are intended to address criticisms of Java.

In the area of mathematical logic and computer science known as type theory, a unit type is a type that allows only one value. The carrier associated with a unit type can be any singleton set. There is an isomorphism between any two such sets, so it is customary to talk about the unit type and ignore the details of its value. One may also regard the unit type as the type of 0-tuples, i.e. the product of no types.

A foreign function interface (FFI) is a mechanism by which a program written in one programming language can call routines or make use of services written or compiled in another one. An FFI is often used in contexts where calls are made into binary dynamic-link library.

In mathematical logic and computer science, some type theories and type systems include a top type that is commonly denoted with top or the symbol ⊤. The top type is sometimes called also universal type, or universal supertype as all other types in the type system of interest are subtypes of it, and in most cases, it contains every possible object of the type system. It is in contrast with the bottom type, or the universal subtype, which every other type is supertype of and it is often that the type contains no members at all.

Nullable types are a feature of some programming languages which allow a value to be set to the special value NULL instead of the usual possible values of the data type. In statically typed languages, a nullable type is an option type, while in dynamically typed languages, equivalent behavior is provided by having a single null value.

Generics are a facility of generic programming that were added to the Java programming language in 2004 within version J2SE 5.0. They were designed to extend Java's type system to allow "a type or method to operate on objects of various types while providing compile-time type safety". The aspect compile-time type safety was not fully achieved, since it was shown in 2016 that it is not guaranteed in all cases.

In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral (null) behavior. The null object design pattern, which describes the uses of such objects and their behavior, was first published as "Void Value" and later in the Pattern Languages of Program Design book series as "Null Object".

The null coalescing operator is a binary operator that is part of the syntax for a basic conditional expression in several programming languages, including C# as of version 2.0, PowerShell as of version 7.0.0, Perl as of version 5.10, Swift, and PHP 7.0.0. While its behavior differs between implementations, the null coalescing operator generally returns the result of its left-most operand if it exists and is not null, and otherwise returns the right-most operand. This behavior allows a default value to be defined for cases where a more specific value is not available.

This Comparison of programming languages (associative arrays) compares the features of associative array data structures or array-lookup processing for over 40 computer programming languages.

In object-oriented programming, the safe navigation operator is a binary operator that returns null if its first argument is null; otherwise it performs a dereferencing operation as specified by the second argument.

References

  1. 1 2 3 Pierce, Benjamin C. (1997). "Bounded Quantification with Bottom". Indiana University CSCI Technical Report (492): 1.
  2. "Section 4.1: The Kinds of Types and Values". Java Language Specification (3rd ed.).
  3. "Data.Void". Hackage. Retrieved 2023-09-20.
  4. "Type NIL". Common Lisp HyperSpec. Retrieved 25 October 2022.
  5. "Primitive Type never". The Rust Standard Library Documentation. Retrieved 2020-09-24.
  6. "Chapter 3. Type system — 3.2.5. The bottom type". The Ceylon Language. Red Hat, Inc. Retrieved 2017-02-19.
  7. "Essentials - The Julia Language", The Julia Programming Language Documentation, retrieved 2021-08-13
  8. The never type, TypeScript 2.0 release notes, Microsoft, 2016-10-06, retrieved 2019-11-01
  9. The never type, TypeScript 2.0 release notes, source code, Microsoft, 2016-10-06, retrieved 2019-11-01
  10. "typing — Support for type hints — Python 3.12.0a0 documentation". docs.python.org. Retrieved 2024-03-02.
  11. typing.NoReturn, typing — Support for type hints, Python documentation, Python Software Foundation, retrieved 2024-03-02
  12. Nothing , retrieved 2020-05-15
  13. "Types - D Programming Language". dlang.org. Retrieved 2022-10-20.
  14. Understanding null safety - top and bottom , retrieved 2022-04-13
  15. Understanding null safety - never for unreachable code , retrieved 2022-04-13

Further reading