Is there any way to determine whether a given type parameter satisfies the F# comparison constraint through reflection?
I would suspect not, since the expression
typedefof<Set<_>>.MakeGenericType [| typeof<System.Type> |]
appears to yield no errors. Still, I would like to hear some authoritative opinion on this.
Quoting from Don Syme's thorough post on equality and comparison constraints:
The constraint type : comparison holds if:
The constraint 'T when 'T :> IComparable
can be encoded in CIL and reflected upon, whereas neither is true of 'T when 'T : comparison
.
Since the two constraints are not equivalent, marking comparable
types with the IComparable
constraint is a bit misleading since it would make it impossible to distinguish between the two using reflection.
There's a similar relationship between the equality
constraint and IEquatable<_>
.
EDIT
Jack's mention that the comparison
constraint could be encoded in F# metadata prompted me to look at the metadata reader in PowerPack. It can be used to detect the constraint:
open Microsoft.FSharp.Metadata
let setEntity = FSharpAssembly.FSharpLibrary.GetEntity("Microsoft.FSharp.Collections.FSharpSet`1")
for typeArg in setEntity.GenericParameters do
printfn "%s - comparison=%b"
typeArg.Name
(typeArg.Constraints |> Seq.exists (fun c -> c.IsComparisonConstraint))
Here's a contrived example that shows the disparity between implementing IComparable
and satisfying comparison
:
type A() =
interface IComparable with
member __.CompareTo(_) = 0
[<NoComparison>]
type B() =
inherit A()
type C<'T when 'T : comparison>() = class end
type D<'T when 'T :> IComparable>() = class end
let c = C<B>() //ERROR
let d = D<B>() //OK
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With