在构造函数的另一个参数类型中引用路径相关的参数类型

Referencing path-dependent type of an argument in the type of another argument to a constructor

我有自动机,它有依赖类型(我会称它们为关联),用于它们的状态和转换标签。

trait Automaton {
  type State
  type Label
  type Transition = (State, Label, State)
}

现在我想写一个 class,它将一个自动机和一个函数作为其参数,该函数对该特定自动机的转换进行某种计数。我会写:

class AutomataMagic(val aut: Automaton, val h: aut.Transition => Int) {

...
}

然而,that doesn't compile。有什么方法可以指定我希望我的函数专门针对 this 自动机的转换类型执行操作?

我是个白痴。显然,你可以这样做:

class AutomataMagic[A <: Automaton](val aut: Automaton, val h: A#Transition => Int) {}

错误消息说明了一切:

illegal dependent method type: parameter may only be referenced in a subsequent parameter section

作为 Luis Miguel Mejía Suárez ,您需要将 h 移动到另一个参数组。

class AutomataMagic(val aut: Automaton)(val h: aut.Transition => Int) {}

奇怪的是,doesn't work (probably because of this bug).

一个(非常天真的)解决方法是 this。不是很满意,但似乎有用。

class AutomataMagic private(_h: Automaton#Transition => Int, val aut: Automaton) {
  val h: aut.Transition => Int = _h.asInstanceOf[aut.Transition => Int]
  def this(aut: Automaton)(h: aut.Transition => Int) =
    this(h.asInstanceOf[Automaton#Transition => Int], aut)
}

编辑:Luis Miguel Mejía Suárez 建议将特性与伴随对象一起使用。 Here's 我对此的解释:

trait AutomataMagic[A <: Automaton] {
  val aut: A
  val h: aut.Transition => Int
}
object AutomataMagic {
  def apply[A <: Automaton](_aut: A)(_h: _aut.Transition => Int) = new AutomataMagic[A] {
    val aut: _aut.type = _aut
    val h = _h
  }
}

顺便说一下,第一个片段 compiles in Scala 3


另外,你真的不应该使用这个:

class AutomataMagic[A <: Automaton](val aut: Automaton, val h: A#Transition => Int) {}

不仅 A#Transitionaut.Transition 无关(至少使其成为 aut: A),类型投影 are unsound 将在 Scala 3 中被删除。也许它赢了在这种特定情况下对您来说无关紧要,因为 Transition 是不变的,但它并不安全。