scalatypescake-patternsingleton-typerefinement-type

Understanding real cake pattern code with self and this references


I have recently learnt about cake pattern and the differences between the uses of self => and self:T => (see here). The difference between these technicalities and real Scala code as remarked here continue to create me problems. For instance, see the following code snippet taken from the Inox project:

trait Trees
  extends Expressions
     with Constructors
     with Extractors
     with Types
     with Definitions
     with Printers
     with TreeOps { self =>

     ...

     val interpolator: Interpolator { val trees: Trees.this.type } = new {
      protected val trees: Trees.this.type = Trees.this
     } with Interpolator    

     ...
}

In summary, the whole snippet does not make much sense to me (and it is a pattern frequently repeated in the code), let me explain:

  1. What is this syntax?

val interpolator: Interpolator { ... }

up to now I wrote val name: Type = value, here there is no equal.

  1. Trees.this.type should be a type, but what type? It should be defined in Trees trait, and the this context which I bet is different from the trait Trees context (related to problem 1). I also looked on file Interpolators but there does not seem to be a type element.

  2. The greatest line is protected val trees: Trees.this.type = Trees.this.

Can anybody explain me what is going on here?


Solution

    1. It's a declaration of variable interpolator with type Interpolator { val trees: Trees.this.type }. The type Interpolator { val trees: Trees.this.type } is a subtype of Interpolator, but refined with the additional restriction that trees is not just some Trees, but instead one concrete instance of Trees, namely the one of the singleton type Trees.this.type. There is an equal-=-symbol: between the type Interpolator { val trees: Trees.this.type } and the new { ... } with Interpolator.

      Shorter example which demonstrates the syntax in isolation:

      trait Foo {
        val trees: Any
      }
      def interpolator: Foo { val trees: Int } = 
        new Foo { val trees = 42 }
      
      interpolator.trees + 58
      
    2. Trees.this.type is the singleton type of the value this. There is only one value of this type: Trees.this.

      Shorter example that demonstrates usage of .type:

      class Bar
      val b = new Bar
      val c: b.type = b
      
    3. You are setting the value trees to Trees.this. You also guarantee to the compiler that trees is not just some Trees, but that trees is the singleton value Trees.this of the singleton type Trees.this.type, which is a strict subtype of Trees.