Как express использовать эту функцию `map` с помощью протокола - PullRequest
1 голос
/ 25 мая 2020

У меня есть следующий код

enum AppSubscription<Event>: Subscription {
    func map<ParentSubscription>(_ lift: @escaping (Event) -> (ParentSubscription.Event)) -> ParentSubscription where ParentSubscription: Subscription {
        switch self {
        case let .loadedArticles(cb):
            return AppSubscription<ParentSubscription.Event>.loadedArticles { article, isHot in lift(cb(article, isHot)) } as! ParentSubscription

        case let .savedArticles(cb):
            return AppSubscription<ParentSubscription.Event>.savedArticles { article in lift(cb(article)) } as! ParentSubscription

        case let .deletedArticles(cb):
            return AppSubscription<ParentSubscription.Event>.deletedArticles { article in lift(cb(article)) } as! ParentSubscription
        }
    }

    case loadedArticles((Article, Bool) -> Event)
    case savedArticles((Article) -> Event)
    case deletedArticles((Article) -> Event)
}

, и я хочу создать протокол для Subscription (которому соответствует AppSubscription). Это моя попытка

public protocol Subscription {
    associatedtype Event
    func map<ParentSubscription>(_ lift:
        @escaping (Event) -> (ParentSubscription.Event)) -> ParentSubscription where
        ParentSubscription: Subscription
}

, но я получаю ошибки

Subs.playground:21:31: Protocol 'Subscription' can only be used as a generic constraint because it has Self or associated type requirements

и

Subs.playground:21:28: Same-type requirement makes generic parameter 'ParentSubscription' non-generic

Как мне записать функцию протокола map в соответствует реализации в AppSubscription?


Изменить : переключено на ParentSubscription: Subscription согласно предложению @ Fabian. Также добавлены недостающие @escaping в AppSubscription.

С изменениями я не уверен, как согласовать протокол с реализацией. Если я использую подпись точно так, как написано в протоколе

func map<ParentSubscription, ParentEvent>(_ lift: @escaping (Event) -> (ParentEvent)) -> ParentSubscription where ParentSubscription : Subscription, ParentEvent == ParentSubscription.Event {

, я вынужден использовать as! ParentSubscription, что кажется избыточным. Если я использую подпись

func map<ParentEvent>(_ lift: (Event) -> ParentEvent) -> AppSubscription<ParentEvent> {

, он жалуется, что AppSubscription не соответствует протоколу. Это единственный способ заставить его скомпилировать для использования as!?


Edit2 : удален избыточный ParentEvent и заменен на ParentSubscription.Event согласно другому предложению @Fabian .

Теперь код компилируется, и это здорово, и большое спасибо @Fabian.

Я думаю, будет справедливо сказать, что количество подсказок типа кажется неудобным, есть ли способ избежать или сократить какое-либо из них?


Edit3 : Добавление реплики https://repl.it/@opsb / ScratchyTrustworthyArchitect , чтобы упростить игру.

...