[swift-evolution] Revisiting 'T != Type' in where clause

Robert Bennett rltbennett at icloud.com
Thu Mar 16 20:40:24 CDT 2017


Hello,

This discussion sort of fizzled out when the topic was first introduced. Joe Groff had asked the following:

> Do you have a concrete example where you need this? It'd be good to know whether the types are ambiguous due to type checker bugs, or whether there's a principle by which they could be naturally ordered.

There is an example of this ordering that I stumbled upon recently. Suppose I wish to extend `Array` with a `uniques()` function that returns an array containing the unique elements of `self`. For performance reasons, I would first write a method for arrays with Hashable elements, so that I could check for uniqueness in constant time per element.

extension Array where Element: Hashable {
	func uniques() -> [Element] {
		var seen: Set<Element> = []
		var uniq: [Element] = []
		
		for e in self {
			if !seen.contains(e) {
				seen.insert(e)
				uniq.append(e)
			}
		}
		
		return uniq
	}
}

However I would still like to have a `uniques()` method for arrays whose elements are merely Equatable, and I'm willing to take the performance cost of O(n) lookup per element.

extension Array where Element: Equatable {
	func uniques() -> [Element] {
		var uniq: [Element] = []
		
		for e in self {
			if !uniq.contains(e) {
				uniq.append(e)
			}
		}
		
		return uniq
	}
}

However, there is a problem, which is that elements that are Hashable are also Equatable, and so there is ambiguity when calling this method:

// error: ambiguous use of 'uniques()'
print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())


If I could add `Element != Hashable` to the second extension, there would be no ambiguity.

FWIW replacing Array with Collection and Element with Iterator.Element fixes the error. The first extension (the one for Hashables) is called. I'm not sure why it is ambiguous in one case and not the other.



More information about the swift-evolution mailing list