Why can this protocol “only be used as a generic constraint”?

前端 未结 2 1489
花落未央
花落未央 2021-02-01 16:44

I\'m attempting to do the following in Swift:

protocol ProtocolWithAlias {
    typealias T
}

protocol AnotherProtocol {
    func someFunc() -> ProtocolWithAl         


        
2条回答
  •  北恋
    北恋 (楼主)
    2021-02-01 17:13

    It's possible to implement this by inverting the control: instead of returning a value from someFunc we pass a consumer that can accept any type implementing ProtocolWithAlias and do something with it.

    protocol ProtocolWithAlias {
        typealias T
    }
    
    protocol ProtocolConsumer {
        func consume(value: T)
    }
    
    protocol AnotherProtocol {
        func someFunc(consumer: ProtocolConsumer)
    }
    

    This trick is known as transforming the function to continuation passing style (CPS). Unfortunately I couldn't find any way to implement this without CPSing. The type system feature we are looking is existential types (and this thread has a nice explanation), but I think Swift doesn't support them (yet).


    Why is the other answer not correct? What this signature tells:

    func someFunc() -> T
    

    is that this function can return a value of type T for any type implementing ProtocolWithAlias that the caller chooses, but we wanted it to be chosen by the callee.

    It's not even possible to write a sensible implementation of this function. Lets pretend I have an implementation of someFunc: I could create a new class implementing ProtocolWithAlias and request someFunc to somehow create an instance of this class:

    class Uninhabited: ProtocolWithAlias {
        typealias T = Int
        init(nope: Uninhabited) {}
    }
    
    ...
    
    let impossible: Uninhabited = someFunc()
    

提交回复
热议问题