Skip to content
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

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions docs/design/generics/type_types_are_unit.md
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)
Copy link
Contributor

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.

Copy link
Contributor Author

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.

for details.

A [unit type](https://en.wikipedia.org/wiki/Unit_type) is a type with a single
Copy link
Contributor

Choose a reason for hiding this comment

The 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.
In a programming language there is just one "unit type".
But I think you want one of these for Int32 another another for Int64.
This use matches the meaning of singleton types.

Copy link
Contributor Author

@josh11b josh11b Sep 2, 2020

Choose a reason for hiding this comment

The 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:

The carrier (underlying set) 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.

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.
1 change: 1 addition & 0 deletions proposals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ request:
- [Decision](p0074_decision.md)
- [0083 - In-progress design overview](p0083.md)
- [0120 - Add idiomatic code performance and developer-facing docs to goals](p0120.md)
- [0151 - Types of types are unit types](p0151.md)

<!-- endproposals -->
34 changes: 34 additions & 0 deletions proposals/p0151.md
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`.