I think Simon was referring to two separate problems in his post - first:
Using ‘KeyType' as a concrete type conforming to protocol 'Hashable' is not supported
And second:
type 'Key' constrained to non-protocol type ‘String’
The first error (which is of particular interest to me) you can reproduce with only the first half, leaving out MyProtocol entirely:
public protocol KeyType : Hashable {
}
public protocol ValueType {
}
struct MyConcrete {
let values : [KeyType: ValueType]
}
I’m fairly new to Swift, and this is my very first time on the mailing lists, so forgive me if this has been answered before…but this seems to me like an arbitrary shortcoming of the compiler and not an intentional language design decision. (As I understand, this comes out of the fact that protocols don’t conform to themselves…?)
I wonder if anyone knows whether there are any plans to look at this corner of the language and allow this use case.
(My particular use case can be seen here: AnyEquatable.swift · GitHub … and the best information I’ve been able to find on this so far is here: swift - Protocol doesn't conform to itself? - Stack Overflow )
Thanks
Jason
hooman
(Hooman Mehr)
March 26, 2016, 12:27am
2
Here is the best you can do for your particular use case:
protocol AnyEquatable { func equals(other: Any) -> Bool }
func ==<T: Equatable>(lhs: T, rhs: Any) -> Bool {
if let rhs = rhs as? T { return lhs == rhs } else { return false }
}
extension Bool: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Int: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Double: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension String: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Array {
func indexOfAny(element : AnyEquatable) -> Index? { return indexOf { element.equals($0) } }
}
var array: [Any] = [false, 1, 2.0, "three"]
array.indexOfAny(2.0)
···
On Mar 25, 2016, at 2:51 PM, Jason Sadler via swift-users <swift-users@swift.org> wrote:
(My particular use case can be seen here: AnyEquatable.swift · GitHub … and the best information I’ve been able to find on this so far is here: swift - Protocol doesn't conform to itself? - Stack Overflow )
hooman
(Hooman Mehr)
March 26, 2016, 12:59am
3
You can also get a heterogenous dictionary, but it needs a type erasing helper box. With the following declarations:
public func ==<T: Equatable>(lhs: T, rhs: Any) -> Bool {
if let rhs = rhs as? T { return lhs == rhs } else { return false }
}
public struct AnyKey : Hashable {
public let hashValue: Int
public let key: Any
public let equals: (AnyKey) -> Bool
init<T: Hashable>(_ key: T) {
self.hashValue = key.hashValue
self.key = key
self.equals = { self.key as! T == $0.key }
}
}
public func == (lhs: AnyKey, rhs: AnyKey) -> Bool { lhs.equals(rhs) }
You can now create a heterogenous [AnyKey: Any] dictionary. Note that `AnyKey` is not very memory efficient.
···
On Mar 25, 2016, at 5:27 PM, Hooman Mehr <hooman@mac.com> wrote:
On Mar 25, 2016, at 2:51 PM, Jason Sadler via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
(My particular use case can be seen here: AnyEquatable.swift · GitHub … and the best information I’ve been able to find on this so far is here: swift - Protocol doesn't conform to itself? - Stack Overflow )
Here is the best you can do for your particular use case:
protocol AnyEquatable { func equals(other: Any) -> Bool }
func ==<T: Equatable>(lhs: T, rhs: Any) -> Bool {
if let rhs = rhs as? T { return lhs == rhs } else { return false }
}
extension Bool: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Int: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Double: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension String: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Array {
func indexOfAny(element : AnyEquatable) -> Index? { return indexOf { element.equals($0) } }
}
var array: [Any] = [false, 1, 2.0, "three"]
array.indexOfAny(2.0)
hooman
(Hooman Mehr)
March 26, 2016, 1:08am
4
Oops! that is buggy. I should check syntax before posting…
Here is the corrected version:
public struct AnyKey : Hashable {
public let hashValue: Int
public let key: Any
public let equals: (Any, AnyKey) -> Bool
init<T: Hashable>(_ key: T) {
self.hashValue = key.hashValue
self.key = key
self.equals = { $0 as! T == $1.key }
}
}
public func == (lhs: AnyKey, rhs: AnyKey) -> Bool { return lhs.equals(lhs,rhs) }
···
On Mar 25, 2016, at 5:59 PM, Hooman Mehr via swift-users <swift-users@swift.org> wrote:
You can also get a heterogenous dictionary, but it needs a type erasing helper box. With the following declarations:
public func ==<T: Equatable>(lhs: T, rhs: Any) -> Bool {
if let rhs = rhs as? T { return lhs == rhs } else { return false }
}
public struct AnyKey : Hashable {
public let hashValue: Int
public let key: Any
public let equals: (AnyKey) -> Bool
init<T: Hashable>(_ key: T) {
self.hashValue = key.hashValue
self.key = key
self.equals = { self.key as! T == $0.key }
}
}
public func == (lhs: AnyKey, rhs: AnyKey) -> Bool { lhs.equals(rhs) }
You can now create a heterogenous [AnyKey: Any] dictionary. Note that `AnyKey` is not very memory efficient.
On Mar 25, 2016, at 5:27 PM, Hooman Mehr <hooman@mac.com <mailto:hooman@mac.com>> wrote:
On Mar 25, 2016, at 2:51 PM, Jason Sadler via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
(My particular use case can be seen here: AnyEquatable.swift · GitHub … and the best information I’ve been able to find on this so far is here: swift - Protocol doesn't conform to itself? - Stack Overflow )
Here is the best you can do for your particular use case:
protocol AnyEquatable { func equals(other: Any) -> Bool }
func ==<T: Equatable>(lhs: T, rhs: Any) -> Bool {
if let rhs = rhs as? T { return lhs == rhs } else { return false }
}
extension Bool: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Int: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Double: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension String: AnyEquatable { func equals(other: Any) -> Bool { return self == other } }
extension Array {
func indexOfAny(element : AnyEquatable) -> Index? { return indexOf { element.equals($0) } }
}
var array: [Any] = [false, 1, 2.0, "three"]
array.indexOfAny(2.0)
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users