我想知道成员类型在 Scala 中是如何工作的,以及我应该如何关联类型。
一种方法是使关联类型成为类型参数。这种方法的优点是我可以规定类型的变化,并且我可以确定子类型不会改变类型。缺点是,我无法从函数中的类型推断类型参数。
第二种方法是使关联类型成为第二种类型的成员,它的问题是我无法对子类型的关联类型规定界限,因此,我不能在函数参数中使用该类型(当 x : X, X#T 可能与 xT 没有任何关系)
一个具体的例子是:
我有一个 DFA 的特征(可能没有 type 参数)
trait DFA[S] { /* S is the type of the symbols in the alphabet */
trait State { def next(x : S); }
/* final type Sigma = S */
}
我想创建一个在输入序列上运行这个 DFA 的函数,我想要
- 该函数必须将任何内容
<% Seq[alphabet-type-of-the-dfa]
作为输入序列类型 - 函数调用者不需要指定类型参数,都必须推断
- 我希望使用具体的 DFA 类型调用该函数(但如果有一个解决方案,该函数没有 DFA 的类型参数,那没关系)
- 字母表类型必须不受约束(即,必须有一个用于 Char 以及未知用户定义类的 DFA)
- 具有不同字母类型的 DFA 不是子类型
我试过这个:
def runDFA[S, D <: DFA[S], SQ <% Seq[S]](d : D)(seq : SQ) = ....
这行得通,除了这里没有推断出类型 S,所以我必须在每个调用站点上编写整个类型参数列表。
def runDFA[D <: DFA[S] forSome { type S }, SQ <% Seq[D#Sigma]]( ... same as above
这不起作用(对类型 D 的无效循环引用???(它是什么?))
我还删除了类型参数,创建了一个抽象类型 Sigma 并尝试在具体类中绑定该类型。runDFA 看起来像
def runDFA[D <: DFA, SQ <% Seq[D#Sigma]]( ... same as above
但这不可避免地会遇到诸如“类型不匹配:预期dfa.Sigma
,得到D#Sigma
”之类的问题
有任何想法吗?指针?
编辑:
由于答案表明没有简单的方法可以做到这一点,有人可以详细说明为什么这是不可能的以及必须改变什么才能奏效吗?
我希望 runDFA ro 成为一个自由函数(而不是方法)的原因是我想要其他类似的函数,如自动机最小化、常规语言操作、NFA 到 DFA 转换、语言分解等,并将所有这些都放在一个类中几乎违反了OO设计的任何原则。