-
Notifications
You must be signed in to change notification settings - Fork 1.1k
The Singleton "kind" is not an upper bound #4944
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
Comments
Marked with |
The use of I'd be open to there being an alternative mechanism for doing that. |
And while we're at it, perhaps find a way to solve scala/bug#10838 |
Yes, that seems to be the case. I believe the only necessary use case of
It would mean complicating the syntax by allowing a modifier on type parameters. Does anybody see an alternative way to express this? |
We have at least two areas where we want to be able to influence inference: type inference, as here (I suspect that there will more cases than just "don't widen" to be found if we go looking); and also term inference, as in implicit search. My hunch is that it would be worth exploring the idea of a something like a tactic language to deal with both of these. |
A few examples in addition to inferring a singleton type if possible,
I'm sure there are plenty more ... In all these cases we can pick a most likely option, but there will be a significant number of scenarios where the most likely option isn't the right one. Parenthetically, we need to be careful not to throw the baby out with the bath water ... there are cases where we want to accept only singleton typed terms, ie. where we want to ensure we have a stable value. |
Indeed. Right now, a typical pattern would be like this: def f[U <: Universe with Singleton](m: Mirror[U]): U#Tree = ... The "only singleton type" guarantee is important to ensure that def f[u.type <: Universe](m: Mirror[u.type]): u.Tree The scheme would be to have a limited form of type pattern in type parameter binding position. A type pattern is either a type name or a term name followed by
the term name |
I think that's a good example of how type and term inference are related. Couldn't we have something like, def f(m: Mirror[u.type])(implicit u: Universe): u.Tree = ... |
Or, for that matter, def f(implicit u: Universe)(m: Mirror[u.type]): u.Tree = ... |
We can't have this, since def f(m: Mirror[u.type])(implicit u: Universe): u.Tree = ... But we could have the second version: def f(implicit erased u: Universe)(m: Mirror[u.type]) u.Tree = ... It's not completely equivalent, since it does not allow us to infer So maybe the answer is: just deprecate |
This is something that's been bugging me for some time now. Why is it possible that in this case, def foo[Eariler](later: Foo[Earlier]) ... we can infer the def foo(implicit earlier: Whatever)(later: Foo[earlier.type]) ... we can't infer |
This would mean implicit search and local type inference are merged into one. I fear that would make implicit search a lot more complex and less predictable. Also, in the example we are discussing the |
Do we really need singletons, or just realizable types there? @milessabin Indeed, in Agda there are separate mechanisms for unification-based inference (Agda implicit arguments, or Scala type arguments) and instance-based inference (Agda instance arguments, or Scala implicit arguments). The search semantics are different, but whether something is a term or a type doesn’t matter at all. But that’s not easy to retrofit, and Scala replaces unification with subtyping, which isn’t obvious on the term level. Meanwhile, in Scala I suspect default arguments given by transparent functions would enable programmable inference tactics and be easier to achieve. |
Created at topic of discussion here |
Why can't it be done with a special typeclass? |
@nafg Interesting idea! def g[U <: Universe with Singleton](implicit us: IsSingleton[U])(m: Mirror[U], x: U#Tree) = ...
def g[U <: Universe with Singleton] with IsSingleton[U] (m: Mirror[U], x: U#Tree) = ... (Beware the new syntax is still in flux, per #5825). |
BTW it seems Martin suggested it on the forum thread before I posted it
here.
…On Thu, Jan 31, 2019, 10:24 PM Paolo G. Giarrusso ***@***.***> wrote:
@nafg <https://github.com/nafg> Interesting idea!
Take def g[U <: Universe with Singleton](m: Mirror[U], x: U#Tree) = ....
We probably need the typeclass instance in scope where U#Tree appears, so
it must be an earlier argument — which the new implicits allow. In old and
"new" (#5458 <#5458>) syntax:
def g[U <: Universe with Singleton](implicit us: IsSingleton[U])(m: Mirror[U], x: U#Tree) = ...
def g[U <: Universe with Singleton] with IsSingleton[U] (m: Mirror[U], x: U#Tree) = ...
(Beware the new syntax is still in flux, per #5825
<#5825>).
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#4944 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAGAUE0EGtIqlteu-PwJJ9QEgW-l50f8ks5vI7NcgaJpZM4V8-EJ>
.
|
I don't think a special type class is the way to go. The problem that the |
Here is how a singleton type bound could work: The type Singleton[-T] Users write bounds as class C[A <: Singleton[A]](a: A)
// or with sugar:
class C[@singleton A](a: A) The type of every value In the example above, you can't instantiate The compiler could then provide useful reasoning on such types, such as |
@LPTK Interesting! So we only need the subtype checker to implement
for any singleton type |
Can someone remind me whether Scala 2 supports |
@odersky yes
|
I believe so, yes. |
A few of us discussed this, but it seems we lack an issue for it. Quoting from #4942:
In fact, already in Scala 2 we can exploit this and write the questionable
In Dotty we also get the clearly broken:
Only
h
fails, and just because we forbid1|2
syntactically for now (#1551), soh2
works.Since
Singleton
is special in core typing rules, @odersky suggested this endangers even soundness. Ad-hoc restrictions (say, forbiddingSingleton
as a type argument) seems a losing whack-a-mole game.Discussing this with @odersky today, we figured that
Singleton
behaves like a kind that can't be expressed via upper bounds, so we should consider something like an annotation or a modifier (tho modifiers on type variables don't exist yet).Migration isn't easy, but one can easily support simple use cases of form
[X <: Singleton]
or even[X <: Foo with Singleton]
. According to @nicolasstucki, eventype SingAlias = Singleton; def foo[X <: Foo with SingAlias]
doesn't currently work.Paging @milessabin and @soronpo, as this affects SIP-23.
The text was updated successfully, but these errors were encountered: