Search code examples
scalatypestype-level-computationsingleton-type

Scala: "Genericising" over singleton types?


In Scala values and objects have singleton types assigned to them individually. So we can have:

val x = 1
type X = x.type
val y = 2
type Y = y.type
  • Can I write a method that takes only x as its argument?

I tried:

val x = 1
def foo(i: x.type ) = println(x.toString)

but it is giving me an error. I think it's complaining the about the fact that the type is unknown. Is there a way of specifying the fact that i is expected to be an int so that we can use say .tofloat on it?

  • Do X and Y above, namely the singleton types of 1 & 2, have a common ancestor so I can write a generic code that involves the singleton type of say Int values.

  • Similarly,

if I had for example

 val list = [1,2,3]

is there a way of writing a code that genericises over these and can only be fed one of these values?


Solution

  • In 2.12.5, it works for boxed non-primitive integers only:

    val x: java.lang.Integer = 42
    def foo(i: x.type): Unit = println(i.toFloat)
    

    I don't know why it doesn't work for val x: Int though. In Dotty, it works also for primitive types:

    val x: Int = 42
    def foo(i: x.type): Unit = println(x.toFloat)
    

    For more than one value (list), you could take an enumeration, or simply create a little class with a private constructor, and instantiate all valid values inside the companion class:

    class SmallInt private(value: Int) {
      def asFloat = value.toFloat
    }
    
    object SmallInt {
      val one = new SmallInt(1)
      val two = new SmallInt(2)
      val three = new SmallInt(3)
    }
    

    this wouldn't compile then:

    val foo = new SmallInt(345678) // forbidden