Swift protocol conformance issue with sub type of protocol

Viewed 102
internal protocol Reducer {
        associatedtype S : BaseState
        associatedtype A : BaseAction
        
        func reduce(state: S, action: A) -> S
    }
    
    internal class ReducerImpl : Reducer {
        func reduce(state: MainState, action: MainAction) -> MainState { //<-- Error because MainAction is a protocol not a concrete one.
            return state
        }
    }
    
    internal class MainState : BaseState {}
    internal protocol MainAction : BaseAction {}
    
    internal protocol BaseState {}
    internal protocol BaseAction {}

If I change MainAction from protocol to class, the compile error disappears.

I've searching many articles to understand of this error but failed.

Do I have to pass a concrete parameter(eg. enum, class, struct) in reduce(...) function?

I want to make ReducerImpl can take various action type that conform MainAction.

Is there anyone who can give me explain about that error and why the Swift adopt this kind of rule.

1 Answers

associatedtype has to be concrete, ie. a type and not a protocol.

What you can do is to create a narrower protocol with a generic function that accepts a MainAction parameter:

internal protocol MainReducer {
    associatedtype State
    func reduce<Action>(state: State, action: Action) -> State where Action: MainAction
}

internal class ReducerImpl: MainReducer {
    func reduce<Action>(state: MainState, action: Action) -> MainState where Action: MainAction {
        return state
    }
}
Related