I am using ReactiveSwift. There are two protocols: CommonProtocol and SpecificProtocol.
When I use SpecificProtocol in map function there is an error Type 'any SpecificProtocol' cannot conform to 'Equatable'. However it is perfectly fine with using ConreateItem
protocol CommonProtocol {}
protocol SpecificProtocol: CommonProtocol, Equatable
extension SpecificProtocol where Self: Equatable {
static func == (lhs: Self, rhs: Self) -> Bool { return true }
}
class ConreateItem: SpecificProtocol{}
var messages = MutableProperty<[CommonProtocol]?>(nil)
messages.producer
// .map({ $0 as? [ConreateItem] }) //that is ok
.map({ $0 as? [any SpecificProtocol] })//Type 'any SpecificProtocol' cannot conform to'Equatable'
.skipRepeats()
I don't understand why/how SpecificProtocol is converted to any SpecificProtocol. And what is the correct way to implement Equatable constraint on protocol so I could use it in map function (Equatable is required for high order function in my case)
map is of ReactiveSwift
tl;dr
==inEquatablerequires both parameters to be of the same concrete type. This cannot be determined if the compiler only knows that each of the two instances isany Equatable.Without looking too closely at
skipNil()it looks like it needs a sequence of objects that conform toEquatable.SpecificProtocoldoes not declare conformance toEquatable, it just declares a function==(which has a compiler error because it does not return aBool), so there is a type error.By the way, note that protocols are not types in Swift which is why the "any" is there. It's short for "anything whose type conforms to
SpecificProtocol". At some point in the future, you'll have to writeanyexplicitly in your declarations. e.g.[any SpecificProtocol]To make SpecificProtocol instances conform to
Equatableyou needYou can keep the extension to define a default
==function or allow concrete types to define their own implementations of it.Update
The reason you see the error message even with
SpecificProtocolconforming toEquatableis because instances of arbitrary types that both conform toEquatablecannot be compared for equality."foo" == 3is not allowed even thoughStringandIntare both equatable.In order for the array that you return from
mapto be Equatable, it must be able to compare its elements against the elements of another array of the same type and if you know nothing about the elements except they both conform toSpecificProtocolyou can't compare them for equality becauseEquatableconformance requires both parameters of==to be of the same concrete type.Also, I don't think your map closure should be returning an array. I think it should look like
.map({ $0 as? any SpecificProtocol })