Using associatedtype from generics in function not recognized

I am trying to create af function which takes another instance of the same class and a closure. The clousure should use an associatedtype of the other instance it conforms to as an parameter.

I can't get it to work. I've tried several things and always end up with a closure that is not recognized or doesn't match the signature.

struct Person {
    let name: String
}

let steve = Person(name: "Steve Jobs")

protocol SelectorProtocol {
    associatedtype State
    associatedtype Value
    func map(_ state: State) -> Value
}

class Selector<State, Value> {
    let projector: (State) -> Value
    
    init(keyPath: KeyPath<State, Value>) {
        self.projector = { $0[keyPath: keyPath] }
    }
    
    init<S1: SelectorProtocol>(_ selector1: S1, _ projector: @escaping (S1.Value) -> Value) where S1.State == State {
        self.projector = { projector(selector1.map($0)) }
    }
    
    func map(state: State) -> Value {
        return projector(state)
    }
}

let selectorKeyPath = Selector(keyPath: \Person.name)
print(selectorKeyPath.map(state: steve)) // Prints "Steve Jobs" correctly

let selector1 = Selector(selectorKeyPath, { name in name.capitalized }) // <-- Error here saying "Expression type 'Selector<_, _>' is ambiguous without more context"
print(selector1.map(state: steve))

When I try to specify the generic arguments to the last Selector it says that S1 could not be inferred.

Can anybody help me with this?

You forgot to conform Selector to SelectorProtocol, so there's no init that matches the signature.

2 Likes

Wow... :man_facepalming: Don't understand how I missed that.

Thank you! :tada:

Might still be worthwhile to file your code example at bugs.swift.org for the poor diagnostic message. Seems to me that the compiler error could more clearly state Selection<X, Y> does not conform to SelectorProtocol.

1 Like