How to use Scala singleton-object object types?

I am writing a class that serves as a base class for a series of singleton objects. In every single object there will be vals representing certain properties, and I want to write a method that for each single object only accepts the objects it creates.

So, I have the following:

class Obj[M <: Maker] class Maker { implicit val me: this.type = this def make[M <: Maker](implicit maker: M) = new Obj[M] def accept(obj: Obj[this.type]) = {...} } 

So far so good. Then I want to declare one of these singleton objects:

 object M extends Maker { val a = make } 

But then if I try this:

 M.accept(Ma) 

then I get a compile time error:

 type mismatch; found : com.test.Obj[object com.test.M] required: com.test.Obj[com.test.M.type] 

My questions:

  • What type of object com.test.M and how is it different from com.test.M.type ?
  • How can I do this in a smarter way?
+6
object types scala singleton
source share
4 answers

Get time, my good man! I fixed it 24 hours ago. Then I expect to see Velociraptors chasing the Dodo, violently cracking their buggy whips, looking at stock prices on their screensavers.

Emerging issue: http://lampsvn.epfl.ch/trac/scala/changeset/23622

 // 1130.scala class Obj[M <: Maker] class Maker { implicit val me: this.type = this def make[M <: Maker](implicit maker: M) = new Obj[M] def accept(obj: Obj[this.type]) = () } object M extends Maker { val a = make } object Test { def main(args: Array[String]): Unit = { M.accept(Ma) } } // too old % /scala/inst/scala-2.9.0.r23619/bin/scalac ./1130.scala ./1130.scala:15: error: type mismatch; found : Obj[object M] required: Obj[M.type] M.accept(Ma) ^ one error found // fresh enough % /scala/inst/scala-2.9.0.r23624/bin/scalac ./1130.scala % 
+16
source share

Use this.type instead of M This simplified example should work:

 class Obj[M <: Maker] class Maker { def make() = new Obj[this.type] def accept(obj: Obj[this.type]) = println(obj) } object M extends Maker object N extends Maker M.accept(M.make()) //works! M.accept(N.make()) //error! type mismatch! 
+8
source share

Your first question: β€œWhat is the type of object com.test.M , and how is it different from com.test.M.type ?”, Still did not answer. I did not find it documented in the specification, but it seems that type object M is an internal type that represents a class that is implicitly created when an object M is defined. Of course, M is the only instance of this class, so you can expect that the type of object M will be equivalent to M.type , but the compiler does not seem to see this.

The problem you ran into, as @retronym explained , is that the singleton type M.type not output for the type parameter when calling make . This is for the same reason that String is displayed instead of v.type in the following session:

 scala> val v = "asdf" v: java.lang.String = asdf scala> identity(v) res0: java.lang.String = asdf 

where identity is defined as

 def identity[T](v: T) = v 
+3
source share

It works:

 class Obj[M <: Maker] class Maker { implicit val me: this.type = this def make[M <: Maker](implicit maker: M) = new Obj[M] def accept(obj: Obj[this.type]) = () } object M extends Maker { val a = make[M.type] } M.accept(Ma) 

The secret sauce uses make[M.type] inside the singleton object.

@retronym is commendable for explaining this: How to properly enter-annotate this HList?

+2
source share

All Articles