Я хотел бы знать, как типы элементов работают в Scala и как я должен связывать типы.
Один из подходов - сделать связанный тип параметром типа. Преимущества этого подхода в том, что я могу прописать дисперсию типа, и я могу быть уверен, что подтип не меняет тип. Недостатки в том, что я не могу вывести параметр типа из типа в функции.
Второй подход заключается в том, чтобы сделать связанный тип членом второго типа, из-за чего я не могу прописать границы для связанных типов подтипов и, следовательно, не могу использовать тип в параметрах функции ( когда x: X, X # T может не иметь никакого отношения к xT)
Конкретный пример будет:
У меня есть черта для DFA (может быть без параметра типа)
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, все в порядке)
- типы алфавита должны быть неограниченными (т. Е. Должен быть DFA для Char, а также для еще неизвестного пользовательского класса)
- 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
»
Есть идеи? Указатели
Edit:
Как показывают ответы, простого способа сделать это не может, может кто-нибудь подробнее рассказать, почему это невозможно и что нужно изменить, чтобы это работало?
Причины, по которым я хочу, чтобы runDFA ro была бесплатной функцией (а не методом), заключаются в том, что я хочу, чтобы другие подобные функции, такие как минимизация автоматов, регулярные языковые операции, преобразования NFA в DFA, языковая факторизация и т. Д., Имели все это внутри одного класса просто против практически любого принципа ОО дизайна.