Я хотел бы создать протокол вроде следующего:
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
таким образом, я получу ошибку
Тип может не ссылаться как требование