Checking if an F# generic parameter has an equality or comparison constraint

Viewed 76

Is it possible to determine at run-time if a generic parameter to a Type has one of the special F# constraints of equality or comparison? These constraints are documented here.

As a concrete example, given type X<'y when 'y: equality> = { Y: 'y }, how would I determine that 'y has the equality constraint in typedefof<X<_>>?

I've tried using a few of the reflection APIs like Type.GetGenericParameterConstraints and Type.GenericParameterAttributes but both are empty.

This question mentions that the F# PowerPack can be used like so:

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))

However, this library does not appear to support .NET core and has since been split up and can now be found here. The GitHub page mentions that "F# metadata reader is replaced by FSharp.Compiler.Service", but on a brief examination of FSharp.Compiler.Service this API appears to be much more complex to set up and use than the example above.

Is there a simple way to access these special constraints in F# 6 / .NET 6 using the reflection API or using some other metadata reader?

Currently I'm working around the issue by manually annotating the parameter using an attribute:

[<AttributeUsage(validOn = AttributeTargets.GenericParameter, AllowMultiple = false)>]
type ConstraintAttribute([<ParamArray>] constraints: string []) =
    inherit Attribute()
    member _.Constraints = constraints |> List.ofArray

type X<[<Constraint("equality")>] 'y when 'y: equality> = { Y: 'y }

typedefof<X<_>>.GetGenericArguments().[0].GetCustomAttributes<ConstraintAttribute>()

Obviously having to manually annotate is not ideal, though!

0 Answers
Related