Scala Зависимый тип не компилируется - PullRequest
4 голосов
/ 03 апреля 2019

Этот код должен скомпилироваться в Scala:

trait Pipe {
  type Input
  type Output
  def apply(input: Input): Output
}

object Pipe {
  trait Start extends Pipe {
    override type Input = Seq[String]
  }

  abstract class Connect(val prev: Pipe) extends Pipe {
    override type Input = prev.Output
  }
}

object Pipe1 extends Pipe.Start {
  override type Output = Int
  override def apply(input: Input): Output = 
   input.length
}

object Pipe2 extends Pipe.Connect(prev = Pipe1) {
  override type Output = Boolean
  override def apply(input: Input): Output = 
   input%2 == 0
}

Pipe1 компилируется нормально, но Pipe2 не компилируется с:

value % is not a member of Pipe2.this.Input
     input%2 == 0
          ^

Я знаю, что могу решить эту проблему с помощью обобщенных, а не зависимых типов, но это должно работать, поскольку Pipe2.Input должно проверять тип, равное Int из Pipe1.Output

Ответы [ 2 ]

6 голосов
/ 03 апреля 2019

Элемент prev = Pipe в вызове конструктора не является правильным путем, компилятор не может связать с ним никакую информацию о типе, поэтому вы получите довольно бесполезный prev.Output =:= Input для некоторого неопределенного prev: Pipe, который был установите что-то в конструкторе.

С минимальным изменением все работает как положено:

trait Pipe {
  type Input
  type Output
  def apply(input: Input): Output
}

object Pipe {
  trait Start extends Pipe {
    override type Input = Seq[String]
  }

  abstract class Connect extends Pipe {
    val prev: Pipe
    override type Input = prev.Output
  }

}

object Pipe1 extends Pipe.Start {
  override type Output = Int
  override def apply(input: Input): Output = 
    input.length
}

object Pipe2 extends Pipe.Connect {
  val prev = Pipe1
  override type Output = Boolean
  override def apply(input: Input): Output = input % 2 == 0
}

Вот почему он называется путь зависимый (не член зависимый, а не значение зависимый и т. Д.).

2 голосов
/ 03 апреля 2019

@ Ответ Андрея-Тюкина работает выше.Я также нашел эту работу вокруг:

trait Pipe {
  type Input
  type Output
  def apply(input: Input): Output
}

object Pipe {
  trait Start extends Pipe {
    override type Input = Seq[String]
  }

  abstract class Connect[O](val prev: Pipe.Emitting[O]) extends Pipe {
    override type Input = O
  }

  type Emitting[O] = Pipe {type Output = O}
}

object Pipe1 extends Pipe.Start {
  override type Output = Int
  override def apply(input: Input): Output = 
   input.length
}

object Pipe2 extends Pipe.Connect(prev = Pipe1) {
  override type Output = Boolean
  override def apply(input: Input): Output = 
   input%2 == 0
}
...