question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

The Singleton "kind" is not an upper bound

See original GitHub issue

A few of us discussed this, but it seems we lack an issue for it. Quoting from #4942:

If A <: Singleton and B <: Singleton, it follows that A | B <: Singleton, but for instance 1 | 2 is not actually a singleton type.

In fact, already in Scala 2 we can exploit this and write the questionable

  def f[Bound, A <: Bound, B <: Bound](cond: Boolean, a: A, b: B): Bound = if (cond) a else b
  def g(cond: Boolean): Singleton = f[Singleton, 1, 2](cond, 1, 2)

In Dotty we also get the clearly broken:

  def f[Bound, A <: Bound, B <: Bound](cond: Boolean, a: A, b: B): (A | B) & Bound = if (cond) a else b
  def g(cond: Boolean): Singleton = f[Singleton, 1, 2](cond, 1, 2)
  // def h(cond: Boolean): (1|2) & Singleton = f[Singleton, 1, 2](cond, 1, 2) // doesn't compile
  type || [A, B] = A | B
  type Boo = 0 || 1

  // def h1(cond: Boolean): (1||2) & Singleton = f[Singleton, 1, 2](cond, 1, 2) // still fails because 1 | 2 is collapsed eagerly

def f2[Bound, A <: Bound, B <: Bound](cond: Boolean, a: A, b: B): (A || B) & Bound = if (cond) a else b

def h2(cond: Boolean): (1||2) & Singleton = f2[Singleton, 1, 2](cond, 1, 2)
def h2(cond: Boolean): Int(1) Any Int(2) & Singleton

Only h fails, and just because we forbid 1|2 syntactically for now (#1551), so h2 works. Since Singleton is special in core typing rules, @odersky suggested this endangers even soundness. Ad-hoc restrictions (say, forbidding Singleton 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, even type SingAlias = Singleton; def foo[X <: Foo with SingAlias] doesn’t currently work.

Paging @milessabin and @soronpo, as this affects SIP-23.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:23 (18 by maintainers)

github_iconTop GitHub Comments

2reactions
LPTKcommented, Feb 1, 2019

Here is how a singleton type bound could work:

The Singleton type is parameterized and contravariant:

type Singleton[-T]

Users write bounds as T <: Singleton[T], which could also be syntax-sugared with an annotation:

class C[A <: Singleton[A]](a: A)

// or with sugar:

class C[@singleton A](a: A)

The type of every value v extends Singleton[v.type]. Non-singleton types naturally could extend Singleton[Nothing], which would be like a top type, but it’s not really useful as we already have Any. In any case we do have v.type | w.type <: Singleton[v.type] | Singleton[w.type] =:= Singleton[v.type & w.type] <: Singleton[Nothing].

In the example above, you can’t instantiate C with a non-singleton type, because that would mean having to pass an a argument typed Nothing or some other impossible stuff (like v.type & w.type).

The compiler could then provide useful reasoning on such types, such as List[Int] & Singleton[x.type] <: x.type. This would actually be useful to reason modularly about subtyping knowledge involving singleton types, which is currently very hard – sometimes we want to refine a singleton type with a type that is more precise than its widened form.

1reaction
nafgcommented, Jan 31, 2019

Why can’t it be done with a special typeclass?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Singleton bound - Wikipedia
In coding theory, the Singleton bound, named after Richard Collom Singleton, is a relatively crude upper bound on the size of an arbitrary...
Read more >
[2208.01138] Generalized Singleton Type Upper Bounds - arXiv
When the list size L is 1, this gives many new Singleton type upper bounds on the sizes of codes with a given...
Read more >
Is the set of upper bounds squared either empty or a singleton?
Your conjecture is not quite right, for two reasons. First, you've forgotten the case when UB(A)=∅. Then UB(UB(A))=P, since every element ...
Read more >
Notes 4: Elementary bounds on codes 1 Singleton bound
We now prove an upper bound which shows that the relative distance has to be at most 1/2. (and thus the Hamming bound...
Read more >
What's the status of union/intersection types + singleton types ...
I'd like to know if the status of the following is not yet done, ... unions over singletons then the least upper bound...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found