Skip to content

Latest commit

 

History

History
54 lines (36 loc) · 1.51 KB

path_dependent_type.adoc

File metadata and controls

54 lines (36 loc) · 1.51 KB

Path Dependent Type

This Type allows us to type-check on a Type internal to another class. This may seem weird at first, but is very intuitive once you see it:

class Outer {
  class Inner
}

val out1 = new Outer
val out1in = new out1.Inner // concrete instance, created from inside of Outer

val out2 = new Outer
val out2in = new out2.Inner // another instance of Inner, with the enclosing instance out2

// the path dependent type. The "path" is "inside out1".
type PathDep1 = out1.Inner


// type checks

val typeChecksOk: PathDep1 = out1in
// OK

val typeCheckFails: PathDep1 = out2in
// <console>:27: error: type mismatch;
// found   : out2.Inner
// required: PathDep1
//    (which expands to)  out1.Inner
//       val typeCheckFails: PathDep1 = out2in

The key to understand here is that "each Outer class has its own Inner class", so it’s a different Type - dependent on which path we use to get there.

Using this kind of typing is useful, we’re able to enforce getting the type from inside of a concrete parameter. An example of a signature using this typing would be:

class Parent {
  class Child
}

class ChildrenContainer(p: Parent) {
  type ChildOfThisParent = p.Child

  def add(c: ChildOfThisParent) = ???
}

Using the path dependent type we have now encoded in the type system, the logic, that this container should only contain children of this parent - and not "any parent".

We’ll see how to require the "child of any parent" Type in the section about Type Projections soon.