-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Types of types are unit types #151
Changes from all commits
ccd6f44
37acb52
fdec2f7
212e44a
acef64a
f861e6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Types of types are unit types | ||
|
||
<!-- | ||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM | ||
Exceptions. See /LICENSE for license information. | ||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
--> | ||
|
||
## Table of contents | ||
|
||
<!-- toc --> | ||
|
||
- [Question](#question) | ||
- [Background](#background) | ||
- [Resolution](#resolution) | ||
|
||
<!-- tocstop --> | ||
|
||
## Question | ||
|
||
Types in Carbon are values. So `Int32` is a type, but it is also a value, and so | ||
it has its own type. What can we say about the type of `Int32`? Do any other | ||
types have the same type? | ||
|
||
## Background | ||
|
||
In this example: | ||
|
||
``` | ||
var Int32: x = 7; | ||
``` | ||
|
||
we say `x` has type `Int32` and value `7`. When writing a function with generic | ||
parameters, we need to talk about sets of types, such as the set of types that | ||
are legal inputs. For example, a `Max` function may be able to take any two | ||
values of the same type, as long as that type implements the `Comparable` | ||
interface: | ||
|
||
``` | ||
fn Max[TypeImplements(Comparable):$ T](T: x, T: y) -> T; | ||
``` | ||
|
||
In this example, `T` is the type of the inputs and outputs, and we constrain | ||
that type to just be types that implement `Comparable` by writing that `T` has | ||
type `TypeImplements(Comparable)`. `Int32` would be an example of a type that | ||
has an implementation for `Comparable`, so you should be able to call `Max` with | ||
arguments of type `Int32`. | ||
|
||
To address | ||
[the expression problem](https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions), | ||
we allow an implementation of an interface to be defined either with the type or | ||
the interface. That is if I define a new type `Foo`, I can also define an | ||
implementation for an existing interface `Bar` for `Foo` at the same time. | ||
Similarly, if I define a new interface `Baz`, I can define implementations for | ||
existing types like `Int32` of `Baz` with `Baz`. See | ||
[the generics proposal](https://github.com/josh11b/carbon-lang/blob/generics-docs/docs/design/generics/facet-type-types.md#implementing-interfaces) | ||
for details. | ||
|
||
A [unit type](https://en.wikipedia.org/wiki/Unit_type) is a type with a single | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if "singleton types" is a better term for what is meant here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are likely correct, I'm not very familiar with common usage here, I was just using Wikipedia as the source of truth. https://en.wikipedia.org/wiki/Unit_type says:
I don't really understand the difference here between unit and singleton types though -- presumably this argument about being isomorphic applies equally well to singleton types. Is it just that you say "unit type" when you don't care about the unique value, making them the same? I just did some searching and it appears while this matches the usage of "singleton type" in https://typesandkinds.wordpress.com/tag/singletons/, in https://en.wikipedia.org/wiki/Scala_(programming_language) "singleton type" seems to refer to a type with a single instance instead of a single value, matching https://en.wikipedia.org/wiki/Singleton_pattern instead of https://en.wikipedia.org/wiki/Singleton_(mathematics) . In the case of this document (and the Haskell case), the value is immutable and so the difference between values and instances is too small to concern us, which is an argument for making the change. |
||
value. Not to be confused with a | ||
[monotype](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Monotypes) | ||
(as opposed to | ||
[polytypes](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Polytypes)) | ||
or the [bottom type](https://en.wikipedia.org/wiki/Bottom_type) (which has no | ||
values). | ||
|
||
## Resolution | ||
|
||
Let us call the type of `Int32` `X`. What set of types have `X` as their type? | ||
Well, we know `X` is a subtype of `TypeImplements(Comparable)` since `Int32` | ||
implements `Comparable`. This allows `T` to be `Int32` in the definition of | ||
`Max` above. In fact, `X` has a supertype for _every_ interface `Int32` | ||
implements. But if `Int32` doesn't implement an interface `Quux`, then `X` won't | ||
be a subtype of `TypeImplements(Quux)`. The problem is that we never have a | ||
comprehensive list of all the interfaces that `Int32` implements, just which of | ||
the interfaces that are imported into any particular file. | ||
|
||
So imagine there is another type `T` that also has type `X`. It would have to | ||
implement exactly the same interfaces as `Int32`. But we can create a new | ||
interface, call it `Int32ButNotT`, in a new library. Since we are defining a new | ||
interface, the only types that will implement that interface are those with | ||
implementations in the same library as `Int32ButNotT`. So if we implement | ||
`Int32ButNotT` for `Int32` but not `T`, we arrive at a contradiction. Since the | ||
compiler won't see every interface definition, it will have to conservatively | ||
assume that there are interfaces out there that separate any pair of types. | ||
|
||
We conclude that every type that can have interface implementations can't share | ||
its type with any other type. However note that there are other type-types, for | ||
example interfaces like `Comparable`, that are not unit. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Types of types are unit types | ||
|
||
<!-- | ||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM | ||
Exceptions. See /LICENSE for license information. | ||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
--> | ||
|
||
[Pull request](https://github.com/carbon-language/carbon-lang/pull/151) | ||
|
||
## Table of contents | ||
|
||
<!-- toc --> | ||
|
||
- [Problem](#problem) | ||
- [Background](#background) | ||
- [Proposal](#proposal) | ||
|
||
<!-- tocstop --> | ||
|
||
## Problem | ||
|
||
Since types are values, types themselves have types. So what can we say about | ||
the type of something like `Int32`? | ||
|
||
## Background | ||
|
||
This proposal builds on and assumes | ||
[Generics proposal PR 36](https://github.com/carbon-language/carbon-lang/pull/36). | ||
|
||
## Proposal | ||
|
||
The type of `Int32` must be a unit type. Details of the reasoning are provided | ||
in `docs/design/generics/type_types_are_unit.md`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you link to this via the pull request, assuming there is a pull request for this branch already? It seems a little unusual for our design to link directly to your repo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to, but I haven't found a URL that will give the latest version of the file, just the one associated with a particular commit.