-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Phantom Types #2040
Comments
Additionally, in the latest prototype it is also possible to have method definitions returning phantom types that have side effects. For this we need to relax the rules on which parts we delete.
This transformation will not remove the method definitions returning phantom types and call to them. If they are only retuning a phantom value (with The question of expressions of phantom type having side effects becomes irrelevant in the general case. It is only necessary to delete references to parameters of phantom type and the The simples use case I can imagine is the following type DoneA <: Phantom.Any
def doA(): DoneA = {
// do something here
assume[DoneA]
}
// At runtime it will be `def doB(): Unit`
def doB(doneA: DoneA): Unit = { /* something here */ }
val doneA = doA()
// At runtime it will be `doB()`
doB(doneA) // Cannot do without the phantom result of doA |
One other question is whether there should be just one phantom domain or several. If we want to integrate perishable capabilities (aka effects) we might need another phantom domain for them where we are not allowed to capture values of such types at all. It could also be useful for other purposes to have several completely isolated phantom domains. A simple way to achieve that would be to change the object definition of |
We decided we need several phantom domains, after all. The proposal has been updated to reflect this. |
How would usage look? Why aren't currently used encodings sufficient? |
The current usage of which feature part? Phantom types in general or phantom domains? |
Current state:
|
Hi, these new phantom types seems really interesting!
and got compile error:
Is that a fundamental limitation of phantom types, or something that will be fixed in the future?Thanks! |
@nicolasstucki Then these phantom types just became even more awesome (for my intended use-cases), thanks! |
Phantom types are already in master and as is the documentation for it. Some changes will be made on them, but those are not part of this issue. |
I believe Phantom Types disapeared over Unused Parameters? |
@joan38 TL;DR IIUC: With unused parameters you can mark values of arbitrary types to be erased at runtime, instead of having to implement separate phantom types. I don't have a link though yet. |
@joan38 |
Thanks guys for the details, that looks indeed better :) |
Phantom types are a proposal to add types that have no runtime values. Such types are useful in several scenarios:
Phantom types have a prototype implementation #1408. This implementation has evolved quite a bit over time. The present issue describes the latest state of the proposal which arose from discussions between @nicolasstucki, myself and other members at LAMP. It is still vague in several places and there are some issues left open.
The proposal introduces a new predefined class
scala.Phantom
, defined as followsThis class is not given in source but has to be synthesized in the compiler.
Phantom
is special in thatPhantom.Any
andPhantom.Nothing
live completely outside the standard type hierarchy. They are not subtypes ofscala.Any
nor supertypes ofscala.Nothing
. A type is called phantom type if it extendsp.Any
wherep
is an instance of classPhantom
.Definition: All types that are supertypes of
scala.Nothing
and subtypes ofscala.Any
make up the standard type domain. Ifp
is an instance of classPhantom
, then all types that are supertypes ofp.Nothing
and subtypes ofp.Any
make up the phantom type domain ofp
.There are some rules to observe:
&
) and unions (|
) cannot be formed between different type domains.Since
p.Any
is sealed, it is impossible to define a class that extends it. Since it is abstract, one cannot create instances of it. Likewise, one can neither instantiate nor extendp.Nothing
. It follows that no new classes can be defined in a phantom domain, and no objects of phantom types can be created usingnew
. However, one can define new phantom types as abstract types with phantom type bounds or as aliases of phantom types.Every type parameter and abstract type has (possibly implied) bounds. These can be either phantom or non-phantom types. It follows that it is not possible to have a generic type parameter that ranges over both phantom and non-phantom types, nor can such a parameter range over phantom types from different domains.
If
p
is an instance ofPhantom
, the expressionp.assume[T]
synthesizes a value of phantom typeT
. This is the only way to produce a value of a phantom type. The actual implementation ofassume
is irrelevant because all phantom types are erased. That is,We discussed a lot about the nature of
assume
. If phantom types model a theory thenassume
defines axioms of that theory. If they define capabilities, thenassume
defines capabilities given a priori. Either way, addingassume
s in arbitrary places destroys the soundness of the theory or the safety guarantees of the capability system. Soassume
needs to be carefully controlled.Note that
assume
isprotected
in classPhantom
, This means that individual phantom domains can each implement their own policy to what degreeassume
should be made available to clients. A phantom domain could either hideassume
completely, and only export some fixed axioms or capabilities that are defined in terms of it. Or it could exportassume
- either unchanged or under a different name such asuncheckedAssume
.The text was updated successfully, but these errors were encountered: