I have automata, which have dependent types (I would call them associated) for the states and labels of their transitions.
trait Automaton {
type State
type Label
type Transition = (State, Label, State)
}
Now I want to write a class that takes as its argument an automaton and a function doing some sort of counting for transitions on that particular automaton. I would write:
class AutomataMagic(val aut: Automaton, val h: aut.Transition => Int) {
...
}
However, that doesn't compile. Is there any way I can specify that I want my function to do things to specifically this automaton's transition type?
The error message says it all:
illegal dependent method type: parameter may only be referenced in a subsequent parameter section
As Luis Miguel Mejía Suárez said, you need to move h
to another parameter group.
class AutomataMagic(val aut: Automaton)(val h: aut.Transition => Int) {}
Oddly enough, that doesn't work (probably because of this bug).
A (very naive) workaround would be this. It's not very satisfying, but it seems to work.
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)
}
EDIT: Luis Miguel Mejía Suárez suggested using a trait with a companion object. Here's my interpretation of that:
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
}
}
By the way, the first snippet compiles in Scala 3.
Also, you really shouldn't use this:
class AutomataMagic[A <: Automaton](val aut: Automaton, val h: A#Transition => Int) {}
Not only is A#Transition
unrelated to aut.Transition
(at least make it aut: A
), type projections are unsound and will be dropped in Scala 3. Maybe it won't matter to you in this specific case because Transition
is invariant, but it is not safe.