Я хотел бы создать протокол вроде следующего:
protocol Parser {
func parse() -> ParserOutcome<?>
}
enum ParserOutcome<Result> {
case result(Result)
case parser(Parser)
}
Я хочу иметь парсеры, которые возвращают либо результат определенного типа, либо другой парсер.
Если я использую связанный тип на Parser, тогда я не могу использовать Parser в enum. Если я укажу общий тип функции parse(), тогда я не могу определить его в реализации без общего типа.
Как я могу это достичь?
Используя generics, я мог бы написать что-то вроде этого:
class Parser<Result> {
func parse() -> ParserOutcome<Result> { ... }
}
enum ParserOutcome<Result> {
case result(Result)
case parser(Parser<Result>)
}
Таким образом, параметр Parser будет параметризован по типу результата. parse() может возвращать результат типа Result или любого вида анализатора, который выводит либо результат типа Result, либо другой парсер, параметризованный тем же типом Result.
Вместе со связанными типами, насколько я могу судить, у меня всегда будет ограничение Self:
protocol Parser {
associatedtype Result
func parse() -> ParserOutcome<Result, Self>
}
enum ParserOutcome<Result, P: Parser where P.Result == Result> {
case result(Result)
case parser(P)
}
В этом случае я не могу иметь никакого типа синтаксического анализатора, который бы возвращал тот же самый тип Result, он должен быть одним и тем же типом парсера.
Я хотел бы получить такое же поведение с протоколом Parser, как и с общим определением, и я хотел бы иметь возможность сделать это в рамках системы типов без введения новых типов в штучной упаковке, просто как я могу с нормальным общим определением.
Мне кажется, что определение associatedtype OutcomeParser: Parser внутри протокола Parser, тогда возврат enum, параметризованный этим типом, разрешит проблему, но если я попытаюсь определить OutcomeParser таким образом, я получу ошибку
Тип может не ссылаться как требование