What is intended for using Heap with non-comparable values?

to provide a little context, this is indeed an issue some longtime users of swift like myself recognize, and i think if we were to go back to 2015 and redesign Comparable, Equatable, and Hashable, it would probably not look exactly the same as it does now.

there is a thread with extensive discussion of this issue here.

in my view EHC’s biggest limitation is it doesn’t have the concept of “projected identity spaces”. to provide a concrete example, we cannot do things such as:

let separator:[OddNumber] = [3, 5, 9]
let numbers:[Int] = [3, 5, 9, 2, 0, 1]

numbers.starts(with: separator)

because we don’t have a way of expressing that an Int can be compared with an OddNumber by promoting the OddNumber value to “Int space”. swift also eschews the notion of a “reinterpret cast”. this is a language design principle, because “rebinding” [OddNumber][Int] is unsound under mutations. on the other hand that decision removes the typical escape hatch other languages use to work around this limitation.

i know this sounds like a toy example that is far removed from your Heap problem, but many pain points that come from EHC-based data structures like Heap aren’t actually problems with the data structure itself, at their core they are problems with identity spaces.

this got slightly better with the introduction of Identifiable a minor release or two back. but to my disappointment, we have not made much additional progress in this direction since then.


TLDR; programming in swift requires a very essentialist worldview, and things like “X is behaving as a Y in context Z” do not make sense to many of us, because the language does not just expect that X can “behave” like a Y, it expects that X must be a Y and be able to do Y things anywhere it travels.

C++ parameterizes this by always making you “say the Z”, which makes for namespaced::colon<angle::bracket, even_more::brackets<std::hell<everything::needs:to::be::said<out::loud, so::everyone::defaults<to::auto>>>>>. swift avoids this problem by requiring that every X should have exactly one canonical Z. some of us like this because you can reason about X without having to think about Zs.

as you get better at swift, you will learn how to factor away the Zs in your code, and you will just have to worry about Xs and Ys. :slight_smile:

1 Like