Closed kentcb closed 3 years ago
Sorry if I don't understand - is the following not sufficient for your needs?
type Wrapper<'T when 'T : comparison> = {
Values: Set<'T>
}
There's no additional constraint if you do this.
@cartermp Thanks for the reply. No, it's not because my real scenario is more like this:
type IMyBaseType =
inherit IComparable
inherit ISomething
inherit ISomethingElse
type Wrapper<'T when 'T :> IMyBaseType> = {
Values: Set<'T>
}
I don't want to have to constrain to both IMyBaseType
and comparison
because I feel like I'm repeating myself as IMyBaseType
already inherits from IComparable
.
There are further requirements for a type to be comparison
that are not mentioned on that page. From section 5.2.10 of the spec:
The constraint type : comparison
is a comparison constraint. Such a constraint is met if all the
following conditions hold:
• If the type is a named type, then the type definition does not have, and is not inferred to have,
the NoComparison
attribute, and the type definition implements System.IComparable
or is an
array type or is System.IntPtr
or is System.UIntPtr
.
• If the type has comparison dependencies ty_1, ..., ty_n
, then each of these must satisfy ty_i : comparison
@DalekBaldwin Thanks, but which of those requirements is not satisfied in my example?
You can't guarantee the second bullet point will be satisfied for every type that could ever be created that implements IMyBaseType
, e.g. with the standard pattern for propagating equality
and comparison
constraints through generic types:
type MyGenericType<[EqualityConditionalOn; ComparisonConditionalOn] 'T> (value:'T) =
override this.Equals thatObj =
// uses Unchecked.equals
// ...
override this.GetHashCode () =
// uses Unchecked.hash
// ...
interface System.IComparable with
member this.CompareTo thatObj =
// uses Unchecked.compare
// ...
There are a number of fslang-suggestions issues along the lines making these constraints more flexible, but as it is currently defined, comparison
does not subsume IComparable
.
I'll close this, as it is indeed by design (@DalekBaldwin feel free to link through to the issues on fslang-suggestions)
The following does not compile:
It insists on a
comparison
constraint on'T
even though the documentation (and intuition) suggests that inheriting fromIComparable
is the same thing:It doesn't matter whether the constraint is for
IComparable
,IComparable<'T>
,IStructuralComparable
, or all of them.Expected behavior
The code should compile.
Actual behavior
Known workarounds
Map<'T>
and useHashSet<'T>
instead. This isn't really an acceptable workaround in my case, since it introduces mutability.