opCmp / opEquals do not actually support partial orders

John Colvin john.loughran.colvin at gmail.com
Tue Jul 17 21:18:12 UTC 2018


On Tuesday, 17 July 2018 at 18:21:26 UTC, H. S. Teoh wrote:
> As we know, when opCmp is defined for a user type, then 
> opEquals must also be defined in order for == to work, even 
> though in theory the compiler could translate x==y into 
> x.opCmp(y)==0.
>
> In the past, it was argued that this was so that partial orders 
> could be made to work, i.e., it could be the case that x and y 
> are incomparable, then x.opCmp(y) would return 0, and 
> x.opEquals(y) would be false. Supposedly, this would allow us 
> to, say, model the subset relation (which is a partial order) 
> using the comparison operators.
>
> However, this supposition is in fact false.  The reason is that 
> `<=` and `>=` *only* check the return value of opCmp(); they do 
> not check opEquals at all.  So suppose we define a Set type, 
> and we'd like to use the comparison operators to model the 
> subset relation.  How would we define opCmp and opEquals?
>
> opEquals is obvious, of course.  It's true if x and y have the 
> same elements, false otherwise.
>
> But opCmp turns out to be a tarpit.  Here's why:
>
> - If x is a (strict) subset of y, then obviously we should 
> return -1.
>
> - If x is a (strict) superset of y, then obviously we return 1.
>
> - If x and y have the same elements, then obviously we should 
> return 0,
>   since we'd like x <= y and x >= y to be true when x == y is 
> true.
>
> - If x and y are not subsets of each other, then what should we 
> return?
>   According to the original claim, it should also return 0, for
>   "incomparable".  However, this leads to problems:
>
>   - Since `x <= y` in D means `x.opCmp(y) <= 0`, this will 
> return TRUE
>     when x and y are incomparable.
>
>   - Similarly, `x >= y` in D means `x.opCmp(y) >= 0`, so it 
> will also
>     return TRUE when x and y are incomparable.
>
>   - Therefore, `x <= y` cannot distinguish between x being a 
> non-strict
>     subset of y vs. x and y being incomparable.  Similarly for 
> `x >= y`.
>
> So we have the counterintuitive semantics that <= and >= will 
> return true for non-comparable sets.
>
> There is no return value of opCmp for which both <= and >= will 
> be false, as we need it to be if we are to map <= to ⊆ and >= 
> to ⊇.

Just do what std.typecons.Proxy does and return float.nan for the 
incomparable case.


More information about the Digitalmars-d mailing list